diff options
41 files changed, 447 insertions, 350 deletions
@@ -1,3 +1,52 @@ +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. + 2002-07-17 Ulrich Drepper <drepper@redhat.com> * sysdeps/unix/sysv/linux/ia64/bits/mman.h: Fix MS_SYNC and @@ -63,9 +63,8 @@ configure: configure.in aclocal.m4; $(autoconf-it) subdir_testclean \ $(addprefix install-, no-libc.a bin lib data headers others) -headers := errno.h sys/errno.h bits/errno.h limits.h values.h \ - features.h gnu-versions.h bits/libc-lock.h bits/xopen_lim.h \ - gnu/libc-version.h +headers := limits.h values.h features.h gnu-versions.h bits/libc-lock.h \ + bits/xopen_lim.h gnu/libc-version.h echo-headers: subdir_echo-headers diff --git a/bits/errno.h b/bits/errno.h index dbeef5de4f..89a5cfddeb 100644 --- a/bits/errno.h +++ b/bits/errno.h @@ -33,5 +33,3 @@ # define Exxxx XXX ... #endif - -#define __set_errno(val) errno = (val) diff --git a/config.h.in b/config.h.in index b3dd601f3b..cf4835cbec 100644 --- a/config.h.in +++ b/config.h.in @@ -94,6 +94,9 @@ /* Define if the compiler supports __builtin_memset. */ #undef HAVE_BUILTIN_MEMSET +/* Define if the __thread keyword is supported. */ +#undef HAVE___THREAD + /* Define if the regparm attribute shall be used for local functions (gcc on ix86 only). */ #undef USE_REGPARMS @@ -3540,8 +3540,33 @@ EOF fi +echo $ac_n "checking for __thread""... $ac_c" 1>&6 +echo "configure:3545: checking for __thread" >&5 +if eval "test \"`echo '$''{'libc_cv_gcc___thread'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.c <<EOF +__thread int a = 42; +EOF +if { ac_try='${CC-cc} $CFLAGS -c conftest.c >&5'; { (eval echo configure:3552: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; }; then + libc_cv_gcc___thread=yes +else + libc_cv_gcc___thread=no +fi +rm -f conftest* +fi + +echo "$ac_t""$libc_cv_gcc___thread" 1>&6 +if test "$libc_cv_gcc___thread" = yes; then + cat >> confdefs.h <<\EOF +#define HAVE___THREAD 1 +EOF + +fi + + echo $ac_n "checking for libgd""... $ac_c" 1>&6 -echo "configure:3545: checking for libgd" >&5 +echo "configure:3570: checking for libgd" >&5 if test "$with_gd" != "no"; then old_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $libgd_include" @@ -3550,14 +3575,14 @@ if test "$with_gd" != "no"; then old_LIBS="$LIBS" LIBS="$LIBS -lgd -lpng -lz -lm" cat > conftest.$ac_ext <<EOF -#line 3554 "configure" +#line 3579 "configure" #include "confdefs.h" #include <gd.h> int main() { gdImagePng (0, 0) ; return 0; } EOF -if { (eval echo configure:3561: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3586: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* LIBGD=yes else @@ -3577,7 +3602,7 @@ echo "$ac_t""$LIBGD" 1>&6 echo $ac_n "checking size of long double""... $ac_c" 1>&6 -echo "configure:3581: checking size of long double" >&5 +echo "configure:3606: checking size of long double" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long_double'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3585,7 +3610,7 @@ else ac_cv_sizeof_long_double=0 else cat > conftest.$ac_ext <<EOF -#line 3589 "configure" +#line 3614 "configure" #include "confdefs.h" #include <stdio.h> int main() @@ -3596,7 +3621,7 @@ int main() return(0); } EOF -if { (eval echo configure:3600: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3625: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_long_double=`cat conftestval` else @@ -3674,7 +3699,7 @@ if test "$uname" = "sysdeps/generic"; then fi echo $ac_n "checking OS release for uname""... $ac_c" 1>&6 -echo "configure:3678: checking OS release for uname" >&5 +echo "configure:3703: checking OS release for uname" >&5 if eval "test \"`echo '$''{'libc_cv_uname_release'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3696,7 +3721,7 @@ echo "$ac_t""$libc_cv_uname_release" 1>&6 uname_release="$libc_cv_uname_release" echo $ac_n "checking OS version for uname""... $ac_c" 1>&6 -echo "configure:3700: checking OS version for uname" >&5 +echo "configure:3725: checking OS version for uname" >&5 if eval "test \"`echo '$''{'libc_cv_uname_version'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -3725,7 +3750,7 @@ EOF # Test for old glibc 2.0.x headers so that they can be removed properly # Search only in includedir. echo $ac_n "checking for old glibc 2.0.x headers""... $ac_c" 1>&6 -echo "configure:3729: checking for old glibc 2.0.x headers" >&5 +echo "configure:3754: checking for old glibc 2.0.x headers" >&5 if eval test -f "${includedir}/elfclass.h" -a -f "${includedir}/fcntlbits.h" then old_glibc_headers=yes @@ -3786,7 +3811,7 @@ if test $shared = default; then fi echo $ac_n "checking whether -fPIC is default""... $ac_c" 1>&6 -echo "configure:3790: checking whether -fPIC is default" >&5 +echo "configure:3815: checking whether -fPIC is default" >&5 if eval "test \"`echo '$''{'pic_default'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else diff --git a/configure.in b/configure.in index 61a13cd147..f120ef41aa 100644 --- a/configure.in +++ b/configure.in @@ -1513,6 +1513,22 @@ if test "$libc_cv_gcc_subtract_local_labels" = yes; then AC_DEFINE(HAVE_SUBTRACT_LOCAL_LABELS) fi +dnl Check whether the compiler supports the __thread keyword. +AC_CACHE_CHECK([for __thread], libc_cv_gcc___thread, +[cat > conftest.c <<EOF +__thread int a = 42; +EOF +if AC_TRY_COMMAND([${CC-cc} $CFLAGS -c conftest.c >&AC_FD_CC]); then + libc_cv_gcc___thread=yes +else + libc_cv_gcc___thread=no +fi +rm -f conftest*]) +if test "$libc_cv_gcc___thread" = yes; then + AC_DEFINE(HAVE___THREAD) +fi + + dnl Check whether we have the gd library available. AC_MSG_CHECKING(for libgd) if test "$with_gd" != "no"; then diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c index 0f284d0a80..a6c1803b34 100644 --- a/elf/dl-minimal.c +++ b/elf/dl-minimal.c @@ -20,6 +20,7 @@ #include <errno.h> #include <limits.h> #include <string.h> +#include <tls.h> #include <unistd.h> #include <sys/mman.h> #include <sys/param.h> @@ -354,8 +355,12 @@ const char INTUSE(_itoa_lower_digits)[16] attribute_hidden = "0123456789abcdef"; + #undef errno /* The 'errno' in ld.so is not exported. */ +#if USE_TLS && HAVE___THREAD +extern __thread int errno attribute_hidden; +#else extern int errno attribute_hidden; int * @@ -363,3 +368,4 @@ __errno_location (void) { return &errno; } +#endif diff --git a/elf/rtld.c b/elf/rtld.c index 9ec250214b..85d8108813 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -130,9 +130,14 @@ _dl_start (void *arg) { struct link_map bootstrap_map; hp_timing_t start_time; -#ifndef HAVE_BUILTIN_MEMSET +#if !defined HAVE_BUILTIN_MEMSET || defined USE_TLS size_t cnt; #endif +#ifdef USE_TLS + ElfW(Ehdr) *ehdr; + ElfW(Phdr) *phdr; + dtv_t initdtv[3]; +#endif /* This #define produces dynamic linking inline functions for bootstrap relocation instead of general-purpose relocation. */ @@ -166,6 +171,97 @@ _dl_start (void *arg) bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic (); elf_get_dynamic_info (&bootstrap_map); +#if USE_TLS +# ifndef HAVE___THREAD + /* Signal that we have not found TLS data so far. */ + bootstrap_map.l_tls_modid = 0; +# endif + + /* Get the dynamic linkers program header. */ + ehdr = (ElfW(Ehdr) *) bootstrap_map.l_addr; + phdr = (ElfW(Phdr) *) (bootstrap_map.l_addr + ehdr->e_phoff); + for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) + if (phdr[cnt].p_type == PT_TLS) + { + void *tlsblock; + size_t max_align = MAX (TLS_INIT_TCB_ALIGN, phdr[cnt].p_align); + + bootstrap_map.l_tls_blocksize = phdr[cnt].p_memsz; + bootstrap_map.l_tls_align = phdr[cnt].p_align; + assert (bootstrap_map.l_tls_blocksize != 0); + bootstrap_map.l_tls_initimage_size = phdr[cnt].p_filesz; + bootstrap_map.l_tls_initimage = (void *) (bootstrap_map.l_addr + + phdr[cnt].p_offset); + + /* We can now allocate the initial TLS block. This can happen + on the stack. We'll get the final memory later when we + know all about the various objects loaded at startup + time. */ +# if TLS_TCB_AT_TP + tlsblock = alloca (roundup (bootstrap_map.l_tls_blocksize, + TLS_INIT_TCB_ALIGN) + + TLS_INIT_TCB_SIZE + + max_align); +# elif TLS_DTV_AT_TP + tlsblock = alloca (roundup (TLS_INIT_TCB_SIZE, + bootstrap_map.l_tls_align) + + bootstrap_map.l_tls_blocksize + + max_align); +# else + /* In case a model with a different layout for the TCB and DTV + is defined add another #elif here and in the following #ifs. */ +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + /* Align the TLS block. */ + tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1) + & ~(max_align - 1)); + + /* Initialize the dtv. [0] is the length, [1] the generation + counter. */ + initdtv[0].counter = 1; + initdtv[1].counter = 0; + + /* Initialize the TLS block. */ +# if TLS_TCB_AT_TP + initdtv[2].pointer = tlsblock; +# elif TLS_DTV_AT_TP + bootstrap_map.l_tls_offset = roundup (TLS_INIT_TCB_SIZE, + bootstrap_map.l_tls_align); + initdtv[2].pointer = (char *) tlsblock + bootstrap_map.l_tls_offset; +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + memset (__mempcpy (initdtv[2].pointer, bootstrap_map.l_tls_initimage, + bootstrap_map.l_tls_initimage_size), + '\0', (bootstrap_map.l_tls_blocksize + - bootstrap_map.l_tls_initimage_size)); + + /* Install the pointer to the dtv. */ + + /* Initialize the thread pointer. */ +# if TLS_TCB_AT_TP + bootstrap_map.l_tls_offset + = roundup (bootstrap_map.l_tls_blocksize, TLS_INIT_TCB_ALIGN); + + INSTALL_DTV ((char *) tlsblock + bootstrap_map.l_tls_offset, + initdtv); + + TLS_INIT_TP ((char *) tlsblock + bootstrap_map.l_tls_offset); +# elif TLS_DTV_AT_TP + INSTALL_DTV (tlsblock, initdtv); + TLS_INIT_TP (tlsblock); +# else +# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" +# endif + + /* So far this is module number one. */ + bootstrap_map.l_tls_modid = 1; + + /* There can only be one PT_TLS entry. */ + break; + } +#endif /* use TLS */ + #ifdef ELF_MACHINE_BEFORE_RTLD_RELOC ELF_MACHINE_BEFORE_RTLD_RELOC (bootstrap_map.l_info); #endif @@ -220,12 +316,6 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p, ElfW(Addr) *start_addr = alloca (sizeof (ElfW(Addr))); extern char _begin[] attribute_hidden; extern char _end[] attribute_hidden; -#ifdef USE_TLS - ElfW(Ehdr) *ehdr; - ElfW(Phdr) *phdr; - size_t cnt; - dtv_t initdtv[3]; -#endif if (HP_TIMING_AVAIL) { @@ -247,96 +337,27 @@ _dl_start_final (void *arg, struct link_map *bootstrap_map_p, GL(dl_rtld_map).l_mach = bootstrap_map_p->l_mach; GL(dl_rtld_map).l_map_start = (ElfW(Addr)) _begin; GL(dl_rtld_map).l_map_end = (ElfW(Addr)) _end; - -#if HP_TIMING_AVAIL - HP_TIMING_NOW (GL(dl_cpuclock_offset)); -#endif - + /* Copy the TLS related data if necessary. */ #if USE_TLS - /* Get the dynamic linkers program header. */ - ehdr = (ElfW(Ehdr) *) GL(dl_rtld_map).l_map_start; - phdr = (ElfW(Phdr) *) (GL(dl_rtld_map).l_map_start + ehdr->e_phoff); - for (cnt = 0; cnt < ehdr->e_phnum; ++cnt) - if (phdr[cnt].p_type == PT_TLS) - { - void *tlsblock; - size_t max_align = MAX (TLS_INIT_TCB_ALIGN, phdr[cnt].p_align); - - GL(dl_rtld_map).l_tls_blocksize = phdr[cnt].p_memsz; - GL(dl_rtld_map).l_tls_align = phdr[cnt].p_align; - assert (GL(dl_rtld_map).l_tls_blocksize != 0); - GL(dl_rtld_map).l_tls_initimage_size = phdr[cnt].p_filesz; - GL(dl_rtld_map).l_tls_initimage = (void *) (GL(dl_rtld_map).l_map_start - + phdr[cnt].p_offset); - - /* We can now allocate the initial TLS block. This can happen - on the stack. We'll get the final memory later when we - know all about the various objects loaded at startup - time. */ -# if TLS_TCB_AT_TP - tlsblock = alloca (roundup (GL(dl_rtld_map).l_tls_blocksize, - TLS_INIT_TCB_ALIGN) - + TLS_INIT_TCB_SIZE - + max_align); -# elif TLS_DTV_AT_TP - tlsblock = alloca (roundup (TLS_INIT_TCB_SIZE, - GL(dl_rtld_map).l_tls_align) - + GL(dl_rtld_map).l_tls_blocksize - + max_align); -# else - /* In case a model with a different layout for the TCB and DTV - is defined add another #elif here and in the following #ifs. */ -# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" -# endif - /* Align the TLS block. */ - tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1) - & ~(max_align - 1)); - - /* Initialize the dtv. [0] is the length, [1] the generation - counter. */ - initdtv[0].counter = 1; - initdtv[1].counter = 0; - - /* Initialize the TLS block. */ -# if TLS_TCB_AT_TP - initdtv[2].pointer = tlsblock; -# elif TLS_DTV_AT_TP - GL(dl_rtld_map).l_tls_offset = roundup (TLS_INIT_TCB_SIZE, - GL(dl_rtld_map).l_tls_align); - initdtv[2].pointer = (char *) tlsblock + GL(dl_rtld_map).l_tls_offset; -# else -# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" -# endif - memset (__mempcpy (initdtv[1].pointer, GL(dl_rtld_map).l_tls_initimage, - GL(dl_rtld_map).l_tls_initimage_size), - '\0', (GL(dl_rtld_map).l_tls_blocksize - - GL(dl_rtld_map).l_tls_initimage_size)); - - /* Install the pointer to the dtv. */ - - /* Initialize the thread pointer. */ -# if TLS_TCB_AT_TP - GL(dl_rtld_map).l_tls_offset - = roundup (GL(dl_rtld_map).l_tls_blocksize, TLS_INIT_TCB_ALIGN); - - INSTALL_DTV ((char *) tlsblock + GL(dl_rtld_map).l_tls_offset, - initdtv); - - TLS_INIT_TP ((char *) tlsblock + GL(dl_rtld_map).l_tls_offset); -# elif TLS_DTV_AT_TP - INSTALL_DTV (tlsblock, initdtv); - TLS_INIT_TP (tlsblock); +# ifdef HAVE___THREAD + assert (bootstrap_map_p->l_tls_modid != 0); # else -# error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" + if (bootstrap_map_p->l_tls_modid != 0) # endif + { + GL(dl_rtld_map).l_tls_blocksize = bootstrap_map_p->l_tls_blocksize; + GL(dl_rtld_map).l_tls_align = bootstrap_map_p->l_tls_align; + GL(dl_rtld_map).l_tls_initimage_size + = bootstrap_map_p->l_tls_initimage_size; + GL(dl_rtld_map).l_tls_initimage = bootstrap_map_p->l_tls_initimage; + GL(dl_rtld_map).l_tls_offset = bootstrap_map_p->l_tls_offset; + GL(dl_rtld_map).l_tls_modid = 1; + } +#endif - /* So far this is module number one. */ - GL(dl_rtld_map).l_tls_modid = 1; - - /* There can only be one PT_TLS entry. */ - break; - } -#endif /* use TLS */ +#if HP_TIMING_AVAIL + HP_TIMING_NOW (GL(dl_cpuclock_offset)); +#endif /* Call the OS-dependent function to set up life so we can do things like file access. It will call `dl_main' (below) to do all the real work diff --git a/include/errno.h b/include/errno.h index 645a439db7..35f705100e 100644 --- a/include/errno.h +++ b/include/errno.h @@ -1,73 +1,13 @@ -/* Copyright (C) 1991, 92, 93, 94, 95, 96, 97 Free Software Foundation, Inc. - This file is part of the GNU C Library. +#include <stdlib/errno.h> - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. +#ifdef _ERRNO_H - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* - * ISO C99 Standard: 7.5 Errors <errno.h> - */ - -#ifndef _ERRNO_H - -/* The includer defined __need_Emath if he wants only the definitions - of EDOM and ERANGE, and not everything else. */ -#ifndef __need_Emath -#define _ERRNO_H 1 -#include <features.h> +#if USE_TLS && HAVE___THREAD +# undef errno +extern __thread int errno; +# define __set_errno(val) (errno = (val)) +#else +# define __set_errno(val) (*__errno_location ()) = (val) #endif -__BEGIN_DECLS - -/* Get the error number constants from the system-specific file. - This file will test __need_Emath and _ERRNO_H. */ -#include <bits/errno.h> -#undef __need_Emath - -#ifdef _ERRNO_H - -/* Declare the `errno' variable, unless it's defined as a macro by - bits/errno.h. This is the case in GNU, where it is a per-thread - variable. This redeclaration using the macro still works, but it - will be a function declaration without a prototype and may trigger - a -Wstrict-prototypes warning. */ -#ifndef errno -extern int errno; -#endif - -#ifdef __USE_GNU - -/* The full and simple forms of the name with which the program was - invoked. These variables are set up automatically at startup based on - the value of ARGV[0] (this works only if you use GNU ld). */ -extern char *program_invocation_name, *program_invocation_short_name; -#endif /* __USE_GNU */ -#endif /* _ERRNO_H */ - -__END_DECLS - -#endif /* _ERRNO_H */ - -/* The Hurd <bits/errno.h> defines `error_t' as an enumerated type so - that printing `error_t' values in the debugger shows the names. We - might need this definition sometimes even if this file was included - before. */ -#if defined __USE_GNU || defined __need_error_t -# ifndef __error_t_defined -typedef int error_t; -# define __error_t_defined 1 -# endif -# undef __need_error_t #endif diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index e70be81c13..7d4cc40832 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,12 @@ +2002-07-19 Ulrich Drepper <drepper@redhat.com> + + * errno.c (__errno_location): Don't define unless !USE_TLS + || !HAVE___THREAD. + * sysdeps/i386/pt-machine.c: Protect C code with #ifndef ASSEMBLER. + * sysdeps/i386/tls.h: Likewise. + * sysdeps/i386/useldt.h: Likewise. + * sysdeps/i386/i686/pt-machine.h: Likewise. + 2002-07-02 H.J. Lu <hjl@gnu.org> * sysdeps/mips/pspinlock.c: Don't include <sgidefs.h>. Always diff --git a/linuxthreads/errno.c b/linuxthreads/errno.c index 0eb98ac20c..c74e4c45c9 100644 --- a/linuxthreads/errno.c +++ b/linuxthreads/errno.c @@ -17,14 +17,18 @@ #include <errno.h> #include <netdb.h> #include <resolv.h> +#include <tls.h> #include "pthread.h" #include "internals.h" +#if !USE_TLS || !HAVE___THREAD +/* The definition in libc is sufficient if we use TLS. */ int * __errno_location() { pthread_descr self = thread_self(); return THREAD_GETMEM (self, p_errnop); } +#endif int * __h_errno_location() { diff --git a/linuxthreads/sysdeps/i386/i686/pt-machine.h b/linuxthreads/sysdeps/i386/i686/pt-machine.h index 6b5b7afeee..4f3541cfb6 100644 --- a/linuxthreads/sysdeps/i386/i686/pt-machine.h +++ b/linuxthreads/sysdeps/i386/i686/pt-machine.h @@ -27,6 +27,7 @@ #endif #include "kernel-features.h" +#ifndef ASSEMBLER extern long int testandset (int *spinlock); extern int __compare_and_swap (long int *p, long int oldval, long int newval); @@ -66,6 +67,7 @@ __compare_and_swap (long int *p, long int oldval, long int newval) : "memory"); return ret; } +#endif #if __ASSUME_LDT_WORKS > 0 #include "../useldt.h" diff --git a/linuxthreads/sysdeps/i386/pt-machine.h b/linuxthreads/sysdeps/i386/pt-machine.h index 5a758584da..ec92ce2418 100644 --- a/linuxthreads/sysdeps/i386/pt-machine.h +++ b/linuxthreads/sysdeps/i386/pt-machine.h @@ -22,6 +22,7 @@ #ifndef _PT_MACHINE_H #define _PT_MACHINE_H 1 +#ifndef ASSEMBLER #ifndef PT_EI # define PT_EI extern inline #endif @@ -102,5 +103,6 @@ compare_and_swap_is_available (void) Otherwise, it's a 486 or above and it has cmpxchg. */ return changed != 0; } +#endif /* ASSEMBLER */ #endif /* pt-machine.h */ diff --git a/linuxthreads/sysdeps/i386/tls.h b/linuxthreads/sysdeps/i386/tls.h index c1bfd1bca8..44f947c9c6 100644 --- a/linuxthreads/sysdeps/i386/tls.h +++ b/linuxthreads/sysdeps/i386/tls.h @@ -20,9 +20,10 @@ #ifndef _TLS_H #define _TLS_H -#include <stddef.h> +# include <pt-machine.h> -#include <pt-machine.h> +#ifndef ASSEMBLER +# include <stddef.h> /* Type for the dtv. */ typedef union dtv @@ -39,56 +40,58 @@ typedef struct dtv_t *dtv; void *self; /* Pointer to the thread descriptor. */ } tcbhead_t; +#endif /* We can support TLS only if the floating-stack support is available. */ #if defined FLOATING_STACKS && defined HAVE_TLS_SUPPORT -/* Get system call information. */ -# include <sysdep.h> - /* Signal that TLS support is available. */ # define USE_TLS 1 +# ifndef ASSEMBLER +/* Get system call information. */ +# include <sysdep.h> + /* Get the thread descriptor definition. */ -# include <linuxthreads/descr.h> +# include <linuxthreads/descr.h> /* This is the size of the initial TCB. */ -# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) +# define TLS_INIT_TCB_SIZE sizeof (tcbhead_t) /* Alignment requirements for the initial TCB. */ -# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) +# define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t) /* This is the size of the TCB. */ -# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) +# define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct) /* Alignment requirements for the TCB. */ -# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) +# define TLS_TCB_ALIGN __alignof__ (struct _pthread_descr_struct) /* The TCB can have any size and the memory following the address the thread pointer points to is unspecified. Allocate the TCB there. */ -# define TLS_TCB_AT_TP 1 +# define TLS_TCB_AT_TP 1 /* Install the dtv pointer. The pointer passed is to the element with index -1 which contain the length. */ -# define INSTALL_DTV(descr, dtvp) \ +# define INSTALL_DTV(descr, dtvp) \ ((tcbhead_t *) descr)->dtv = dtvp + 1 /* Install new dtv for current thread. */ -# define INSTALL_NEW_DTV(dtv) \ +# define INSTALL_NEW_DTV(dtv) \ ({ struct _pthread_descr_struct *__descr; \ THREAD_SETMEM (__descr, p_header.data.dtvp, dtv); }) /* Return dtv of given thread descriptor. */ -# define GET_DTV(descr) \ +# define GET_DTV(descr) \ (((tcbhead_t *) descr)->dtv) /* Code to initially initialize the thread pointer. This might need special attention since 'errno' is not yet available and if the operation can cause a failure 'errno' must not be touched. */ -# define TLS_INIT_TP(descr) \ +# define TLS_INIT_TP(descr) \ do { \ void *_descr = (descr); \ struct modify_ldt_ldt_s ldt_entry = \ @@ -116,10 +119,11 @@ typedef struct /* Return the address of the dtv for the current thread. */ -# define THREAD_DTV() \ +# define THREAD_DTV() \ ({ struct _pthread_descr_struct *__descr; \ THREAD_GETMEM (__descr, p_header.data.dtvp); }) -#endif /* FLOATING_STACKS && HAVE_TLS_SUPPORT */ +# endif /* FLOATING_STACKS && HAVE_TLS_SUPPORT */ +#endif /* __ASSEMBLER__ */ #endif /* tls.h */ diff --git a/linuxthreads/sysdeps/i386/useldt.h b/linuxthreads/sysdeps/i386/useldt.h index 116e95d042..64a3b52123 100644 --- a/linuxthreads/sysdeps/i386/useldt.h +++ b/linuxthreads/sysdeps/i386/useldt.h @@ -1,6 +1,6 @@ /* Special definitions for ix86 machine using segment register based thread descriptor. - Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1998, 2000, 2001, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>. @@ -19,6 +19,7 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#ifndef ASSEMBLER #include <stddef.h> /* For offsetof. */ #include <stdlib.h> /* For abort(). */ @@ -198,6 +199,7 @@ extern int __modify_ldt (int, struct modify_ldt_ldt_s *, size_t); member))); \ } \ }) +#endif /* We want the OS to assign stack addresses. */ #define FLOATING_STACKS 1 diff --git a/stdlib/Makefile b/stdlib/Makefile index ab6c8bf6a2..18adf35624 100644 --- a/stdlib/Makefile +++ b/stdlib/Makefile @@ -22,7 +22,8 @@ subdir := stdlib headers := stdlib.h alloca.h monetary.h fmtmsg.h ucontext.h sys/ucontext.h \ - inttypes.h stdint.h bits/wordsize.h bits/wchar.h + inttypes.h stdint.h bits/wordsize.h bits/wchar.h \ + errno.h sys/errno.h bits/errno.h routines := \ atof atoi atol atoll \ diff --git a/stdlib/errno.h b/stdlib/errno.h new file mode 100644 index 0000000000..f33b0c921c --- /dev/null +++ b/stdlib/errno.h @@ -0,0 +1,73 @@ +/* Copyright (C) 1991,92,93,94,95,96,97,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 + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* + * ISO C99 Standard: 7.5 Errors <errno.h> + */ + +#ifndef _ERRNO_H + +/* The includer defined __need_Emath if he wants only the definitions + of EDOM and ERANGE, and not everything else. */ +#ifndef __need_Emath +# define _ERRNO_H 1 +# include <features.h> +#endif + +__BEGIN_DECLS + +/* Get the error number constants from the system-specific file. + This file will test __need_Emath and _ERRNO_H. */ +#include <bits/errno.h> +#undef __need_Emath + +#ifdef _ERRNO_H + +/* Declare the `errno' variable, unless it's defined as a macro by + bits/errno.h. This is the case in GNU, where it is a per-thread + variable. This redeclaration using the macro still works, but it + will be a function declaration without a prototype and may trigger + a -Wstrict-prototypes warning. */ +#ifndef errno +extern int errno; +#endif + +#ifdef __USE_GNU + +/* The full and simple forms of the name with which the program was + invoked. These variables are set up automatically at startup based on + the value of ARGV[0] (this works only if you use GNU ld). */ +extern char *program_invocation_name, *program_invocation_short_name; +#endif /* __USE_GNU */ +#endif /* _ERRNO_H */ + +__END_DECLS + +#endif /* _ERRNO_H */ + +/* The Hurd <bits/errno.h> defines `error_t' as an enumerated type so + that printing `error_t' values in the debugger shows the names. We + might need this definition sometimes even if this file was included + before. */ +#if defined __USE_GNU || defined __need_error_t +# ifndef __error_t_defined +typedef int error_t; +# define __error_t_defined 1 +# endif +# undef __need_error_t +#endif diff --git a/stdlib/sys/errno.h b/stdlib/sys/errno.h new file mode 100644 index 0000000000..339f4fc10c --- /dev/null +++ b/stdlib/sys/errno.h @@ -0,0 +1 @@ +#include <errno.h> 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) |