diff --git a/ChangeLog b/ChangeLog
index 0fa7a55..506083a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2010-12-08  Carlos O'Donell  <carlos@codesourcery.com>
+
+	* elf/dl-fptr.c: Update copyright year.
+	(struct local): Don't initialize root when SHARED.
+	(_dl_fptr_init): New function.
+	* sysdeps/generic/dl-fptr.h: Update copyright year.
+	(_dl_fptr_init): New prototype. 
+	* sysdeps/ia64/dl-machine.h: Update copyright year.
+	(ELF_MACHINE_BEFORE_RTLD_RELOC): Call _dl_fptr_init.
+
 2010-12-03  Ulrich Drepper  <drepper@gmail.com>
 
 	* po/it.po: Update from translation team.
diff --git a/elf/dl-fptr.c b/elf/dl-fptr.c
index e068124..0853894 100644
--- a/elf/dl-fptr.c
+++ b/elf/dl-fptr.c
@@ -1,5 +1,5 @@
 /* Manage function descriptors.  Generic version.
-   Copyright (C) 1999-2004, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1999-2004, 2006, 2010 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -56,7 +56,12 @@ static struct local
   }
 local =
   {
+#ifndef SHARED
     .root = &local.boot_table,
+#else
+    /* Address of .boot_table is not known until runtime.  */
+    .root = 0,
+#endif
     .npages = 2,
     .boot_table =
       {
@@ -93,6 +98,17 @@ new_fdesc_table (struct local *l, size_t *size)
   return new_table;
 }
 
+/* Must call _dl_fptr_init before using any other function.  */
+void 
+_dl_fptr_init (void)
+{
+  struct local *l;
+
+  ELF_MACHINE_LOAD_ADDRESS (l, local);
+  /* Initialize root once.  */
+  if (__builtin_expect (l->root == 0, 0))
+    l->root = &l->boot_table;
+}
 
 static ElfW(Addr)
 make_fdesc (ElfW(Addr) ip, ElfW(Addr) gp)
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index e3bfd00..4f7ed37 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,21 @@
+2010-10-29  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.
+
 2010-10-13  H.J. Lu  <hongjiu.lu@intel.com>
 
 	[BZ #12113]
diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
index 831e98e..8512e7f 100644
--- a/nptl/allocatestack.c
+++ b/nptl/allocatestack.c
@@ -356,6 +356,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.  */
@@ -365,11 +374,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
@@ -379,10 +388,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
@@ -394,7 +403,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
@@ -625,7 +634,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)
@@ -724,7 +733,6 @@ allocate_stack (const struct pthread_attr *attr, struct pthread **pdp,
   *stack = stacktop;
 #elif _STACK_GROWS_UP
   *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..333020e 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -387,12 +387,18 @@ 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
+  char *sp = CURRENT_STACK_FRAME;
+  size_t freesize = ((char *) pd->stackblock + pd->stackblock_size - sp) 
+		     & ~pagesize_m1;
+  void *freeblock = (void *) (sp + PTHREAD_STACK_MIN);
+  assert (freesize < pd->stackblock_size);
+  if (freesize > PTHREAD_STACK_MIN)
+    madvise (freeblock, freesize - PTHREAD_STACK_MIN, 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;
diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c
index 6bb1ca3..4b5b392 100644
--- a/sunrpc/clnt_udp.c
+++ b/sunrpc/clnt_udp.c
@@ -456,7 +456,7 @@ send_again:
       while (inlen < 0 && errno == EINTR);
       if (inlen < 0)
 	{
-	  if (errno == EWOULDBLOCK)
+	  if (errno == EWOULDBLOCK || errno == EAGAIN)
 	    continue;
 	  cu->cu_error.re_errno = errno;
 	  return (cu->cu_error.re_status = RPC_CANTRECV);
diff --git a/sysdeps/generic/dl-fptr.h b/sysdeps/generic/dl-fptr.h
index d47fb7b..e7c09ea 100644
--- a/sysdeps/generic/dl-fptr.h
+++ b/sysdeps/generic/dl-fptr.h
@@ -1,5 +1,6 @@
 /* Function descriptors. Generic version.
-   Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 2000, 2001, 2010 Free Software Foundation, 
+   Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -40,6 +41,9 @@ struct link_map;
 
 extern ElfW(Addr) _dl_boot_fptr_table [];
 
+/* Initialize function pointer code. Call before relocation processing.  */
+extern void _dl_fptr_init (void);
+
 extern ElfW(Addr) _dl_make_fptr (struct link_map *, const ElfW(Sym) *,
 				 ElfW(Addr));
 
diff --git a/sysdeps/ia64/dl-machine.h b/sysdeps/ia64/dl-machine.h
index 61b4ea9..2d8eff3 100644
--- a/sysdeps/ia64/dl-machine.h
+++ b/sysdeps/ia64/dl-machine.h
@@ -1,5 +1,6 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  IA-64 version.
-   Copyright (C) 1995-1997, 2000-2004, 2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1995-1997, 2000-2004, 2005, 2006, 2010 
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -46,7 +47,8 @@ __ia64_init_bootstrap_fdesc_table (struct link_map *map)
 }
 
 #define ELF_MACHINE_BEFORE_RTLD_RELOC(dynamic_info)		\
-	__ia64_init_bootstrap_fdesc_table (&bootstrap_map);
+	__ia64_init_bootstrap_fdesc_table (&bootstrap_map);	\
+	_dl_fptr_init();
 
 /* Return nonzero iff ELF header is compatible with the running host.  */
 static inline int __attribute__ ((unused))

