diff --git a/README b/README
index 7c27e36..c2f9dc6 100644
--- a/README
+++ b/README
@@ -94,4 +94,7 @@ This web page gives detailed information on how to report bugs properly.
 
 The GNU C Library is free software.  See the file COPYING.LIB for copying
 conditions, and LICENSES for notices about a few contributions that require
-these additional notices to be distributed.
+these additional notices to be distributed. License copyright years may be
+listed using range notation e.g. 2000-2011, indicating that every year in
+the range, inclusive, is a copyrightable year that would otherwise be listed 
+individually.
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index c44ce2a..953e5ca 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,21 @@
+2011-08-31  Carlos O'Donell  <carlos@codesourcery.com>
+
+	* allocatestack.c (allocate_stack): Define
+	_STACK_GROWS_DOWN and _STACK_GROWS_UP cases for
+	user defined stacks. Adjust define indentation.
+	Remove assert for _STACK_GROWS_UP case.
+	* pthread_create.c: Update coprigyt year.
+	(start_thread): Implement _STACK_GROWS_UP case.
+	* pthread_attr_getstack.c: Update copyright year.
+	(__pthread_attr_getstack): Define _STACK_GROWS_UP
+	case.
+	* pthread_attr_setstack.c: Update copyright year.
+	(__pthread_attr_setstack): Define _STACK_GROWS_UP
+	case.
+	(__old_pthread_attr_setstack): Likewise.
+	* pthread_getattr_np: Update copyright year.
+	(pthread_getattr_np): Define _STACK_GROWS_UP cases.
+
 2011-08-31  Andreas Schwab  <schwab@redhat.com>
 
 	* allocatestack.c (setxid_mark_thread): Ensure that the exiting
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index 23d2ce5..0f98667 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -361,6 +361,15 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
   if (__builtin_expect (attr->flags & ATTR_FLAG_STACKADDR, 0))
     {
       uintptr_t adj;
+#if _STACK_GROWS_DOWN
+      char * stackaddr = (char *) attr->stackaddr;
+#else
+      /* Assume the same layout as the _STACK_GROWS_DOWN case, 
+	 with struct pthread at the top of the stack block. 
+	 Later we adjust the guard location and stack address 
+	 to match the _STACK_GROWS_UP case.  */
+      char * stackaddr = (char *) attr->stackaddr + attr->stacksize;
+#endif
 
       /* If the user also specified the size of the stack make sure it
 	 is large enough.  */
@@ -370,11 +379,11 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 
       /* Adjust stack size for alignment of the TLS block.  */
 #if TLS_TCB_AT_TP
-      adj = ((uintptr_t) attr->stackaddr - TLS_TCB_SIZE)
+      adj = ((uintptr_t) stackaddr - TLS_TCB_SIZE)
 	    & __static_tls_align_m1;
       assert (size > adj + TLS_TCB_SIZE);
 #elif TLS_DTV_AT_TP
-      adj = ((uintptr_t) attr->stackaddr - __static_tls_size)
+      adj = ((uintptr_t) stackaddr - __static_tls_size)
 	    & __static_tls_align_m1;
       assert (size > adj);
 #endif
@@ -384,10 +393,10 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 	 the stack.  It is the user's responsibility to do this if it
 	 is wanted.  */
 #if TLS_TCB_AT_TP
-      pd = (struct pthread *) ((uintptr_t) attr->stackaddr
+      pd = (struct pthread *) ((uintptr_t) stackaddr
 			       - TLS_TCB_SIZE - adj);
 #elif TLS_DTV_AT_TP
-      pd = (struct pthread *) (((uintptr_t) attr->stackaddr
+      pd = (struct pthread *) (((uintptr_t) stackaddr
 				- __static_tls_size - adj)
 			       - TLS_PRE_TCB_SIZE);
 #endif
@@ -399,7 +408,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
       pd->specific[0] = pd->specific_1stblock;
 
       /* Remember the stack-related values.  */
-      pd->stackblock = (char *) attr->stackaddr - size;
+      pd->stackblock = (char *) stackaddr - size;
       pd->stackblock_size = size;
 
       /* This is a user-provided stack.  It will not be queued in the
@@ -630,7 +639,7 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 	  char *guard = mem + (((size - guardsize) / 2) & ~pagesize_m1);
 #elif _STACK_GROWS_DOWN
 	  char *guard = mem;
-# elif _STACK_GROWS_UP
+#elif _STACK_GROWS_UP
 	  char *guard = (char *) (((uintptr_t) pd - guardsize) & ~pagesize_m1);
 #endif
 	  if (mprotect (guard, guardsize, PROT_NONE) != 0)
@@ -683,9 +692,13 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 			prot) != 0)
 	    goto mprot_error;
 #elif _STACK_GROWS_UP
-	  if (mprotect ((char *) pd - pd->guardsize,
-			pd->guardsize - guardsize, prot) != 0)
-	    goto mprot_error;
+	  char *new_guard = (char *) (((uintptr_t) pd - guardsize) & ~pagesize_m1);
+	  char *old_guard = (char *) (((uintptr_t) pd - pd->guardsize) & ~pagesize_m1);
+	  /* The guard size difference might be > 0, but once rounded
+	     to the nearest page the size difference might be zero.  */
+	  if (old_guard - new_guard > 0)
+	    if (mprotect (old_guard, new_guard - old_guard, prot) != 0)
+	      goto mprot_error;
 #endif
 
 	  pd->guardsize = guardsize;
@@ -728,8 +741,10 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
 #elif _STACK_GROWS_DOWN
   *stack = stacktop;
 #elif _STACK_GROWS_UP
+  /* We don't use stacktop. In _STACK_GROWS_UP the start
+     of the stack is simply stackblock (lowest address of
+     the stored block of memory for the stack).  */
   *stack = pd->stackblock;
-  assert (*stack > 0);
 #endif
 
   return 0;
diff --git a/nptl/pthread_attr_getstack.c b/nptl/pthread_attr_getstack.c
index 1db135e..792f5d5 100644
--- a/nptl/pthread_attr_getstack.c
+++ b/nptl/pthread_attr_getstack.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -33,7 +33,11 @@ __pthread_attr_getstack (attr, stackaddr, stacksize)
   iattr = (struct pthread_attr *) attr;
 
   /* Store the result.  */
+#ifdef _STACK_GROWS_DOWN
   *stackaddr = (char *) iattr->stackaddr - iattr->stacksize;
+#else
+  *stackaddr = (char *) iattr->stackaddr;
+#endif
   *stacksize = iattr->stacksize;
 
   return 0;
diff --git a/nptl/pthread_attr_setstack.c b/nptl/pthread_attr_setstack.c
index be79e32..a455a04 100644
--- a/nptl/pthread_attr_setstack.c
+++ b/nptl/pthread_attr_setstack.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2006, 2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -48,7 +48,11 @@ __pthread_attr_setstack (attr, stackaddr, stacksize)
 #endif
 
   iattr->stacksize = stacksize;
+#if _STACK_GROWS_DOWN
   iattr->stackaddr = (char *) stackaddr + stacksize;
+#else
+  iattr->stackaddr = (char *) stackaddr;
+#endif
   iattr->flags |= ATTR_FLAG_STACKADDR;
 
   return 0;
@@ -81,7 +85,11 @@ __old_pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
 #  endif
 
   iattr->stacksize = stacksize;
+#if _STACK_GROWS_DOWN
   iattr->stackaddr = (char *) stackaddr + stacksize;
+#else
+  iattr->stackaddr = (char *) stackaddr;
+#endif
   iattr->flags |= ATTR_FLAG_STACKADDR;
 
   return 0;
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index 34d83f9..886d186 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -387,12 +387,25 @@ start_thread (void *arg)
 #ifdef _STACK_GROWS_DOWN
   char *sp = CURRENT_STACK_FRAME;
   size_t freesize = (sp - (char *) pd->stackblock) & ~pagesize_m1;
-#else
-# error "to do"
-#endif
   assert (freesize < pd->stackblock_size);
   if (freesize > PTHREAD_STACK_MIN)
     madvise (pd->stackblock, freesize - PTHREAD_STACK_MIN, MADV_DONTNEED);
+#else
+  /* Page aligned start of memory to free (higher than or equal 
+     to current sp plus the minimum stack size).  */
+  void *freeblock = (void*)((size_t)(CURRENT_STACK_FRAME 
+				     + PTHREAD_STACK_MIN 
+				     + pagesize_m1) 
+				    & ~pagesize_m1);
+  char *free_end = (char *) (((uintptr_t) pd - pd->guardsize) & ~pagesize_m1);
+  /* Is there any space to free?  */
+  if (free_end > (char *)freeblock)
+    {
+      size_t freesize = (size_t)(free_end - (char *)freeblock);
+      assert (freesize < pd->stackblock_size);
+      madvise (freeblock, freesize, MADV_DONTNEED);
+    }
+#endif
 
   /* If the thread is detached free the TCB.  */
   if (IS_DETACHED (pd))
diff --git a/nptl/pthread_getattr_np.c b/nptl/pthread_getattr_np.c
index 9c25caf..80f0f3c 100644
--- a/nptl/pthread_getattr_np.c
+++ b/nptl/pthread_getattr_np.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2006, 2007, 
+   2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -61,7 +62,11 @@ pthread_getattr_np (thread_id, attr)
   if (__builtin_expect (thread->stackblock != NULL, 1))
     {
       iattr->stacksize = thread->stackblock_size;
+#ifdef _STACK_GROWS_DOWN
       iattr->stackaddr = (char *) thread->stackblock + iattr->stacksize;
+#else
+      iattr->stackaddr = (char *) thread->stackblock;
+#endif
     }
   else
     {
@@ -110,13 +115,21 @@ pthread_getattr_np (thread_id, attr)
 		    {
 		      /* Found the entry.  Now we have the info we need.  */
 		      iattr->stacksize = rl.rlim_cur;
+#ifdef _STACK_GROWS_DOWN
 		      iattr->stackaddr = (void *) to;
 
 		      /* The limit might be too high.  */
 		      if ((size_t) iattr->stacksize
 			  > (size_t) iattr->stackaddr - last_to)
 			iattr->stacksize = (size_t) iattr->stackaddr - last_to;
+#else
+		      iattr->stackaddr = (void *) from;
 
+		      /* The limit might be too high.  */
+		      if ((size_t) iattr->stacksize
+			  > to - (size_t) iattr->stackaddr)
+			iattr->stacksize = to - (size_t) iattr->stackaddr;
+#endif
 		      /* We succeed and no need to look further.  */
 		      ret = 0;
 		      break;
diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c
index 25029be..20a40a2 100644
--- a/nptl/pthread_mutex_trylock.c
+++ b/nptl/pthread_mutex_trylock.c
@@ -240,7 +240,8 @@ __pthread_mutex_trylock (mutex)
 							  private), 0, 0);
 
 	    if (INTERNAL_SYSCALL_ERROR_P (e, __err)
-		&& INTERNAL_SYSCALL_ERRNO (e, __err) == EWOULDBLOCK)
+		&& ((INTERNAL_SYSCALL_ERRNO (e, __err) == EWOULDBLOCK)
+		    || (INTERNAL_SYSCALL_ERRNO (e, __err) == EAGAIN)))
 	      {
 		THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
 
diff --git a/nptl/sysdeps/pthread/aio_misc.h b/nptl/sysdeps/pthread/aio_misc.h
index f36825e..edef3d4 100644
--- a/nptl/sysdeps/pthread/aio_misc.h
+++ b/nptl/sysdeps/pthread/aio_misc.h
@@ -51,7 +51,7 @@
 	  {								      \
 	    status = lll_futex_timed_wait (futexaddr, oldval, timeout,	      \
 					   LLL_PRIVATE);		      \
-	    if (status != -EWOULDBLOCK)					      \
+	    if (status != -EWOULDBLOCK && status != -EAGAIN)		      \
 	      break;							      \
 									      \
 	    oldval = *futexaddr;					      \
@@ -66,7 +66,7 @@
 	else if (status == -ETIMEDOUT)					      \
 	  result = EAGAIN;						      \
 	else								      \
-	  assert (status == 0 || status == -EWOULDBLOCK);		      \
+	  assert (status == 0 || status == -EWOULDBLOCK || status == -EAGAIN);\
 									      \
 	pthread_mutex_lock (&__aio_requests_mutex);			      \
       }									      \
diff --git a/nptl/sysdeps/pthread/gai_misc.h b/nptl/sysdeps/pthread/gai_misc.h
index 9094c1e..7591d93 100644
--- a/nptl/sysdeps/pthread/gai_misc.h
+++ b/nptl/sysdeps/pthread/gai_misc.h
@@ -52,7 +52,7 @@
 	  {								      \
 	    status = lll_futex_timed_wait (futexaddr, oldval, timeout,	      \
 					   LLL_PRIVATE);		      \
-	    if (status != -EWOULDBLOCK)					      \
+	    if (status != -EWOULDBLOCK && status != -EAGAIN)		      \
 	      break;							      \
 									      \
 	    oldval = *futexaddr;					      \
@@ -67,7 +67,7 @@
 	else if (status == -ETIMEDOUT)					      \
 	  result = EAGAIN;						      \
 	else								      \
-	  assert (status == 0 || status == -EWOULDBLOCK);		      \
+	  assert (status == 0 || status == -EWOULDBLOCK || status == -EAGAIN);\
 									      \
 	pthread_mutex_lock (&__gai_requests_mutex);			      \
       }									      \
diff --git a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
index fdf0d74..c4d8a6e 100644
--- a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c
@@ -90,7 +90,7 @@ sem_timedwait (sem_t *sem, const struct timespec *abstime)
       /* Disable asynchronous cancellation.  */
       __pthread_disable_asynccancel (oldtype);
 
-      if (err != 0 && err != -EWOULDBLOCK)
+      if (err != 0 && err != -EWOULDBLOCK && err != -EAGAIN)
 	{
 	  __set_errno (-err);
 	  err = -1;
diff --git a/nptl/sysdeps/unix/sysv/linux/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sem_wait.c
index 20e2b48..0c8070f 100644
--- a/nptl/sysdeps/unix/sysv/linux/sem_wait.c
+++ b/nptl/sysdeps/unix/sysv/linux/sem_wait.c
@@ -62,7 +62,7 @@ __new_sem_wait (sem_t *sem)
       /* Disable asynchronous cancellation.  */
       __pthread_disable_asynccancel (oldtype);
 
-      if (err != 0 && err != -EWOULDBLOCK)
+      if (err != 0 && err != -EWOULDBLOCK && err != -EAGAIN)
 	{
 	  __set_errno (-err);
 	  err = -1;
@@ -107,7 +107,7 @@ __old_sem_wait (sem_t *sem)
       /* Disable asynchronous cancellation.  */
       __pthread_disable_asynccancel (oldtype);
     }
-  while (err == 0 || err == -EWOULDBLOCK);
+  while (err == 0 || err == -EWOULDBLOCK || err == -EAGAIN);
 
   __set_errno (-err);
   return -1;

