summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2002-07-20 01:14:41 +0000
committerUlrich Drepper <drepper@redhat.com>2002-07-20 01:14:41 +0000
commit739d440d2a748be4b0139d4e5e0a566098abfcec (patch)
tree395d06a998290892d7d92568471adee8e1e4824f /sysdeps
parent9df63767d4078fdaf90307f5aa153422f7ec0722 (diff)
downloadglibc-739d440d2a748be4b0139d4e5e0a566098abfcec.tar.gz
glibc-739d440d2a748be4b0139d4e5e0a566098abfcec.tar.xz
glibc-739d440d2a748be4b0139d4e5e0a566098abfcec.zip
Update.
2002-07-19  Ulrich Drepper  <drepper@redhat.com>

	* configure.in: Add test for __thread support in compiler.
	* config.h.in: Add HAVE___THREAD.
	* Makefile (headers): Remove errno.h, sys/errno.h, and bits/errno.h.
	* include/sys/errno.h: Moved to...
	* stdlib/sys/errno.h: ...here.  New file.
	* stdlib/errno.h: New file.  Moved from...
	* include/errno.h: ...here.  Changed into an internal header defining
	libc-local things like __set_errno.
	* stdlib/Makefile (headers): Add errno.h, sys/errno.h, and
	bits/errno.h.
	* elf/dl-minimal.c: Include <tls.h>.  Define errno as thread-local
	variable if USE_TLS && HAVE___THREAD.  Don't define __errno_location
	either.
	* elf/rtld.c (_dl_start): Add code to initialize TLS for ld.so
	from...
	(_dl_start_final): ...here.  Add code to initialize tls elements from
	bootstrap_map.
	* sysdeps/generic/errno-loc.c: Define errno as thread-local variable
	if USE_TLS && HAVE___THREAD.
	* sysdeps/generic/bits/errno.h: Remove __set_errno definition.
	* sysdeps/mach/hurd/bits/errno.h: Likewise.
	* sysdeps/standalone/arm/bits/errno.h: Likewise.
	* sysdeps/standalone/bits/errno.h: Likewise.
	* sysdeps/unix/bsd/bsd4.4/bits/errno.h: Likewise.
	* sysdeps/unix/sysv/aix/bits/errno.h: Likewise.
	* sysdeps/unix/sysv/hpux/bits/errno.h: Likewise.
	* sysdeps/unix/sysv/linux/bits/errno.h: Likewise.
	* sysdeps/unix/sysv/linux/hppa/bits/errno.h: Likewise.
	* sysdeps/unix/sysv/linux/mips/bits/errno.h: Likewise.
	* sysdeps/unix/sysv/sysv4/solaris2/bits/errno.h: Likewise.
	* sysdeps/i386/dl-machine.c (elf_machine_rel) [RTLD_BOOTSTRAP]: Don't
	use GL(dl_rtld_map), use map parameter.
	* sysdeps/sh/dl-machine.h (elf_machine_rela): Likewise.
	* sysdeps/unix/sysv/linux/i386/sysdep.S: Define errno in .tbss if
	USE_TLS && HAVE___THREAD.
	* sysdeps/unix/sysv/linux/i386/sysdep.h: Unify SETUP_PIC_REG
	definitions.  If USE_TLS && HAVE___THREAD store errooor value using
	TLS code sequence.
	* sysdeps/unix/sysv/linux/i386/i686/sysdep.h: Likewise.

	* sysdeps/unix/sysv/linux/getcwd.c: No real need to restore errno.
	* sysdeps/unix/sysv/linux/grantpt.c: Likewise.
	* sysdeps/unix/sysv/linux/internal_statvfs.c: Likewise.
	* sysdeps/unix/sysv/linux/msgctl.c: Likewise.
	* sysdeps/unix/sysv/linux/readv.c: Likewise.
	* sysdeps/unix/sysv/linux/writev.c: Likewise.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/generic/bits/errno.h2
-rw-r--r--sysdeps/generic/errno-loc.c9
-rw-r--r--sysdeps/i386/dl-machine.h2
-rw-r--r--sysdeps/mach/hurd/bits/errno.h1
-rw-r--r--sysdeps/sh/dl-machine.h2
-rw-r--r--sysdeps/standalone/arm/bits/errno.h1
-rw-r--r--sysdeps/standalone/bits/errno.h2
-rw-r--r--sysdeps/unix/bsd/bsd4.4/bits/errno.h2
-rw-r--r--sysdeps/unix/sysv/aix/bits/errno.h4
-rw-r--r--sysdeps/unix/sysv/hpux/bits/errno.h2
-rw-r--r--sysdeps/unix/sysv/linux/bits/errno.h8
-rw-r--r--sysdeps/unix/sysv/linux/getcwd.c11
-rw-r--r--sysdeps/unix/sysv/linux/grantpt.c9
-rw-r--r--sysdeps/unix/sysv/linux/hppa/bits/errno.h8
-rw-r--r--sysdeps/unix/sysv/linux/i386/i686/sysdep.h72
-rw-r--r--sysdeps/unix/sysv/linux/i386/sysdep.S13
-rw-r--r--sysdeps/unix/sysv/linux/i386/sysdep.h72
-rw-r--r--sysdeps/unix/sysv/linux/internal_statvfs.c5
-rw-r--r--sysdeps/unix/sysv/linux/mips/bits/errno.h8
-rw-r--r--sysdeps/unix/sysv/linux/msgctl.c5
-rw-r--r--sysdeps/unix/sysv/linux/readv.c6
-rw-r--r--sysdeps/unix/sysv/linux/writev.c6
-rw-r--r--sysdeps/unix/sysv/sysv4/solaris2/bits/errno.h2
23 files changed, 97 insertions, 155 deletions
diff --git a/sysdeps/generic/bits/errno.h b/sysdeps/generic/bits/errno.h
index dbeef5de4f..89a5cfddeb 100644
--- a/sysdeps/generic/bits/errno.h
+++ b/sysdeps/generic/bits/errno.h
@@ -33,5 +33,3 @@
 # define Exxxx	XXX
 ...
 #endif
-
-#define __set_errno(val) errno = (val)
diff --git a/sysdeps/generic/errno-loc.c b/sysdeps/generic/errno-loc.c
index 44fedf41f0..bda9fa4211 100644
--- a/sysdeps/generic/errno-loc.c
+++ b/sysdeps/generic/errno-loc.c
@@ -1,6 +1,6 @@
 /* MT support function to get address of `errno' variable, non-threaded
    version.
-   Copyright (C) 1996, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1996, 1998, 2002 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
@@ -19,8 +19,15 @@
    02111-1307 USA.  */
 
 #include <errno.h>
+#include <tls.h>
 #undef errno
 
+#if USE_TLS && HAVE___THREAD
+extern __thread int errno;
+#else
+extern int errno;
+#endif
+
 int *
 weak_const_function
 __errno_location (void)
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 7dbb4ba903..f8b2a3cbd1 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -399,7 +399,7 @@ elf_machine_rel (struct link_map *map, const Elf32_Rel *reloc,
 	case R_386_TLS_TPOFF32:
 	  /* The offset is positive, backward from the thread pointer.  */
 # ifdef RTLD_BOOTSTRAP
-	  *reloc_addr = GL(dl_rtld_map).l_tls_offset - sym->st_value;
+	  *reloc_addr = map->l_tls_offset - sym->st_value;
 # else
 	  /* We know the offset of object the symbol is contained in.
 	     It is a positive value which will be subtracted from the
diff --git a/sysdeps/mach/hurd/bits/errno.h b/sysdeps/mach/hurd/bits/errno.h
index 78597af703..e5d208c8f5 100644
--- a/sysdeps/mach/hurd/bits/errno.h
+++ b/sysdeps/mach/hurd/bits/errno.h
@@ -310,7 +310,6 @@ typedef enum __error_t_codes error_t;
 extern int *__errno_location (void) __THROW __attribute__ ((__const__));
 
 #define errno			(*__errno_location ())
-#define __set_errno(val)	(errno = (val))
 
 #endif /* <errno.h> included.  */
 
diff --git a/sysdeps/sh/dl-machine.h b/sysdeps/sh/dl-machine.h
index 6ba7c42133..483b42f9f3 100644
--- a/sysdeps/sh/dl-machine.h
+++ b/sysdeps/sh/dl-machine.h
@@ -573,7 +573,7 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 	case R_SH_TLS_TPOFF32:
 	  /* The offset is positive, afterward from the thread pointer.  */
 # ifdef RTLD_BOOTSTRAP
-	  *reloc_addr = GL(dl_rtld_map).l_tls_offset + sym->st_value;
+	  *reloc_addr = map->l_tls_offset + sym->st_value;
 # else
 	  /* We know the offset of object the symbol is contained in.
 	     It is a positive value which will be added to the thread
diff --git a/sysdeps/standalone/arm/bits/errno.h b/sysdeps/standalone/arm/bits/errno.h
index 2700c17338..d7db91db89 100644
--- a/sysdeps/standalone/arm/bits/errno.h
+++ b/sysdeps/standalone/arm/bits/errno.h
@@ -60,7 +60,6 @@
 # define EOVERFLOW	32
 #endif
 
-#define __set_errno(val) errno = (val)
 
 /* Function to get address of global `errno' variable.  */
 extern int *__errno_location __P ((void)) __attribute__ ((__const__));
diff --git a/sysdeps/standalone/bits/errno.h b/sysdeps/standalone/bits/errno.h
index c7d3755a15..217c6d5d82 100644
--- a/sysdeps/standalone/bits/errno.h
+++ b/sysdeps/standalone/bits/errno.h
@@ -57,5 +57,3 @@
 # define ENOSPC 31
 # define EBUSY 32
 #endif
-
-#define __set_errno(val) errno = (val)
diff --git a/sysdeps/unix/bsd/bsd4.4/bits/errno.h b/sysdeps/unix/bsd/bsd4.4/bits/errno.h
index 816059e79b..48b1c8b6e6 100644
--- a/sysdeps/unix/bsd/bsd4.4/bits/errno.h
+++ b/sysdeps/unix/bsd/bsd4.4/bits/errno.h
@@ -161,6 +161,4 @@
 #endif /* __USE_BSD */
 
 
-#define __set_errno(val) errno = (val)
-
 #endif /* <errno.h> included.  */
diff --git a/sysdeps/unix/sysv/aix/bits/errno.h b/sysdeps/unix/sysv/aix/bits/errno.h
index f2cdba8d64..9f22a965e1 100644
--- a/sysdeps/unix/sysv/aix/bits/errno.h
+++ b/sysdeps/unix/sysv/aix/bits/errno.h
@@ -144,10 +144,6 @@
 # define EMULTIHOP	125	/* Multihop is not allowed.  */
 # define ENOLINK	126	/* The link has been severed.  */
 # define EOVERFLOW	127	/* Value too large to be stored in data type.*/
-
-# ifdef _LIBC
-#  define __set_errno(val) errno = (val)
-# endif
 #endif
 
 #if !defined _ERRNO_H && defined __need_Emath
diff --git a/sysdeps/unix/sysv/hpux/bits/errno.h b/sysdeps/unix/sysv/hpux/bits/errno.h
index acae4848f8..c9903c6dfe 100644
--- a/sysdeps/unix/sysv/hpux/bits/errno.h
+++ b/sysdeps/unix/sysv/hpux/bits/errno.h
@@ -32,5 +32,3 @@
 #define ENOMSG		35
 #define ENOSYS		251
 #endif
-
-#define __set_errno(val) errno = (val)
diff --git a/sysdeps/unix/sysv/linux/bits/errno.h b/sysdeps/unix/sysv/linux/bits/errno.h
index ac59d4c9dd..7307c2d6d9 100644
--- a/sysdeps/unix/sysv/linux/bits/errno.h
+++ b/sysdeps/unix/sysv/linux/bits/errno.h
@@ -32,17 +32,9 @@
 # define ECANCELED	125
 
 # ifndef __ASSEMBLER__
-/* We now need a declaration of the `errno' variable.  */
-extern int errno;
-
 /* Function to get address of global `errno' variable.  */
 extern int *__errno_location (void) __THROW __attribute__ ((__const__));
 
-#  if defined _LIBC
-/* We wouldn't need a special macro anymore but it is history.  */
-#   define __set_errno(val) (*__errno_location ()) = (val)
-#  endif /* _LIBC */
-
 #  if !defined _LIBC || defined _LIBC_REENTRANT
 /* When using threads, errno is a per-thread value.  */
 #   define errno (*__errno_location ())
diff --git a/sysdeps/unix/sysv/linux/getcwd.c b/sysdeps/unix/sysv/linux/getcwd.c
index fd8c634c63..7c27426f3c 100644
--- a/sysdeps/unix/sysv/linux/getcwd.c
+++ b/sysdeps/unix/sysv/linux/getcwd.c
@@ -1,5 +1,5 @@
 /* Determine current working directory.  Linux version.
-   Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -64,7 +64,6 @@ static int have_new_dcache = 1;
 char *
 __getcwd (char *buf, size_t size)
 {
-  int save_errno;
   char *path;
   int n;
   char *result;
@@ -93,8 +92,6 @@ __getcwd (char *buf, size_t size)
 	return NULL;
     }
 
-  save_errno = errno;
-
 #if defined __NR_getcwd || __LINUX_GETCWD_SYSCALL > 0
   if (!no_syscall_getcwd)
     {
@@ -137,8 +134,6 @@ __getcwd (char *buf, size_t size)
 	    free (path);
 	  return NULL;
 	}
-
-      __set_errno (save_errno);
 # endif
     }
 #endif
@@ -179,10 +174,6 @@ __getcwd (char *buf, size_t size)
     have_new_dcache = 0;
 #endif
 
-  /* Something went wrong.  Restore the error number and use the generic
-     version.  */
-  __set_errno (save_errno);
-
   /* Don't put restrictions on the length of the path unless the user does.  */
   if (size == 0)
     {
diff --git a/sysdeps/unix/sysv/linux/grantpt.c b/sysdeps/unix/sysv/linux/grantpt.c
index 168081758f..b894b8b631 100644
--- a/sysdeps/unix/sysv/linux/grantpt.c
+++ b/sysdeps/unix/sysv/linux/grantpt.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999, 2001, 2002 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,12 +56,13 @@ grantpt (int fd)
       if (__libc_fcntl (fd, F_GETFD) == -1 && errno == EBADF)
 	return -1;
 
-      __set_errno (save_errno);
-
        /* If the filedescriptor is no TTY, grantpt has to set errno
           to EINVAL.  */
-       if (errno == ENOTTY)
+       if (save_errno == ENOTTY)
          __set_errno (EINVAL);
+       else
+	 __set_errno (save_errno);
+
        return -1;
     }
 
diff --git a/sysdeps/unix/sysv/linux/hppa/bits/errno.h b/sysdeps/unix/sysv/linux/hppa/bits/errno.h
index 8b1fa44e98..4d75ff1f61 100644
--- a/sysdeps/unix/sysv/linux/hppa/bits/errno.h
+++ b/sysdeps/unix/sysv/linux/hppa/bits/errno.h
@@ -29,17 +29,9 @@
 # define ECANCELED	125
 
 # ifndef __ASSEMBLER__
-/* We now need a declaration of the `errno' variable.  */
-extern int errno;
-
 /* Function to get address of global `errno' variable.  */
 extern int *__errno_location (void) __THROW __attribute__ ((__const__));
 
-#  if defined _LIBC
-/* We wouldn't need a special macro anymore but it is history.  */
-#   define __set_errno(val) (*__errno_location ()) = (val)
-#  endif /* _LIBC */
-
 #  if !defined _LIBC || defined _LIBC_REENTRANT
 /* When using threads, errno is a per-thread value.  */
 #   define errno (*__errno_location ())
diff --git a/sysdeps/unix/sysv/linux/i386/i686/sysdep.h b/sysdeps/unix/sysv/linux/i386/i686/sysdep.h
index 6b54a81d32..1cd335ad7b 100644
--- a/sysdeps/unix/sysv/linux/i386/i686/sysdep.h
+++ b/sysdeps/unix/sysv/linux/i386/i686/sysdep.h
@@ -30,32 +30,44 @@
 #ifdef PIC
 # undef SYSCALL_ERROR_HANDLER
 
-/* Store (- %eax) into errno through the GOT.  */
-# ifdef _LIBC_REENTRANT
-
-#  ifndef HAVE_HIDDEN
-#   define SETUP_PIC_REG \
+# undef SETUP_PIC_REG
+# ifndef HAVE_HIDDEN
+#  define SETUP_PIC_REG(reg) \
   call 1f;								      \
   .subsection 1;							      \
-1:movl (%esp), %ebx;							      \
+1:movl (%esp), %e##reg;							      \
   ret;									      \
   .previous
-#  else
-#   define SETUP_PIC_REG \
-  .section .gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits;	      \
-  .globl __i686.get_pc_thunk.bx;					      \
-  .hidden __i686.get_pc_thunk.bx;					      \
-  .type __i686.get_pc_thunk.bx,@function;				      \
-__i686.get_pc_thunk.bx:							      \
-  movl (%esp), %ebx;							      \
+# else
+#  define SETUP_PIC_REG(reg) \
+  .section .gnu.linkonce.t.__i686.get_pc_thunk.reg,"ax",@progbits;	      \
+  .globl __i686.get_pc_thunk.reg;					      \
+  .hidden __i686.get_pc_thunk.reg;					      \
+  .type __i686.get_pc_thunk.reg,@function;				      \
+__i686.get_pc_thunk.reg:						      \
+  movl (%esp), %e##reg;							      \
   ret;									      \
   .previous;								      \
-  call __i686.get_pc_thunk.bx
-#  endif
+  call __i686.get_pc_thunk.reg
+# endif
 
-#  define SYSCALL_ERROR_HANDLER						      \
+/* Store (- %eax) into errno through the GOT.  */
+# ifdef _LIBC_REENTRANT
+#  if USE_TLS && HAVE___THREAD
+#   define SYSCALL_ERROR_HANDLER					      \
+0:SETUP_PIC_REG (cx);							      \
+  addl $_GLOBAL_OFFSET_TABLE_, %ecx;					      \
+  xorl %edx, %edx;							      \
+  subl %eax, %edx;							      \
+  movl %gs:0, %eax;							      \
+  subl errno@gottpoff(%ecx), %eax;					      \
+  movl %edx, (%eax);							      \
+  orl $-1, %eax;							      \
+  jmp L(pseudo_end);
+#  else
+#   define SYSCALL_ERROR_HANDLER					      \
 0:pushl %ebx;								      \
-  SETUP_PIC_REG;							      \
+  SETUP_PIC_REG(bx);							      \
   addl $_GLOBAL_OFFSET_TABLE_, %ebx;					      \
   xorl %edx, %edx;							      \
   subl %eax, %edx;							      \
@@ -70,30 +82,10 @@ __i686.get_pc_thunk.bx:							      \
   jmp L(pseudo_end);
 /* A quick note: it is assumed that the call to `__errno_location' does
    not modify the stack!  */
-# else
-
-#  ifndef HAVE_HIDDEN
-#   define SETUP_PIC_REG \
-  call 1f;								      \
-  .subsection 1;							      \
-1:movl (%esp), %ecx;							      \
-  ret;									      \
-  .previous
-#  else
-#   define SETUP_PIC_REG \
-  .section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits;	      \
-  .globl __i686.get_pc_thunk.cx;					      \
-  .hidden __i686.get_pc_thunk.cx;					      \
-  .type __i686.get_pc_thunk.cx,@function;				      \
-__i686.get_pc_thunk.cx:							      \
-  movl (%esp), %ecx;							      \
-  ret;									      \
-  .previous;								      \
-  call __i686.get_pc_thunk.cx
 #  endif
-
+# else
 #  define SYSCALL_ERROR_HANDLER						      \
-0:SETUP_PIC_REG;							      \
+0:SETUP_PIC_REG(cx);							      \
   addl $_GLOBAL_OFFSET_TABLE_, %ecx;					      \
   xorl %edx, %edx;							      \
   subl %eax, %edx;							      \
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.S b/sysdeps/unix/sysv/linux/i386/sysdep.S
index cd9f23a8cd..09428987ec 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.S
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1996, 1997, 1998, 2002 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
@@ -17,6 +17,7 @@
    02111-1307 USA.  */
 
 #include <sysdep.h>
+#include <tls.h>
 
 /* Because the Linux version is in fact i386/ELF and the start.? file
    for this system (sysdeps/i386/elf/start.S) is also used by The Hurd
@@ -25,13 +26,21 @@
    it somewhere else.
 
    ...and this place is here.  */
+#if USE_TLS && HAVE___THREAD
+	.section .tbss
+#else
 	.bss
+#endif
 	.globl	errno
 	.type errno,@object
 	.size errno,4
+	.globl	_errno
+	.type _errno,@object
+	.size _errno,4
+	.align 4
 errno:
+_errno:
 	.space	4
-weak_alias (errno, _errno)
 
 /* The following code is only used in the shared library when we
    compile the reentrant version.  Otherwise each system call defines
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h
index 730c4dfdf9..a6f18ec6f1 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.h
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.h
@@ -24,6 +24,7 @@
 #include <sysdeps/unix/i386/sysdep.h>
 #include <bp-sym.h>
 #include <bp-asm.h>
+#include <tls.h>
 
 /* For Linux we can use the system call table in the header file
 	/usr/include/asm/unistd.h
@@ -72,34 +73,47 @@
   END (name)
 
 #ifndef PIC
-#define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.S is used.  */
+# define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.S is used.  */
 #else
-/* Store (- %eax) into errno through the GOT.  */
-#ifdef _LIBC_REENTRANT
 
 # ifndef HAVE_HIDDEN
-#  define SETUP_PIC_REG \
+#  define SETUP_PIC_REG(reg) \
   call 1f;								      \
   .subsection 1;							      \
-1:movl (%esp), %ebx;							      \
+1:movl (%esp), %e##reg;							      \
   ret;									      \
   .previous
 # else
-#  define SETUP_PIC_REG \
-  .section .gnu.linkonce.t.__i686.get_pc_thunk.bx,"ax",@progbits;	      \
-  .globl __i686.get_pc_thunk.bx;					      \
-  .hidden __i686.get_pc_thunk.bx;					      \
-  .type __i686.get_pc_thunk.bx,@function;				      \
-__i686.get_pc_thunk.bx:							      \
-  movl (%esp), %ebx;							      \
+#  define SETUP_PIC_REG(reg) \
+  .section .gnu.linkonce.t.__i686.get_pc_thunk.reg,"ax",@progbits;	      \
+  .globl __i686.get_pc_thunk.reg;					      \
+  .hidden __i686.get_pc_thunk.reg;					      \
+  .type __i686.get_pc_thunk.reg,@function;				      \
+__i686.get_pc_thunk.reg:						      \
+  movl (%esp), %e##reg;							      \
   ret;									      \
   .previous;								      \
-  call __i686.get_pc_thunk.bx
+  call __i686.get_pc_thunk.reg
 # endif
 
-#define SYSCALL_ERROR_HANDLER						      \
+/* Store (- %eax) into errno through the GOT.  */
+# ifdef _LIBC_REENTRANT
+
+#  if USE_TLS && HAVE___THREAD
+#   define SYSCALL_ERROR_HANDLER					      \
+0:SETUP_PIC_REG (cx);							      \
+  addl $_GLOBAL_OFFSET_TABLE_, %ecx;					      \
+  xorl %edx, %edx;							      \
+  subl %eax, %edx;							      \
+  movl %gs:0, %eax;							      \
+  subl errno@gottpoff(%ecx), %eax;					      \
+  movl %edx, (%eax);							      \
+  orl $-1, %eax;							      \
+  jmp L(pseudo_end);
+#  else
+#   define SYSCALL_ERROR_HANDLER					      \
 0:pushl %ebx;								      \
-  SETUP_PIC_REG;							      \
+  SETUP_PIC_REG (bx);							      \
   addl $_GLOBAL_OFFSET_TABLE_, %ebx;					      \
   xorl %edx, %edx;							      \
   subl %eax, %edx;							      \
@@ -114,30 +128,10 @@ __i686.get_pc_thunk.bx:							      \
   jmp L(pseudo_end);
 /* A quick note: it is assumed that the call to `__errno_location' does
    not modify the stack!  */
-#else
-
-# ifndef HAVE_HIDDEN
-#  define SETUP_PIC_REG \
-  call 1f;								      \
-  .subsection 1;							      \
-1:movl (%esp), %ecx;							      \
-  ret;									      \
-  .previous
+#  endif
 # else
-#  define SETUP_PIC_REG \
-  .section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits;	      \
-  .globl __i686.get_pc_thunk.cx;					      \
-  .hidden __i686.get_pc_thunk.cx;					      \
-  .type __i686.get_pc_thunk.cx,@function;				      \
-__i686.get_pc_thunk.cx:							      \
-  movl (%esp), %ecx;							      \
-  ret;									      \
-  .previous;								      \
-  call __i686.get_pc_thunk.cx
-# endif
-
-#define SYSCALL_ERROR_HANDLER						      \
-0:define SETUP_PIC_REG;							      \
+#  define SYSCALL_ERROR_HANDLER						      \
+0:define SETUP_PIC_REG(cx);						      \
   addl $_GLOBAL_OFFSET_TABLE_, %ecx;					      \
   xorl %edx, %edx;							      \
   subl %eax, %edx;							      \
@@ -145,7 +139,7 @@ __i686.get_pc_thunk.cx:							      \
   movl %edx, (%ecx);							      \
   orl $-1, %eax;							      \
   jmp L(pseudo_end);
-#endif	/* _LIBC_REENTRANT */
+# endif	/* _LIBC_REENTRANT */
 #endif	/* PIC */
 
 /* Linux takes system call arguments in registers:
diff --git a/sysdeps/unix/sysv/linux/internal_statvfs.c b/sysdeps/unix/sysv/linux/internal_statvfs.c
index f78642b59f..ed9dbaaa0e 100644
--- a/sysdeps/unix/sysv/linux/internal_statvfs.c
+++ b/sysdeps/unix/sysv/linux/internal_statvfs.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
 
@@ -53,7 +53,6 @@
   buf->f_flag = 0;
   if (STAT (&st) >= 0)
     {
-      int save_errno = errno;
       struct mntent mntbuf;
       FILE *mtab;
 
@@ -104,6 +103,4 @@
 	  /* Close the file.  */
 	  __endmntent (mtab);
 	}
-
-      __set_errno (save_errno);
     }
diff --git a/sysdeps/unix/sysv/linux/mips/bits/errno.h b/sysdeps/unix/sysv/linux/mips/bits/errno.h
index 29ba9807a5..8220c2e513 100644
--- a/sysdeps/unix/sysv/linux/mips/bits/errno.h
+++ b/sysdeps/unix/sysv/linux/mips/bits/errno.h
@@ -28,17 +28,9 @@
 # define ENOTSUP EOPNOTSUPP
 
 # ifndef __ASSEMBLER__
-/* We now need a declaration of the `errno' variable.  */
-extern int errno;
-
 /* Function to get address of global `errno' variable.  */
 extern int *__errno_location (void) __THROW __attribute__ ((__const__));
 
-#  if defined _LIBC
-/* We wouldn't need a special macro anymore but it is history.  */
-#   define __set_errno(val) (*__errno_location ()) = (val)
-#  endif /* _LIBC */
-
 #  if !defined _LIBC || defined _LIBC_REENTRANT
 /* When using threads, errno is a per-thread value.  */
 #   define errno (*__errno_location ())
diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c
index 6a1be827e8..24c87d3ad9 100644
--- a/sysdeps/unix/sysv/linux/msgctl.c
+++ b/sysdeps/unix/sysv/linux/msgctl.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1995, 1997, 1998, 2000 Free Software Foundation, Inc.
+/* Copyright (C) 1995, 1997, 1998, 2000, 2002 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
 
@@ -80,7 +80,7 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf)
   }
 
   {
-    int save_errno = errno, result;
+    int result;
     struct __old_msqid_ds old;
 
     /* Unfortunately there is no way how to find out for sure whether
@@ -90,7 +90,6 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf)
     if (result != -1 || errno != EINVAL)
       return result;
 
-    __set_errno(save_errno);
     if (cmd == IPC_SET)
       {
 	old.msg_perm.uid = buf->msg_perm.uid;
diff --git a/sysdeps/unix/sysv/linux/readv.c b/sysdeps/unix/sysv/linux/readv.c
index 7a8fc54e03..601afc09e5 100644
--- a/sysdeps/unix/sysv/linux/readv.c
+++ b/sysdeps/unix/sysv/linux/readv.c
@@ -1,5 +1,5 @@
 /* readv supports all Linux kernels >= 2.0.
-   Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 2000, 2002 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
@@ -45,7 +45,6 @@ __readv (fd, vector, count)
      const struct iovec *vector;
      int count;
 {
-  int errno_saved = errno;
   ssize_t bytes_read;
 
   bytes_read = INLINE_SYSCALL (readv, 3, fd, CHECK_N (vector, count), count);
@@ -53,9 +52,6 @@ __readv (fd, vector, count)
   if (bytes_read >= 0 || errno != EINVAL || count <= UIO_FASTIOV)
     return bytes_read;
 
-  /* Restore the old error value as if nothing happened.  */
-  __set_errno (errno_saved);
-
   return __atomic_readv_replacement (fd, vector, count);
 }
 weak_alias (__readv, readv)
diff --git a/sysdeps/unix/sysv/linux/writev.c b/sysdeps/unix/sysv/linux/writev.c
index f0064543c0..729fd9aca5 100644
--- a/sysdeps/unix/sysv/linux/writev.c
+++ b/sysdeps/unix/sysv/linux/writev.c
@@ -1,5 +1,5 @@
 /* writev supports all Linux kernels >= 2.0.
-   Copyright (C) 1997, 1998, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 2000, 2002 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
@@ -45,7 +45,6 @@ __writev (fd, vector, count)
      const struct iovec *vector;
      int count;
 {
-  int errno_saved = errno;
   ssize_t bytes_written;
 
   bytes_written = INLINE_SYSCALL (writev, 3, fd, CHECK_N (vector, count), count);
@@ -53,9 +52,6 @@ __writev (fd, vector, count)
   if (bytes_written >= 0 || errno != EINVAL || count <= UIO_FASTIOV)
     return bytes_written;
 
-  /* Restore the old error value as if nothing happened.  */
-  __set_errno (errno_saved);
-
   return __atomic_writev_replacement (fd, vector, count);
 }
 weak_alias (__writev, writev)
diff --git a/sysdeps/unix/sysv/sysv4/solaris2/bits/errno.h b/sysdeps/unix/sysv/sysv4/solaris2/bits/errno.h
index 8d5d49e42b..6c0de92151 100644
--- a/sysdeps/unix/sysv/sysv4/solaris2/bits/errno.h
+++ b/sysdeps/unix/sysv/sysv4/solaris2/bits/errno.h
@@ -166,5 +166,3 @@
 # define ESTALE		151     /* Stale NFS file handle.  */
 
 #endif
-
-#define __set_errno(val) errno = (val)