Update.
authorUlrich Drepper <drepper@redhat.com>
Tue, 28 Jan 2003 10:42:28 +0000 (10:42 +0000)
committerUlrich Drepper <drepper@redhat.com>
Tue, 28 Jan 2003 10:42:28 +0000 (10:42 +0000)
2003-01-27  Martin Schwidefsky  <schwidefsky@de.ibm.com>

* elf/elf.h: Add new s390 relocs.
* elf/tls-macros.h: Add s390 versions.
* sysdeps/s390/Versions [GLIBC_2.3] (ld): Export __tls_get_offset.
* sysdeps/s390/dl-tls.h: New file.
* sysdeps/s390/libc-tls.c: New file.
* sysdeps/s390/s390-32/dl-machine.h (elf_machine_type_class): Add TLS
relocs for class PLT.
(elf_machine_rela): Handle TLS relocs.
* sysdeps/s390/s390-64/dl-machine.h: Likewise.
* sysdeps/s390/s390-32/elf/configure.in: Add TLS check.
* sysdeps/s390/s390-64/elf/configure.in: Likewise.
* sysdeps/unix/sysv/linux/s390/s390-32/clone.S: Add support for
CLONE_CHILD_*TID flags.
* sysdeps/unix/sysv/linux/s390/s390-64/clone.S: Likewise.
* sysdeps/unix/sysv/linux/s390/s390-64/mmap.S: Use branch with 32
bit offset.
* sysdeps/unix/sysv/linux/s390/s390-64/socket.S: Likewise.
* sysdeps/unix/sysv/linux/s390/s390-64/syscall.S: Likewise.
* sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S (__syscall_error):
Support USE___THREAD. Define RTLD_PRIVATE_ERRNO variant.
* sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S (__syscall_error):
Likewise.
* sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h:
(SYSCALL_ERROR_LABEL): Move define next to SYSCALL_ERROR_HANDLER.
(SYSCALL_ERROR_HANDLER): Add USE___THREAD and RTLD_PRIVATE_ERRNO
variants.
* sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h:
(SYSCALL_ERROR_LABEL): Move define next to SYSCALL_ERROR_HANDLER. Use
direct branch to syscall_error for !PIC and PIC && !_LIBC_REENTRANT.
(SYSCALL_ERROR_HANDLER): Add USE___THREAD and RTLD_PRIVATE_ERRNO
variants.

30 files changed:
ChangeLog
elf/elf.h
elf/tls-macros.h
linuxthreads/ChangeLog
linuxthreads/sysdeps/s390/s390-32/pt-machine.h
linuxthreads/sysdeps/s390/s390-64/pt-machine.h
linuxthreads/sysdeps/s390/tls.h
linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S
nptl/ChangeLog
nptl/sysdeps/pthread/createthread.c [new file with mode: 0644]
nptl/sysdeps/unix/sysv/linux/i386/createthread.c
sysdeps/s390/Versions [new file with mode: 0644]
sysdeps/s390/dl-tls.h [new file with mode: 0644]
sysdeps/s390/libc-tls.c [new file with mode: 0644]
sysdeps/s390/s390-32/dl-machine.h
sysdeps/s390/s390-32/elf/configure [new file with mode: 0644]
sysdeps/s390/s390-32/elf/configure.in [new file with mode: 0644]
sysdeps/s390/s390-64/dl-machine.h
sysdeps/s390/s390-64/elf/configure [new file with mode: 0644]
sysdeps/s390/s390-64/elf/configure.in [new file with mode: 0644]
sysdeps/unix/sysv/linux/s390/s390-32/clone.S
sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S
sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
sysdeps/unix/sysv/linux/s390/s390-64/clone.S
sysdeps/unix/sysv/linux/s390/s390-64/mmap.S
sysdeps/unix/sysv/linux/s390/s390-64/socket.S
sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S
sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h

index ef422b7..bf8f96f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+2003-01-27  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+       * elf/elf.h: Add new s390 relocs.
+       * elf/tls-macros.h: Add s390 versions.
+       * sysdeps/s390/Versions [GLIBC_2.3] (ld): Export __tls_get_offset.
+       * sysdeps/s390/dl-tls.h: New file.
+       * sysdeps/s390/libc-tls.c: New file.
+       * sysdeps/s390/s390-32/dl-machine.h (elf_machine_type_class): Add TLS
+       relocs for class PLT.
+       (elf_machine_rela): Handle TLS relocs.
+       * sysdeps/s390/s390-64/dl-machine.h: Likewise.
+       * sysdeps/s390/s390-32/elf/configure.in: Add TLS check.
+       * sysdeps/s390/s390-64/elf/configure.in: Likewise.
+       * sysdeps/unix/sysv/linux/s390/s390-32/clone.S: Add support for
+       CLONE_CHILD_*TID flags.
+       * sysdeps/unix/sysv/linux/s390/s390-64/clone.S: Likewise.
+       * sysdeps/unix/sysv/linux/s390/s390-64/mmap.S: Use branch with 32
+       bit offset.
+       * sysdeps/unix/sysv/linux/s390/s390-64/socket.S: Likewise.
+       * sysdeps/unix/sysv/linux/s390/s390-64/syscall.S: Likewise.
+       * sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S (__syscall_error):
+       Support USE___THREAD. Define RTLD_PRIVATE_ERRNO variant.
+       * sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S (__syscall_error):
+       Likewise.
+       * sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h:
+       (SYSCALL_ERROR_LABEL): Move define next to SYSCALL_ERROR_HANDLER.
+       (SYSCALL_ERROR_HANDLER): Add USE___THREAD and RTLD_PRIVATE_ERRNO
+       variants.
+       * sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h:
+       (SYSCALL_ERROR_LABEL): Move define next to SYSCALL_ERROR_HANDLER. Use
+       direct branch to syscall_error for !PIC and PIC && !_LIBC_REENTRANT.
+       (SYSCALL_ERROR_HANDLER): Add USE___THREAD and RTLD_PRIVATE_ERRNO
+       variants.
+
 2003-01-28  Ulrich Drepper  <drepper@redhat.com>
 
        * sysdeps/unix/common/pause.c (do_pause): New function.  Split
index 89ce568..30d0669 100644 (file)
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -2228,36 +2228,83 @@ typedef Elf32_Addr Elf32_Conflict;
 
 /* Additional s390 relocs */
 
-#define R_390_NONE     0              /* No reloc.  */
-#define R_390_8                1              /* Direct 8 bit.  */
-#define R_390_12       2              /* Direct 12 bit.  */
-#define R_390_16       3              /* Direct 16 bit.  */
-#define R_390_32       4              /* Direct 32 bit.  */
-#define R_390_PC32     5              /* PC relative 32 bit.  */
-#define R_390_GOT12    6              /* 12 bit GOT offset.  */
-#define R_390_GOT32    7              /* 32 bit GOT offset.  */
-#define R_390_PLT32    8              /* 32 bit PC relative PLT address.  */
-#define R_390_COPY     9              /* Copy symbol at runtime.  */
-#define R_390_GLOB_DAT 10             /* Create GOT entry.  */
-#define R_390_JMP_SLOT 11             /* Create PLT entry.  */
-#define R_390_RELATIVE 12             /* Adjust by program base.  */
-#define R_390_GOTOFF   13             /* 32 bit offset to GOT.  */
-#define R_390_GOTPC    14             /* 32 bit PC relative offset to GOT.  */
-#define R_390_GOT16    15             /* 16 bit GOT offset.  */
-#define R_390_PC16     16             /* PC relative 16 bit.  */
-#define R_390_PC16DBL  17             /* PC relative 16 bit shifted by 1.  */
-#define R_390_PLT16DBL 18             /* 16 bit PC rel. PLT shifted by 1.  */
-#define R_390_PC32DBL  19             /* PC relative 32 bit shifted by 1.  */
-#define R_390_PLT32DBL 20             /* 32 bit PC rel. PLT shifted by 1.  */
-#define R_390_GOTPCDBL 21             /* 32 bit PC rel. GOT shifted by 1.  */
-#define R_390_64       22             /* Direct 64 bit.  */
-#define R_390_PC64     23             /* PC relative 64 bit.  */
-#define R_390_GOT64    24             /* 64 bit GOT offset.  */
-#define R_390_PLT64    25             /* 64 bit PC relative PLT address.  */
-#define R_390_GOTENT   26             /* 32 bit PC rel. to GOT entry >> 1. */
+#define R_390_NONE             0       /* No reloc.  */
+#define R_390_8                        1       /* Direct 8 bit.  */
+#define R_390_12               2       /* Direct 12 bit.  */
+#define R_390_16               3       /* Direct 16 bit.  */
+#define R_390_32               4       /* Direct 32 bit.  */
+#define R_390_PC32             5       /* PC relative 32 bit.  */
+#define R_390_GOT12            6       /* 12 bit GOT offset.  */
+#define R_390_GOT32            7       /* 32 bit GOT offset.  */
+#define R_390_PLT32            8       /* 32 bit PC relative PLT address.  */
+#define R_390_COPY             9       /* Copy symbol at runtime.  */
+#define R_390_GLOB_DAT         10      /* Create GOT entry.  */
+#define R_390_JMP_SLOT         11      /* Create PLT entry.  */
+#define R_390_RELATIVE         12      /* Adjust by program base.  */
+#define R_390_GOTOFF32         13      /* 32 bit offset to GOT.         */
+#define R_390_GOTPC            14      /* 32 bit PC relative offset to GOT.  */
+#define R_390_GOT16            15      /* 16 bit GOT offset.  */
+#define R_390_PC16             16      /* PC relative 16 bit.  */
+#define R_390_PC16DBL          17      /* PC relative 16 bit shifted by 1.  */
+#define R_390_PLT16DBL         18      /* 16 bit PC rel. PLT shifted by 1.  */
+#define R_390_PC32DBL          19      /* PC relative 32 bit shifted by 1.  */
+#define R_390_PLT32DBL         20      /* 32 bit PC rel. PLT shifted by 1.  */
+#define R_390_GOTPCDBL         21      /* 32 bit PC rel. GOT shifted by 1.  */
+#define R_390_64               22      /* Direct 64 bit.  */
+#define R_390_PC64             23      /* PC relative 64 bit.  */
+#define R_390_GOT64            24      /* 64 bit GOT offset.  */
+#define R_390_PLT64            25      /* 64 bit PC relative PLT address.  */
+#define R_390_GOTENT           26      /* 32 bit PC rel. to GOT entry >> 1. */
+#define R_390_GOTOFF16         27      /* 16 bit offset to GOT. */
+#define R_390_GOTOFF64         28      /* 64 bit offset to GOT. */
+#define R_390_GOTPLT12         29      /* 12 bit offset to jump slot.  */
+#define R_390_GOTPLT16         30      /* 16 bit offset to jump slot.  */
+#define R_390_GOTPLT32         31      /* 32 bit offset to jump slot.  */
+#define R_390_GOTPLT64         32      /* 64 bit offset to jump slot.  */
+#define R_390_GOTPLTENT                33      /* 32 bit rel. offset to jump slot.  */
+#define R_390_PLTOFF16         34      /* 16 bit offset from GOT to PLT. */
+#define R_390_PLTOFF32         35      /* 32 bit offset from GOT to PLT. */
+#define R_390_PLTOFF64         36      /* 16 bit offset from GOT to PLT. */
+#define R_390_TLS_LOAD         37      /* Tag for load insn in TLS code.  */
+#define R_390_TLS_GDCALL       38      /* Tag for function call in general
+                                          dynamic TLS code. */
+#define R_390_TLS_LDCALL       39      /* Tag for function call in local
+                                          dynamic TLS code. */
+#define R_390_TLS_GD32         40      /* Direct 32 bit for general dynamic
+                                          thread local data.  */
+#define R_390_TLS_GD64         41      /* Direct 64 bit for general dynamic
+                                         thread local data.  */
+#define R_390_TLS_GOTIE12      42      /* 12 bit GOT offset for static TLS
+                                          block offset.  */
+#define R_390_TLS_GOTIE32      43      /* 32 bit GOT offset for static TLS
+                                          block offset.  */
+#define R_390_TLS_GOTIE64      44      /* 64 bit GOT offset for static TLS
+                                          block offset. */
+#define R_390_TLS_LDM32                45      /* Direct 32 bit for local dynamic
+                                          thread local data in LE code.  */
+#define R_390_TLS_LDM64                46      /* Direct 64 bit for local dynamic
+                                          thread local data in LE code.  */
+#define R_390_TLS_IE32         47      /* 32 bit address of GOT entry for
+                                          negated static TLS block offset.  */
+#define R_390_TLS_IE64         48      /* 64 bit address of GOT entry for
+                                          negated static TLS block offset.  */
+#define R_390_TLS_IEENT                49      /* 32 bit rel. offset to GOT entry for
+                                          negated static TLS block offset.  */
+#define R_390_TLS_LE32         50      /* 32 bit negated offset relative to
+                                          static TLS block.  */
+#define R_390_TLS_LE64         51      /* 64 bit negated offset relative to
+                                          static TLS block.  */
+#define R_390_TLS_LDO32                52      /* 32 bit offset relative to TLS
+                                          block.  */
+#define R_390_TLS_LDO64                53      /* 64 bit offset relative to TLS
+                                          block.  */
+#define R_390_TLS_DTPMOD       54      /* ID of module containing symbol.  */
+#define R_390_TLS_DTPOFF       55      /* Offset in TLS block.  */
+#define R_390_TLS_TPOFF                56      /* Negated offset in static TLS
+                                          block.  */
 
 /* Keep this the last entry.  */
-#define R_390_NUM      27
+#define R_390_NUM              57
 
 /* CRIS relocations.  */
 #define R_CRIS_NONE            0
index 2de4b1a..ea9ec56 100644 (file)
@@ -367,6 +367,196 @@ register void *__gp __asm__("$29");
            "o5", "o7");                                                      \
      __o0; })
 
+#elif defined __s390x__
+
+# define TLS_LE(x) \
+  ({ unsigned long __offset;                                                 \
+     asm ("bras %0,1f\n"                                                     \
+         "0:\t.quad " #x "@ntpoff\n"                                         \
+         "1:\tlg %0,0(%0)"                                                   \
+         : "=a" (__offset) : : "cc" );                                       \
+     (int *) (__builtin_thread_pointer() + __offset); })
+
+# ifdef PIC
+#  define TLS_IE(x) \
+  ({ unsigned long __offset;                                                 \
+     asm ("bras %0,1f\n"                                                     \
+         "0:\t.quad " #x "@gotntpoff\n"                                      \
+         "1:\tlg %0,0(%0)\n\t"                                               \
+         "lg %0,0(%0,%%r12):tls_load:" #x                                    \
+         : "=&a" (__offset) : : "cc" );                                      \
+     (int *) (__builtin_thread_pointer() + __offset); })
+# else
+#  define TLS_IE(x) \
+  ({ unsigned long  __offset;                                                \
+     asm ("bras %0,1f\n"                                                     \
+         "0:\t.quad " #x "@indntpoff\n"                                      \
+         "1:\t lg %0,0(%0)\n\t"                                              \
+         "lg %0,0(%0):tls_load:" #x                                          \
+         : "=&a" (__offset) : : "cc" );                                      \
+     (int *) (__builtin_thread_pointer() + __offset); })
+# endif
+
+# ifdef PIC
+#  define TLS_LD(x) \
+  ({ unsigned long __offset, __save12;                                       \
+     asm ("bras %0,1f\n"                                                     \
+         "0:\t.quad " #x "@tlsldm\n\t"                                       \
+         ".quad " #x "@dtpoff\n"                                             \
+         "1:\tlgr %1,%%r12\n\t"                                              \
+          "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t"                             \
+          "lg %%r2,0(%0)\n\t"                                                \
+         "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t"            \
+         "lg %0,8(%0)\n\t"                                                   \
+         "algr %0,%%r2\n\t"                                                  \
+          "lgr %%r12,%1"                                                     \
+         : "=&a" (__offset), "=&a" (__save12)                                \
+          : : "cc", "0", "1", "2", "3", "4", "5" );                          \
+     (int *) (__builtin_thread_pointer() + __offset); })
+# else
+#  define TLS_LD(x) \
+  ({ unsigned long __offset;                                                 \
+     asm ("bras %0,1f\n"                                                     \
+         "0:\t.quad " #x "@tlsldm\n\t"                                       \
+         ".quad " #x "@dtpoff\n"                                             \
+         "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t"                          \
+          "lg %%r2,0(%0)\n\t"                                                \
+         "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t"            \
+         "lg %0,8(%0)\n\t"                                                   \
+         "algr %0,%%r2"                                                      \
+         : "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" );  \
+     (int *) (__builtin_thread_pointer() + __offset); })
+# endif
+
+# ifdef PIC
+#  define TLS_GD(x) \
+  ({ unsigned long __offset, __save12;                                       \
+     asm ("bras %0,1f\n"                                                     \
+         "0:\t.quad " #x "@tlsgd\n"                                          \
+         "1:\tlgr %1,%%r12\n\t"                                              \
+         "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t"                              \
+          "lg %%r2,0(%0)\n\t"                                                \
+         "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t"            \
+          "lgr %0,%%r2\n\t"                                                  \
+          "lgr %%r12,%1"                                                     \
+         : "=&a" (__offset), "=&a" (__save12)                                \
+          : : "cc", "0", "1", "2", "3", "4", "5" );                          \
+     (int *) (__builtin_thread_pointer() + __offset); })
+# else
+#  define TLS_GD(x) \
+  ({ unsigned long __offset;                                                 \
+     asm ("bras %0,1f\n"                                                     \
+         "0:\t.quad " #x "@tlsgd\n"                                          \
+         "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t"                          \
+         "lg %%r2,0(%0)\n\t"                                                 \
+         "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t"            \
+          "lgr %0,%%r2"                                                              \
+         : "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" );  \
+     (int *) (__builtin_thread_pointer() + __offset); })
+# endif
+
+#elif defined __s390__
+
+# define TLS_LE(x) \
+  ({ unsigned long __offset;                                                 \
+     asm ("bras %0,1f\n"                                                     \
+         "0:\t.long " #x "@ntpoff\n"                                         \
+         "1:\tl %0,0(%0)"                                                    \
+         : "=a" (__offset) : : "cc" );                                       \
+     (int *) (__builtin_thread_pointer() + __offset); })
+
+# ifdef PIC
+#  define TLS_IE(x) \
+  ({ unsigned long __offset;                                                 \
+     asm ("bras %0,1f\n"                                                     \
+         "0:\t.long " #x "@gotntpoff\n"                                      \
+         "1:\tl %0,0(%0)\n\t"                                                \
+         "l %0,0(%0,%%r12):tls_load:" #x                                     \
+         : "=&a" (__offset) : : "cc" );                                      \
+     (int *) (__builtin_thread_pointer() + __offset); })
+# else
+#  define TLS_IE(x) \
+  ({ unsigned long  __offset;                                                \
+     asm ("bras %0,1f\n"                                                     \
+         "0:\t.long " #x "@indntpoff\n"                                      \
+         "1:\t l %0,0(%0)\n\t"                                               \
+         "l %0,0(%0):tls_load:" #x                                           \
+         : "=&a" (__offset) : : "cc" );                                      \
+     (int *) (__builtin_thread_pointer() + __offset); })
+# endif
+
+# ifdef PIC
+#  define TLS_LD(x) \
+  ({ unsigned long __offset, __save12;                                       \
+     asm ("bras %0,1f\n"                                                     \
+         "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t"                            \
+         ".long __tls_get_offset@plt-0b\n\t"                                 \
+         ".long " #x "@tlsldm\n\t"                                           \
+         ".long " #x "@dtpoff\n"                                             \
+         "1:\tlr %1,%%r12\n\t"                                               \
+          "l %%r12,0(%0)\n\t"                                                \
+          "la %%r12,0(%%r12,%0)\n\t"                                         \
+         "l %%r1,4(%0)\n\t"                                                  \
+         "l %%r2,8(%0)\n\t"                                                  \
+         "bas %%r14,0(%%r1,%0):tls_ldcall:" #x "\n\t"                        \
+         "l %0,12(%0)\n\t"                                                   \
+         "alr %0,%%r2\n\t"                                                   \
+          "lr %%r12,%1"                                                              \
+         : "=&a" (__offset), "=&a" (__save12)                                \
+          : : "cc", "0", "1", "2", "3", "4", "5" );                          \
+     (int *) (__builtin_thread_pointer() + __offset); })
+# else
+#  define TLS_LD(x) \
+  ({ unsigned long __offset;                                                 \
+     asm ("bras %0,1f\n"                                                     \
+         "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t"                               \
+         ".long __tls_get_offset@plt\n\t"                                    \
+         ".long " #x "@tlsldm\n\t"                                           \
+         ".long " #x "@dtpoff\n"                                             \
+         "1:\tl %%r12,0(%0)\n\t"                                             \
+         "l %%r1,4(%0)\n\t"                                                  \
+         "l %%r2,8(%0)\n\t"                                                  \
+         "bas %%r14,0(%%r1):tls_ldcall:" #x "\n\t"                           \
+         "l %0,12(%0)\n\t"                                                   \
+         "alr %0,%%r2"                                                       \
+         : "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" );  \
+     (int *) (__builtin_thread_pointer() + __offset); })
+# endif
+
+# ifdef PIC
+#  define TLS_GD(x) \
+  ({ unsigned long __offset, __save12;                                       \
+     asm ("bras %0,1f\n"                                                     \
+         "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t"                            \
+         ".long __tls_get_offset@plt-0b\n\t"                                 \
+         ".long " #x "@tlsgd\n"                                              \
+         "1:\tlr %1,%%r12\n\t"                                               \
+          "l %%r12,0(%0)\n\t"                                                \
+          "la %%r12,0(%%r12,%0)\n\t"                                         \
+         "l %%r1,4(%0)\n\t"                                                  \
+         "l %%r2,8(%0)\n\t"                                                  \
+         "bas %%r14,0(%%r1,%0):tls_gdcall:" #x "\n\t"                        \
+          "lr %0,%%r2\n\t"                                                   \
+          "lr %%r12,%1"                                                              \
+         : "=&a" (__offset), "=&a" (__save12)                                \
+          : : "cc", "0", "1", "2", "3", "4", "5" );                          \
+     (int *) (__builtin_thread_pointer() + __offset); })
+# else
+#  define TLS_GD(x) \
+  ({ unsigned long __offset;                                                 \
+     asm ("bras %0,1f\n"                                                     \
+         "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t"                               \
+         ".long __tls_get_offset@plt\n\t"                                    \
+         ".long " #x "@tlsgd\n"                                              \
+         "1:\tl %%r12,0(%0)\n\t"                                             \
+         "l %%r1,4(%0)\n\t"                                                  \
+         "l %%r2,8(%0)\n\t"                                                  \
+         "bas %%r14,0(%%r1):tls_gdcall:" #x "\n\t"                           \
+          "lr %0,%%r2"                                                       \
+         : "=&a" (__offset) : : "cc", "0", "1", "2", "3", "4", "5", "12" );  \
+     (int *) (__builtin_thread_pointer() + __offset); })
+# endif
+
 #else
 # error "No support for this architecture so far."
 #endif
index 2949321..80de0de 100644 (file)
@@ -1,3 +1,17 @@
+2003-01-27  Martin Schwidefsky  <schwidefsky@de.ibm.com>
+
+       * sysdeps/s390/s390-32/pt-machine.h (THREAD_SELF, INIT_THREAD_SELF):
+       Define TLS versions.
+       * sysdeps/s390/s390-64/pt-machine.h (THREAD_SELF, INIT_THREAD_SELF):
+       Likewise.
+       * sysdeps/s390/tls.h [HAVE_TLS_SUPPORT] (USE_TLS, TLS_INIT_TCB_SIZE,
+       TLS_INIT_TCB_ALIGN, TLS_TCB_SIZE, TLS_TCB_ALIGN, TLS_TCB_AT_TP,
+       INSTALL_DTV, INSTALL_NEW_DTV, GET_DTV, TLS_INIT_TP, THREAD_DTV):
+       Define.
+       * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO): Use
+       branch with 32 bit offset.
+       * sysdeps/unix/sysv/linux/s390/s390-64/vfork.S: Likewise.
+
 2003-01-24  Jakub Jelinek  <jakub@redhat.com>
 
        * sysdeps/sparc/sparc32/pt-machine.h (__thread_self): Change to %g7,
index 18b5919..ee35320 100644 (file)
@@ -58,6 +58,13 @@ testandset (int *spinlock)
 #define CURRENT_STACK_FRAME  stack_pointer
 register char * stack_pointer __asm__ ("15");
 
+#ifdef USE_TLS
+/* Return the thread descriptor for the current thread.  */
+# define THREAD_SELF ((pthread_descr) __builtin_thread_pointer ())
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr) __builtin_set_thread_pointer (descr)
+#else
 /* Return the thread descriptor for the current thread.
    S/390 registers uses access register 0 as "thread register".  */
 #define THREAD_SELF  ({                                                       \
@@ -70,6 +77,7 @@ register char * stack_pointer __asm__ ("15");
 #define INIT_THREAD_SELF(descr, nr)  ({                                       \
   __asm__ ("sar %%a0,%0" : : "d" (descr) );                                   \
 })
+#endif
 
 /* Access to data in the thread descriptor is easy.  */
 #define THREAD_GETMEM(descr, member) THREAD_SELF->member
index 92ebe1e..c0f3078 100644 (file)
@@ -58,6 +58,13 @@ testandset (int *spinlock)
 #define CURRENT_STACK_FRAME  stack_pointer
 register char * stack_pointer __asm__ ("15");
 
+#ifdef USE_TLS
+/* Return the thread descriptor for the current thread.  */
+# define THREAD_SELF ((pthread_descr) __builtin_thread_pointer ())
+
+/* Initialize the thread-unique value.  */
+#define INIT_THREAD_SELF(descr, nr) __builtin_set_thread_pointer (descr)
+#else
 /* Return the thread descriptor for the current thread.
    64 bit S/390 uses access register 0 and 1 as "thread register".  */
 #define THREAD_SELF  ({                                                       \
@@ -76,6 +83,7 @@ register char * stack_pointer __asm__ ("15");
            "   sar  %%a0,0\n"                                                 \
            : : "d" (descr) : "0" );                                           \
 })
+#endif
 
 /* Access to data in the thread descriptor is easy.  */
 #define THREAD_GETMEM(descr, member) THREAD_SELF->member
index d872bb7..11f31ba 100644 (file)
@@ -45,19 +45,96 @@ typedef struct
 # include <tcb-offsets.h>
 #endif /* __ASSEMBLER__ */
 
-#undef USE_TLS
+/* TLS is always supported if the tools support it.  There are no
+   kernel dependencies.  To avoid bothering with the TLS support code
+   at all, use configure --without-tls.
 
-#if USE_TLS
+   We need USE_TLS to be consistently defined, for ldsodefs.h
+   conditionals.  */
 
-#else
+#ifdef HAVE_TLS_SUPPORT
 
-#define NONTLS_INIT_TP \
+/* 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>
+
+/* This is the size of the initial TCB.  */
+#  define TLS_INIT_TCB_SIZE sizeof (tcbhead_t)
+
+/* Alignment requirements for the initial TCB.  */
+#  define TLS_INIT_TCB_ALIGN __alignof__ (tcbhead_t)
+
+/* This is the size of the TCB.  */
+#  define TLS_TCB_SIZE sizeof (struct _pthread_descr_struct)
+
+/* Alignment requirements for the TCB.  */
+#  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
+
+
+/* Install the dtv pointer.  The pointer passed is to the element with
+   index -1 which contain the length.  */
+#  define INSTALL_DTV(descr, dtvp) \
+  ((tcbhead_t *) (descr))->dtv = (dtvp) + 1
+
+/* Install new dtv for current thread.  */
+#  define INSTALL_NEW_DTV(dtv) \
+  (((tcbhead_t *) __builtin_thread_pointer ())->dtv = (dtv))
+
+/* Return dtv of given thread descriptor.  */
+#  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.
+
+   The value of this macro is null if successful, or an error string.  */
+#  define TLS_INIT_TP(descr, secondcall)                                     \
+  ({                                                                         \
+    void *_descr = (descr);                                                  \
+    tcbhead_t *head = _descr;                                                \
+                                                                             \
+    head->tcb = _descr;                                                              \
+    /* For now the thread descriptor is at the same address.  */             \
+    head->self = _descr;                                                     \
+                                                                             \
+    __builtin_set_thread_pointer (_descr);                                   \
+    0;                                                                       \
+  })
+
+/* Return the address of the dtv for the current thread.  */
+#  define THREAD_DTV() \
+  (((tcbhead_t *) __builtin_thread_pointer ())->dtv)
+
+# endif /* __ASSEMBLER__ */
+
+#else  /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */
+
+# ifndef __ASSEMBLER__
+
+/* Get the thread descriptor definition.  */
+#  include <linuxthreads/descr.h>
+
+#  define NONTLS_INIT_TP \
   do {                                                                 \
     static const tcbhead_t nontls_init_tp                      \
       = { .multiple_threads = 0 };                             \
     INIT_THREAD_SELF (&nontls_init_tp, 0);                     \
   } while (0)
 
-#endif /* USE_TLS */
+# endif /* __ASSEMBLER__ */
+
+#endif /* HAVE_TLS_SUPPORT && (FLOATING_STACKS || !IS_IN_libpthread) */
 
 #endif /* tls.h */
index ce4afb1..4e54e55 100644 (file)
@@ -51,7 +51,7 @@ ENTRY(name)                                                                 \
 L(pseudo_check):                                                             \
        lghi    %r4,-4095;                                                    \
        clgr    %r2,%r4;                                                      \
-       jnl     SYSCALL_ERROR_LABEL;                                          \
+       jgnl    SYSCALL_ERROR_LABEL;                                          \
 L(pseudo_end):
 
 # ifdef IS_IN_libpthread
index e01d438..efc9710 100644 (file)
@@ -36,7 +36,7 @@ ENTRY (__vfork)
        /* Check for error.  */
        lghi    %r4,-4095
        clgr    %r2,%r4
-       jnl     SYSCALL_ERROR_LABEL
+       jgnl    SYSCALL_ERROR_LABEL
 
        /* Normal return.  */
        br      %r14
index 9f5080b..1f293f5 100644 (file)
@@ -1,3 +1,10 @@
+2003-01-28  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/unix/sysv/linux/i386/createthread.c: Define
+       PREPARE_CREATE and TLS_VALUE with x86-specific bits.  All the rest
+       of the code is moved to ...
+       * sysdeps/pthread/createthread.c: ...here.  New file.
+
 2003-01-27  Ulrich Drepper  <drepper@redhat.com>
 
        * sysdeps/unix/sysv/linux/i386/i486/lowlevelsem.S
diff --git a/nptl/sysdeps/pthread/createthread.c b/nptl/sysdeps/pthread/createthread.c
new file mode 100644 (file)
index 0000000..b689836
--- /dev/null
@@ -0,0 +1,145 @@
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   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.  */
+
+#include <sched.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <atomic.h>
+#include <ldsodefs.h>
+#include <tls.h>
+
+
+#define CLONE_SIGNAL           (CLONE_SIGHAND | CLONE_THREAD)
+
+/* Unless otherwise specified, the thread "register" is going to be
+   initialized with a pointer to the TCB.  */
+#ifndef TLS_VALUE
+# define TLS_VALUE pd
+#endif
+
+
+static int
+create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
+{
+#ifdef PREPARE_CREATE
+  PREPARE_CREATE;
+#endif
+
+  assert (pd->header.data.tcb != NULL);
+
+
+  if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0))
+    {
+      /* The parent thread is supposed to report events.  Check whether
+        the TD_CREATE event is needed, too.  */
+      const int _idx = __td_eventword (TD_CREATE);
+      const uint32_t _mask = __td_eventmask (TD_CREATE);
+
+      if ((_mask & (__nptl_threads_events.event_bits[_idx]
+                   | pd->eventbuf.eventmask.event_bits[_idx])) != 0)
+       {
+         /* We have to report the new thread.  Make sure the thread
+            does not run far by forcing it to get a lock.  We lock it
+            here too so that the new thread cannot continue until we
+            tell it to.  */
+         lll_lock (pd->lock);
+
+         /* Create the thread.  */
+         if (__clone (start_thread_debug, STACK_VARIABLES_ARGS,
+                      CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
+                      CLONE_SETTLS | CLONE_PARENT_SETTID |
+                      CLONE_CHILD_CLEARTID | CLONE_DETACHED | 0,
+                      pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
+           /* Failed.  */
+           return errno;
+
+         /* We now have for sure more than one thread.  */
+         pd->header.data.multiple_threads = 1;
+
+         /* Now fill in the information about the new thread in
+            the newly created thread's data structure.  We cannot let
+            the new thread do this since we don't know whether it was
+            already scheduled when we send the event.  */
+         pd->eventbuf.eventnum = TD_CREATE;
+         pd->eventbuf.eventdata = pd;
+
+         /* Enqueue the descriptor.  */
+         do
+           pd->nextevent = __nptl_last_event;
+         while (atomic_compare_and_exchange_acq (&__nptl_last_event, pd,
+                                                 pd->nextevent) != 0);
+
+         /* Now call the function which signals the event.  */
+         __nptl_create_event ();
+
+         /* And finally restart the new thread.  */
+         lll_unlock (pd->lock);
+
+         return 0;
+       }
+    }
+
+#ifdef NEED_DL_SYSINFO
+  assert (THREAD_GETMEM (THREAD_SELF, header.data.sysinfo)
+         == pd->header.data.sysinfo);
+#endif
+
+  /* We rely heavily on various flags the CLONE function understands:
+
+     CLONE_VM, CLONE_FS, CLONE_FILES
+       These flags select semantics with shared address space and
+       file descriptors according to what POSIX requires.
+
+     CLONE_SIGNAL
+       This flag selects the POSIX signal semantics.
+
+     CLONE_SETTLS
+       The sixth parameter to CLONE determines the TLS area for the
+       new thread.
+
+     CLONE_PARENT_SETTID
+       The kernels writes the thread ID of the newly created thread
+       into the location pointed to by the fifth parameters to CLONE.
+
+       Note that it would be semantically equivalent to use
+       CLONE_CHILD_SETTID but it is be more expensive in the kernel.
+
+     CLONE_CHILD_CLEARTID
+       The kernels clears the thread ID of a thread that has called
+       sys_exit() - using the same parameter as CLONE_SETTID.
+
+     CLONE_DETACHED
+       No signal is generated if the thread exists and it is
+       automatically reaped.
+
+     The termination signal is chosen to be zero which means no signal
+     is sent.  */
+  if (__clone (start_thread, STACK_VARIABLES_ARGS,
+              CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
+              CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
+              CLONE_DETACHED | 0, pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
+    /* Failed.  */
+    return errno;
+
+  /* We now have for sure more than one thread.  */
+  THREAD_SETMEM (THREAD_SELF, header.data.multiple_threads, 1);
+
+  return 0;
+}
index def1633..37e3d94 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
 
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#include <sched.h>
-#include <setjmp.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <atomic.h>
-#include <ldsodefs.h>
-#include <tls.h>
-
-
-#define CLONE_SIGNAL           (CLONE_SIGHAND | CLONE_THREAD)
-
-
-static int
-create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
-{
-  union user_desc_init desc;
-
-  /* Describe the thread-local storage segment.  */
-
-  /* The 'entry_number' field.  The first three bits of the segment
-     register value select the GDT, ignore them.  We get the index
-     from the value of the %gs register in the current thread.  */
-  desc.vals[0] = TLS_GET_GS () >> 3;
-  /* The 'base_addr' field.  Pointer to the TCB.  */
-  desc.vals[1] = (unsigned long int) pd;
-  /* The 'limit' field.  We use 4GB which is 0xfffff pages.  */
-  desc.vals[2] = 0xfffff;
-  /* Collapsed value of the bitfield:
-       .seg_32bit = 1
-       .contents = 0
-       .read_exec_only = 0
-       .limit_in_pages = 1
-       .seg_not_present = 0
-       .useable = 1 */
-  desc.vals[3] = 0x51;
-
-
-  assert (pd->header.data.tcb != NULL);
-
-
-  if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0))
-    {
-      /* The parent thread is supposed to report events.  Check whether
-        the TD_CREATE event is needed, too.  */
-      const int _idx = __td_eventword (TD_CREATE);
-      const uint32_t _mask = __td_eventmask (TD_CREATE);
-
-      if ((_mask & (__nptl_threads_events.event_bits[_idx]
-                   | pd->eventbuf.eventmask.event_bits[_idx])) != 0)
-       {
-         /* We have to report the new thread.  Make sure the thread
-            does not run far by forcing it to get a lock.  We lock it
-            here too so that the new thread cannot continue until we
-            tell it to.  */
-         lll_lock (pd->lock);
-
-         /* Create the thread.  */
-         if (__clone (start_thread_debug, STACK_VARIABLES_ARGS,
-                      CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
-                      CLONE_SETTLS | CLONE_PARENT_SETTID |
-                      CLONE_CHILD_CLEARTID | CLONE_DETACHED | 0,
-                      pd, &pd->tid, &desc.desc, &pd->tid) == -1)
-           /* Failed.  */
-           return errno;
-
-         /* We now have for sure more than one thread.  */
-         pd->header.data.multiple_threads = 1;
-
-         /* Now fill in the information about the new thread in
-            the newly created thread's data structure.  We cannot let
-            the new thread do this since we don't know whether it was
-            already scheduled when we send the event.  */
-         pd->eventbuf.eventnum = TD_CREATE;
-         pd->eventbuf.eventdata = pd;
-
-         /* Enqueue the descriptor.  */
-         do
-           pd->nextevent = __nptl_last_event;
-         while (atomic_compare_and_exchange_acq (&__nptl_last_event, pd,
-                                                 pd->nextevent) != 0);
-
-         /* Now call the function which signals the event.  */
-         __nptl_create_event ();
-
-         /* And finally restart the new thread.  */
-         lll_unlock (pd->lock);
-
-         return 0;
-       }
-    }
-
-#ifdef NEED_DL_SYSINFO
-  assert (THREAD_GETMEM (THREAD_SELF, header.data.sysinfo)
-         == pd->header.data.sysinfo);
-#endif
-
-  /* We rely heavily on various flags the CLONE function understands:
-
-     CLONE_VM, CLONE_FS, CLONE_FILES
-       These flags select semantics with shared address space and
-       file descriptors according to what POSIX requires.
-
-     CLONE_SIGNAL
-       This flag selects the POSIX signal semantics.
-
-     CLONE_SETTLS
-       The sixth parameter to CLONE determines the TLS area for the
-       new thread.
-
-     CLONE_PARENT_SETTID
-       The kernels writes the thread ID of the newly created thread
-       into the location pointed to by the fifth parameters to CLONE.
-
-       Note that it would be semantically equivalent to use
-       CLONE_CHILD_SETTID but it is be more expensive in the kernel.
-
-     CLONE_CHILD_CLEARTID
-       The kernels clears the thread ID of a thread that has called
-       sys_exit() - using the same parameter as CLONE_SETTID.
-
-     CLONE_DETACHED
-       No signal is generated if the thread exists and it is
-       automatically reaped.
-
-     The termination signal is chosen to be zero which means no signal
-     is sent.  */
-  if (__clone (start_thread, STACK_VARIABLES_ARGS,
-              CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
-              CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
-              CLONE_DETACHED | 0, pd, &pd->tid, &desc.desc, &pd->tid) == -1)
-    /* Failed.  */
-    return errno;
-
-  /* We now have for sure more than one thread.  */
-  THREAD_SETMEM (THREAD_SELF, header.data.multiple_threads, 1);
-
-  return 0;
-}
+/* The "thread register" gets initialized from a segment descriptor.
+   Initialize such a descriptor first.  */
+#define PREPARE_CREATE \
+  union user_desc_init desc;                                                 \
+                                                                             \
+  /* Describe the thread-local storage segment.  */                          \
+                                                                             \
+  /* The 'entry_number' field.  The first three bits of the segment          \
+     register value select the GDT, ignore them.  We get the index           \
+     from the value of the %gs register in the current thread.  */           \
+  desc.vals[0] = TLS_GET_GS () >> 3;                                         \
+  /* The 'base_addr' field.  Pointer to the TCB.  */                         \
+  desc.vals[1] = (unsigned long int) pd;                                     \
+  /* The 'limit' field.  We use 4GB which is 0xfffff pages.  */                      \
+  desc.vals[2] = 0xfffff;                                                    \
+  /* Collapsed value of the bitfield:                                        \
+       .seg_32bit = 1                                                        \
+       .contents = 0                                                         \
+       .read_exec_only = 0                                                   \
+       .limit_in_pages = 1                                                   \
+       .seg_not_present = 0                                                  \
+       .useable = 1 */                                                       \
+  desc.vals[3] = 0x51
+
+/* Value passed to 'clone' for initialization of the thread register.  */
+#define TLS_VALUE &desc.desc
+
+
+/* Get the real implementation.  */
+#include <nptl/sysdeps/pthread/createthread.c>
diff --git a/sysdeps/s390/Versions b/sysdeps/s390/Versions
new file mode 100644 (file)
index 0000000..7136af2
--- /dev/null
@@ -0,0 +1,6 @@
+ld {
+  GLIBC_2.3 {
+    # runtime interface to TLS
+    __tls_get_offset;
+  }
+}
\ No newline at end of file
diff --git a/sysdeps/s390/dl-tls.h b/sysdeps/s390/dl-tls.h
new file mode 100644 (file)
index 0000000..fbd85c1
--- /dev/null
@@ -0,0 +1,73 @@
+/* Thread-local storage handling in the ELF dynamic linker.  s390 version.
+   Copyright (C) 2003 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.  */
+
+
+/* Type used for the representation of TLS information in the GOT.  */
+typedef struct
+{
+  unsigned long int ti_module;
+  unsigned long int ti_offset;
+} tls_index;
+
+
+#ifdef SHARED
+/* This is the prototype for the GNU version.  */
+extern void *__tls_get_addr (tls_index *ti) attribute_hidden;
+extern unsigned long __tls_get_offset (unsigned long got_offset);
+
+/* The special thing about the s390 TLS ABI is that we do not have the
+   standard __tls_get_addr function but the __tls_get_offset function
+   which differs in two important aspects:
+   1) __tls_get_offset gets a got offset instead of a pointer to the
+      tls_index structure
+   2) __tls_get_offset returns the offset of the requested variable to
+      the thread descriptor instead of a pointer to the variable.
+ */
+#if defined __s390x__
+asm("\n\
+       .text\n\
+       .globl __tls_get_offset\n\
+       .type __tls_get_offset, @function\n\
+       .align 4\n\
+__tls_get_offset:\n\
+       la      %r2,0(%r2,%r12)\n\
+       jg      __tls_get_addr\n\
+");
+#elif defined __s390__
+asm("\n\
+       .text\n\
+       .globl __tls_get_offset\n\
+       .type __tls_get_offset, @function\n\
+       .align 4\n\
+__tls_get_offset:\n\
+       basr    %r3,0\n\
+0:     la      %r2,0(%r2,%r12)\n\
+       l       %r4,1f-0b(%r3)\n\
+       b       0(%r4,%r3)\n\
+1:     .long   __tls_get_addr - 0b\n\
+");
+#endif
+
+#define GET_ADDR_OFFSET \
+  (ti->ti_offset - (unsigned long) __builtin_thread_pointer ())
+
+#define __TLS_GET_ADDR(__ti) \
+  (__tls_get_addr(__ti) + (unsigned long) __builtin_thread_pointer ())
+
+#endif
diff --git a/sysdeps/s390/libc-tls.c b/sysdeps/s390/libc-tls.c
new file mode 100644 (file)
index 0000000..bc433f8
--- /dev/null
@@ -0,0 +1,37 @@
+/* Thread-local storage handling in the ELF dynamic linker.  IA-64 version.
+   Copyright (C) 2003 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.  */
+
+#include <sysdeps/generic/libc-tls.c>
+
+#if USE_TLS
+
+/* On s390, the literal pool entry that refers to __tls_get_offset
+   is not removed, even if all branches that use the literal pool
+   entry gets removed by TLS optimizations. To get binaries
+   statically linked __tls_get_offset is defined here but
+   aborts if it is used.  */
+
+void *
+__tls_get_offset (size_t m, size_t offset)
+{
+  abort ();
+}
+
+#endif
+
index 557c04e..6905814 100644 (file)
@@ -1,5 +1,5 @@
 /* Machine-dependent ELF dynamic relocation inline functions.  S390 Version.
-   Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
    Contributed by Carl Pederson & Martin Schwidefsky.
    This file is part of the GNU C Library.
 
@@ -312,13 +312,22 @@ _dl_start_user:\n\
 #define RTLD_START_SPECIAL_INIT /* nothing */
 #endif
 
-/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
-   PLT entries should not be allowed to define the value.
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+   TLS variable, so undefined references should not be allowed to
+   define the value.
    ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
    of the main executable's symbols, as for a COPY reloc.  */
-#define elf_machine_type_class(type) \
+#ifdef USE_TLS
+# define elf_machine_type_class(type) \
+  ((((type) == R_390_JMP_SLOT || (type) == R_390_TLS_DTPMOD                  \
+     || (type) == R_390_TLS_DTPOFF || (type) == R_390_TLS_TPOFF)             \
+    * ELF_RTYPE_CLASS_PLT)                                                   \
+   | (((type) == R_390_COPY) * ELF_RTYPE_CLASS_COPY))
+#else
+# define elf_machine_type_class(type) \
   ((((type) == R_390_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)  \
    | (((type) == R_390_COPY) * ELF_RTYPE_CLASS_COPY))
+#endif
 
 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
 #define ELF_MACHINE_JMP_SLOT    R_390_JMP_SLOT
@@ -372,25 +381,90 @@ elf_machine_rela (struct link_map *map, const Elf32_Rela *reloc,
 {
   const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
 
+#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
   if (__builtin_expect (r_type == R_390_RELATIVE, 0))
-    *reloc_addr = map->l_addr + reloc->r_addend;
-#ifndef RTLD_BOOTSTRAP
-  else if (__builtin_expect (r_type == R_390_NONE, 0))
-    return;
+    {
+# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
+      /* This is defined in rtld.c, but nowhere in the static libc.a;
+        make the reference weak so static programs can still link.
+        This declaration cannot be done when compiling rtld.c
+        (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the
+        common defn for _dl_rtld_map, which is incompatible with a
+        weak decl in the same file.  */
+#  ifndef SHARED
+      weak_extern (GL(dl_rtld_map));
+#  endif
+      if (map != &GL(dl_rtld_map)) /* Already done in rtld itself.  */
+# endif
+       *reloc_addr = map->l_addr + reloc->r_addend;
+    }
+  else
 #endif
+  if (__builtin_expect (r_type == R_390_NONE, 0))
+    return;
   else
     {
       const Elf32_Sym *const refsym = sym;
+#if defined USE_TLS && !defined RTLD_BOOTSTRAP
+      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+      Elf32_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
+#else
       Elf32_Addr value = RESOLVE (&sym, version, r_type);
+
+# ifndef RTLD_BOOTSTRAP
       if (sym)
+# endif
        value += sym->st_value;
+#endif /* use TLS and !RTLD_BOOTSTRAP */
 
       switch (r_type)
        {
        case R_390_GLOB_DAT:
        case R_390_JMP_SLOT:
-         *reloc_addr = value;
+         *reloc_addr = value + reloc->r_addend;
+         break;
+
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
+       case R_390_TLS_DTPMOD:
+# ifdef RTLD_BOOTSTRAP
+         /* During startup the dynamic linker is always the module
+            with index 1.
+            XXX If this relocation is necessary move before RESOLVE
+            call.  */
+         *reloc_addr = 1;
+# else
+         /* Get the information from the link map returned by the
+            resolv function.  */
+         if (sym_map != NULL)
+           *reloc_addr = sym_map->l_tls_modid;
+# endif
+         break;
+       case R_390_TLS_DTPOFF:
+# ifndef RTLD_BOOTSTRAP
+         /* During relocation all TLS symbols are defined and used.
+            Therefore the offset is already correct.  */
+         if (sym != NULL)
+           *reloc_addr = sym->st_value + reloc->r_addend;
+# endif
          break;
+       case R_390_TLS_TPOFF:
+         /* The offset is negative, forward from the thread pointer.  */
+# ifdef RTLD_BOOTSTRAP
+         *reloc_addr = sym->st_value + reloc->r_addend - map->l_tls_offset;
+# else
+         /* We know the offset of the object the symbol is contained in.
+            It is a negative value which will be added to the
+            thread pointer.  */
+         if (sym != NULL)
+           {
+             CHECK_STATIC_TLS (map, sym_map);
+             *reloc_addr = (sym->st_value + reloc->r_addend
+                            - sym_map->l_tls_offset);
+           }
+#endif
+         break;
+#endif  /* use TLS */
+
 #ifndef RTLD_BOOTSTRAP
        case R_390_COPY:
          if (sym == NULL)
diff --git a/sysdeps/s390/s390-32/elf/configure b/sysdeps/s390/s390-32/elf/configure
new file mode 100644 (file)
index 0000000..64eff1f
--- /dev/null
@@ -0,0 +1,52 @@
+# This file is generated from configure.in by Autoconf.  DO NOT EDIT!
+ # Local configure fragment for sysdeps/s390/elf.
+
+if test "$usetls" != no; then
+# Check for support of thread-local storage handling in assembler and
+# linker.
+echo "$as_me:$LINENO: checking for s390 TLS support" >&5
+echo $ECHO_N "checking for s390 TLS support... $ECHO_C" >&6
+if test "${libc_cv_390_tls+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat > conftest.s <<\EOF
+       .section ".tdata", "awT", @progbits
+foo:   .long   25
+       .text
+       .long   foo@TLSGD
+       .long   foo@TLSLDM
+       .long   foo@DTPOFF
+       .long   foo@NTPOFF
+       .long   foo@GOTNTPOFF
+       .long   foo@INDNTPOFF
+       l       %r1,foo@GOTNTPOFF(%r12)
+       l       %r1,0(%r1):tls_load:foo
+       bas     %r14,0(%r1,%r13):tls_gdcall:foo
+       bas     %r14,0(%r1,%r13):tls_ldcall:foo
+EOF
+if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  libc_cv_390_tls=yes
+else
+  libc_cv_390_tls=no
+fi
+rm -f conftest*
+fi
+echo "$as_me:$LINENO: result: $libc_cv_390_tls" >&5
+echo "${ECHO_T}$libc_cv_390_tls" >&6
+if test $libc_cv_390_tls = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_TLS_SUPPORT 1
+_ACEOF
+
+fi
+fi
+
+cat >>confdefs.h <<\_ACEOF
+#define PI_STATIC_AND_HIDDEN 1
+_ACEOF
+
diff --git a/sysdeps/s390/s390-32/elf/configure.in b/sysdeps/s390/s390-32/elf/configure.in
new file mode 100644 (file)
index 0000000..fcf9329
--- /dev/null
@@ -0,0 +1,37 @@
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/s390/elf.
+
+if test "$usetls" != no; then
+# Check for support of thread-local storage handling in assembler and
+# linker.
+AC_CACHE_CHECK(for s390 TLS support, libc_cv_390_tls, [dnl
+cat > conftest.S <<\EOF
+       .section ".tdata", "awT", @progbits
+foo:   .long   25
+       .text
+       .long   foo@TLSGD
+       .long   foo@TLSLDM
+       .long   foo@DTPOFF
+       .long   foo@NTPOFF
+       .long   foo@GOTNTPOFF
+       .long   foo@INDNTPOFF
+       l       %r1,foo@GOTNTPOFF(%r12)
+       l       %r1,0(%r1):tls_load:foo
+       bas     %r14,0(%r1,%r13):tls_gdcall:foo
+       bas     %r14,0(%r1,%r13):tls_ldcall:foo
+EOF
+dnl
+if AC_TRY_COMMAND(${CC-cc} -S $CFLAGS conftest.S 1>&AS_MESSAGE_LOG_FD); then
+  libc_cv_390_tls=yes
+else
+  libc_cv_390_tls=no
+fi
+rm -f conftest*])
+if test $libc_cv_390_tls = yes; then
+  AC_DEFINE(HAVE_TLS_SUPPORT)
+fi
+fi
+
+dnl It is always possible to access static and hidden symbols in an
+dnl position independent way.
+AC_DEFINE(PI_STATIC_AND_HIDDEN)
index a4033ee..e7ae3f7 100644 (file)
@@ -1,6 +1,6 @@
 /* Machine-dependent ELF dynamic relocation inline functions.
    64 bit S/390 Version.
-   Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
    Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
    This file is part of the GNU C Library.
 
@@ -284,13 +284,22 @@ _dl_start_user:\n\
 #define RTLD_START_SPECIAL_INIT /* nothing */
 #endif
 
-/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
-   PLT entries should not be allowed to define the value.
+/* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
+   TLS variable, so undefined references should not be allowed to
+   define the value.
    ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
    of the main executable's symbols, as for a COPY reloc.  */
-#define elf_machine_type_class(type) \
+#ifdef USE_TLS
+# define elf_machine_type_class(type) \
+  ((((type) == R_390_JMP_SLOT || (type) == R_390_TLS_DTPMOD                  \
+     || (type) == R_390_TLS_DTPOFF || (type) == R_390_TLS_TPOFF)             \
+    * ELF_RTYPE_CLASS_PLT)                                                   \
+   | (((type) == R_390_COPY) * ELF_RTYPE_CLASS_COPY))
+#else
+# define elf_machine_type_class(type) \
   ((((type) == R_390_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)  \
    | (((type) == R_390_COPY) * ELF_RTYPE_CLASS_COPY))
+#endif
 
 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
 #define ELF_MACHINE_JMP_SLOT   R_390_JMP_SLOT
@@ -340,18 +349,41 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
 {
   const unsigned int r_type = ELF64_R_TYPE (reloc->r_info);
 
+#if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
   if (__builtin_expect (r_type == R_390_RELATIVE, 0))
-    *reloc_addr = map->l_addr + reloc->r_addend;
-#ifndef RTLD_BOOTSTRAP
-  else if (__builtin_expect (r_type == R_390_NONE, 0))
-    return;
+    {
+# if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
+      /* This is defined in rtld.c, but nowhere in the static libc.a;
+        make the reference weak so static programs can still link.
+        This declaration cannot be done when compiling rtld.c
+        (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the
+        common defn for _dl_rtld_map, which is incompatible with a
+        weak decl in the same file.  */
+#  ifndef SHARED
+      weak_extern (GL(dl_rtld_map));
+#  endif
+      if (map != &GL(dl_rtld_map)) /* Already done in rtld itself.  */
+# endif
+       *reloc_addr = map->l_addr + reloc->r_addend;
+    }
+  else
 #endif
+  if (__builtin_expect (r_type == R_390_NONE, 0))
+    return;
   else
     {
       const Elf64_Sym *const refsym = sym;
+#if defined USE_TLS && !defined RTLD_BOOTSTRAP
+      struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
+      Elf64_Addr value = sym == NULL ? 0 : sym_map->l_addr + sym->st_value;
+#else
       Elf64_Addr value = RESOLVE (&sym, version, r_type);
+
+# ifndef RTLD_BOOTSTRAP
       if (sym)
+# endif
        value += sym->st_value;
+#endif /* use TLS and !RTLD_BOOTSTRAP */
 
       switch (r_type)
        {
@@ -359,6 +391,48 @@ elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc,
        case R_390_JMP_SLOT:
          *reloc_addr = value + reloc->r_addend;
          break;
+
+#if defined USE_TLS && (!defined RTLD_BOOTSTRAP || USE___THREAD)
+       case R_390_TLS_DTPMOD:
+# ifdef RTLD_BOOTSTRAP
+         /* During startup the dynamic linker is always the module
+            with index 1.
+            XXX If this relocation is necessary move before RESOLVE
+            call.  */
+         *reloc_addr = 1;
+# else
+         /* Get the information from the link map returned by the
+            resolv function.  */
+         if (sym_map != NULL)
+           *reloc_addr = sym_map->l_tls_modid;
+# endif
+         break;
+       case R_390_TLS_DTPOFF:
+# ifndef RTLD_BOOTSTRAP
+         /* During relocation all TLS symbols are defined and used.
+            Therefore the offset is already correct.  */
+         if (sym != NULL)
+           *reloc_addr = sym->st_value + reloc->r_addend;
+# endif
+         break;
+       case R_390_TLS_TPOFF:
+         /* The offset is negative, forward from the thread pointer.  */
+# ifdef RTLD_BOOTSTRAP
+         *reloc_addr = sym->st_value + reloc->r_addend - map->l_tls_offset;
+# else
+         /* We know the offset of the object the symbol is contained in.
+            It is a negative value which will be added to the
+            thread pointer.  */
+         if (sym != NULL)
+           {
+             CHECK_STATIC_TLS (map, sym_map);
+             *reloc_addr = (sym->st_value + reloc->r_addend
+                            - sym_map->l_tls_offset);
+           }
+#endif
+         break;
+#endif  /* use TLS */
+
 #ifndef RTLD_BOOTSTRAP
        case R_390_COPY:
          if (sym == NULL)
@@ -439,7 +513,7 @@ elf_machine_lazy_rel (struct link_map *map,
                      Elf64_Addr l_addr, const Elf64_Rela *reloc)
 {
   Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
-  const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
+  const unsigned int r_type = ELF64_R_TYPE (reloc->r_info);
   /* Check for unexpected PLT reloc type.  */
   if (__builtin_expect (r_type == R_390_JMP_SLOT, 1))
     {
diff --git a/sysdeps/s390/s390-64/elf/configure b/sysdeps/s390/s390-64/elf/configure
new file mode 100644 (file)
index 0000000..42fc6e6
--- /dev/null
@@ -0,0 +1,52 @@
+# This file is generated from configure.in by Autoconf.  DO NOT EDIT!
+ # Local configure fragment for sysdeps/s390/elf.
+
+if test "$usetls" != no; then
+# Check for support of thread-local storage handling in assembler and
+# linker.
+echo "$as_me:$LINENO: checking for s390 TLS support" >&5
+echo $ECHO_N "checking for s390 TLS support... $ECHO_C" >&6
+if test "${libc_cv_390_tls+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat > conftest.s <<\EOF
+       .section ".tdata", "awT", @progbits
+foo:   .long   25
+       .text
+       .quad   foo@TLSGD
+       .quad   foo@TLSLDM
+       .quad   foo@DTPOFF
+       .quad   foo@NTPOFF
+       .quad   foo@GOTNTPOFF
+       .quad   foo@INDNTPOFF
+       lg      %r1,foo@GOTNTPOFF(%r12)
+       lg      %r1,0(%r1):tls_load:foo
+       brasl   %r14,__tls_get_offset@plt:tls_gdcall:foo
+       brasl   %r14,__tls_get_offset@plt:tls_ldcall:foo
+EOF
+if { ac_try='${CC-cc} -c $CFLAGS conftest.s 1>&5'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  libc_cv_390_tls=yes
+else
+  libc_cv_390_tls=no
+fi
+rm -f conftest*
+fi
+echo "$as_me:$LINENO: result: $libc_cv_390_tls" >&5
+echo "${ECHO_T}$libc_cv_390_tls" >&6
+if test $libc_cv_390_tls = yes; then
+  cat >>confdefs.h <<\_ACEOF
+#define HAVE_TLS_SUPPORT 1
+_ACEOF
+
+fi
+fi
+
+cat >>confdefs.h <<\_ACEOF
+#define PI_STATIC_AND_HIDDEN 1
+_ACEOF
+
diff --git a/sysdeps/s390/s390-64/elf/configure.in b/sysdeps/s390/s390-64/elf/configure.in
new file mode 100644 (file)
index 0000000..ac953fc
--- /dev/null
@@ -0,0 +1,37 @@
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+# Local configure fragment for sysdeps/s390/elf.
+
+if test "$usetls" != no; then
+# Check for support of thread-local storage handling in assembler and
+# linker.
+AC_CACHE_CHECK(for s390 TLS support, libc_cv_390_tls, [dnl
+cat > conftest.S <<\EOF
+       .section ".tdata", "awT", @progbits
+foo:   .long   25
+       .text
+       .quad   foo@TLSGD
+       .quad   foo@TLSLDM
+       .quad   foo@DTPOFF
+       .quad   foo@NTPOFF
+       .quad   foo@GOTNTPOFF
+       .quad   foo@INDNTPOFF
+       lg      %r1,foo@GOTNTPOFF(%r12)
+       lg      %r1,0(%r1):tls_load:foo
+       brasl   %r14,__tls_get_offset@plt:tls_gdcall:foo
+       brasl   %r14,__tls_get_offset@plt:tls_ldcall:foo
+EOF
+dnl
+if AC_TRY_COMMAND(${CC-cc} -S $CFLAGS conftest.S 1>&AS_MESSAGE_LOG_FD); then
+  libc_cv_390_tls=yes
+else
+  libc_cv_390_tls=no
+fi
+rm -f conftest*])
+if test $libc_cv_390_tls = yes; then
+  AC_DEFINE(HAVE_TLS_SUPPORT)
+fi
+fi
+
+dnl It is always possible to access static and hidden symbols in an
+dnl position independent way.
+AC_DEFINE(PI_STATIC_AND_HIDDEN)
index c93570e..23fb464 100644 (file)
 #define _ERRNO_H       1
 #include <bits/errno.h>
 
-/*int __clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg);*/
-/* sys_clone(void *child_stack, unsigned long flags) */
+/* int __clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+               void *tls, pid_t *parent_tid, pid_t *child_tid);  */
+/* sys_clone  (void *child_stack, unsigned long flags,
+               pid_t *parent_tid, pid_t *child_tid, void *tls);  */
 
        .text
 ENTRY(__clone)
        /* Sanity check arguments & move registers */
+       lr      %r0,%r5                 /* move *arg out of the way */
        ltr     %r1,%r2                 /* no NULL function pointers */
        lhi     %r2,-EINVAL
        jz      SYSCALL_ERROR_LABEL
        ltr     %r3,%r3                 /* no NULL stack pointers */
        jz      SYSCALL_ERROR_LABEL
-       /* move child_stack and flags, then call SVC */
+       /* set up registers, then call SVC */
        lr      %r2,%r3
        lr      %r3,%r4
+       lm      %r4,%r5,96(%r15)
        svc     SYS_ify(clone)
        ltr     %r2,%r2                 /* check return code */
        jm      SYSCALL_ERROR_LABEL
@@ -45,10 +49,10 @@ ENTRY(__clone)
        br      %r14
 
 thread_start:
-       /* fn is in gpr 1, arg in gpr 5 */
-       lr      %r2,%r5         /* set first parameter to void *arg */
-       sr      %r11,%r11       /* terminate the stack frame */
+       /* fn is in gpr 1, arg in gpr 0 */
+       lr      %r2,%r0         /* set first parameter to void *arg */
        ahi     %r15,-96        /* make room on the stack for the save area */
+       xc      0(4,%r15),0(%r15)
        basr    %r14,%r1        /* jump to fn */
 #ifdef PIC
        basr    %r12,0
index 98b0072..94d772f 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
    Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
    This file is part of the GNU C Library.
 
        .text
 ENTRY(__syscall_error)
 #ifndef PIC
-#ifndef _LIBC_REENTRANT
-       lcr     %r2,%r2
-       basr    %r1,0
-.L0:    l       %r1,.L1-.L0(%r1)
-       st      %r2,0(0,%r1)
-       lhi     %r2,-1
-       br      %r14
-.L1:    .long  errno
-#else
-       stm     %r11,%r15,44(%r15)
-       lr      %r0,%r15
-       ahi     %r15,-96
-       st      %r0,0(%r15)
-       lcr     %r11,%r2
-       basr    %r13,0
-.L0:   l       %r1,.L1-.L0(%r13)
-       basr    %r14,%r1
-       st      %r11,0(%r2)
-       lhi     %r2,-1
-       l       %r15,0(%r15)
-       lm      %r11,%r15,44(%r15)
-       br      %r14
-.L1:   .long  __errno_location
+# if USE___THREAD
+#  ifndef NOT_IN_libc
+#   define SYSCALL_ERROR_ERRNO __libc_errno
+#  else
+#   define SYSCALL_ERROR_ERRNO errno
+#  endif
+       basr    %r1,0
+0:     l       %r1,1f-0b(%r1)
+       ear     %r3,%a0
+       lcr     %r2,%r2
+       st      %r2,0(%r1,%r3)
+       lhi     %r2,-1
+       br      %r14
+1:     .long   SYSCALL_ERROR_ERRNO@ntpoff
+# elif !defined _LIBC_REENTRANT
+       basr    %r1,0
+0:     l       %r1,1f-0b(%r1)
+       lcr     %r2,%r2
+       st      %r2,0(%r1)
+       lhi     %r2,-1
+       br      %r14
+1:     .long  errno
+# else
+       stm     %r13,%r15,52(%r15)
+       lr      %r0,%r15
+       ahi     %r15,-96
+       lcr     %r13,%r2
+       st      %r0,0(%r15)
+       basr    %r1,0
+0:     l       %r1,1f-0b(%r1)
+       basr    %r14,%r1
+       st      %r13,0(%r2)
+       lm      %r13,%r15,148(%r15)
+       lhi     %r2,-1
+       br      %r14
+1:     .long  __errno_location
 #endif
 #else
-#ifndef _LIBC_REENTRANT
-       basr    %r1,0
-.L0:    al      %r1,.L1-.L0(%r1)
-       l       %r1,errno@GOT12(%r1)
-       lcr     %r2,%r2
-       st      %r2,0(0,%r1)
-       lhi     %r2,-1
-       br      %r14
-.L1:    .long   _GLOBAL_OFFSET_TABLE_-0b
-#else
-       stm     %r11,%r15,44(%r15)
-       lr      %r0,%r15
-       ahi     %r15,-96
-       st      %r0,0(%r15)
-       lcr     %r11,%r2
-       basr    %r13,0
-.L0:   l       %r12,.L1-.L0(%r13)
-       ar      %r12,%r13
-       l       %r14,.L2-.L0(%r13)
-       bas     %r14,0(%r14,%r13)
-       st      %r11,0(0,%r2)
-       lhi     %r2,-1
-       l       %r15,0(%r15)
-       lm      %r11,%r15,44(%r15)
-       br      %r14
-.L1:   .long _GLOBAL_OFFSET_TABLE_ - .L0
-.L2:    .long __errno_location@PLT - .L0
-#endif
+# if RTLD_PRIVATE_ERRNO
+       basr    %r1,0
+0:     al      %r1,1f-0b(%r1)
+       lcr     %r2,%r2
+       st      %r2,0(%r1)
+       lhi     %r2,-1
+       br      %r14
+1:     .long   errno - 0b
+# elif USE___THREAD
+#  ifndef NOT_IN_libc
+#   define SYSCALL_ERROR_ERRNO __libc_errno
+#  else
+#   define SYSCALL_ERROR_ERRNO errno
+#  endif
+       basr    %r1,0
+0:     al      %r1,1f-0b(%r1)
+       ear     %r3,%a0
+       l       %r1,SYSCALL_ERROR_ERRNO@gotntpoff(%r1)
+       lcr     %r2,%r2
+       st      %r2,0(%r1,%r3)
+       lhi     %r2,-1
+       br      %r14
+1:     .long   _GLOBAL_OFFSET_TABLE_-0b
+# elif !defined _LIBC_REENTRANT
+       basr    %r1,0
+0:     al      %r1,1f-0b(%r1)
+       l       %r1,errno@GOT(%r1)
+       lcr     %r2,%r2
+       st      %r2,0(0,%r1)
+       lhi     %r2,-1
+       br      %r14
+1:     .long   _GLOBAL_OFFSET_TABLE_-0b
+# else
+       stm     %r11,%r15,44(%r15)
+       lr      %r0,%r15
+       ahi     %r15,-96
+       lcr     %r11,%r2
+       st      %r0,0(%r15)
+       basr    %r13,0
+0:     l       %r12,1f-0b(%r13)
+       l       %r1,2f-0b(%r13)
+       la      %r12,0(%r12,%r13)
+       bas     %r14,0(%r1,%r13)
+       st      %r11,0(%r2)
+       lm      %r11,%r15,140(%r15)
+       lhi     %r2,-1
+       br      %r14
+1:     .long _GLOBAL_OFFSET_TABLE_-0b
+2:     .long __errno_location@PLT-0b
+# endif
 #endif
 
 END (__syscall_error)
index e89e6a1..f7bfb8d 100644 (file)
@@ -45,8 +45,6 @@
    number.  Linus said he will make sure the no syscall returns a value
    in -1 .. -4095 as a valid result so we can savely test with -4095.  */
 
-#define SYSCALL_ERROR_LABEL 0f
-
 #undef PSEUDO
 #define        PSEUDO(name, syscall_name, args)                                      \
   .text;                                                                      \
     DO_CALL (syscall_name, args);                                             \
     lhi  %r4,-4095 ;                                                          \
     clr  %r2,%r4 ;                                                           \
-    jnl  SYSCALL_ERROR_LABEL ;                                                \
-  L(pseudo_end):
+    jnl  SYSCALL_ERROR_LABEL
 
 #undef PSEUDO_END
 #define PSEUDO_END(name)                                                     \
   SYSCALL_ERROR_HANDLER;                                                     \
   END (name)
 
-#ifndef _LIBC_REENTRANT
 #ifndef PIC
-#define SYSCALL_ERROR_HANDLER                                                 \
-0:  lcr     %r2,%r2 ;                                                         \
-    basr    %r1,0 ;                                                           \
-1:  l       %r1,2f-1b(%r1)                                                    \
-    st      %r2,0(%r1)                                                        \
-    lhi     %r2,-1                                                            \
-    br      %r14                                                              \
-2:  .long   errno
+# define SYSCALL_ERROR_LABEL 0f
+# define SYSCALL_ERROR_HANDLER \
+0:  basr  %r1,0;                                                             \
+1:  l     %r1,2f-1b(%r1);                                                    \
+    br    %r1;                                                               \
+2:  .long syscall_error
 #else
-#define SYSCALL_ERROR_HANDLER                                                \
-0:  basr    %r1,0 ;                                                           \
-1:  al      %r1,2f-1b(%r1) ;                                                  \
-    l       %r1,errno@GOT12(%r1) ;                                            \
-    lcr     %r2,%r2 ;                                                        \
-    st      %r2,0(%r1) ;                                                     \
-    lhi     %r2,-1 ;                                                          \
-    br      %r14 ;                                                            \
-2:  .long   _GLOBAL_OFFSET_TABLE_-1b
+# if RTLD_PRIVATE_ERRNO
+#  define SYSCALL_ERROR_LABEL 0f
+#  define SYSCALL_ERROR_HANDLER \
+0:  basr  %r1,0;                                                             \
+1:  al    %r1,2f-1b(%r1);                                                    \
+    lcr   %r2,%r2;                                                           \
+    st    %r2,0(%r1);                                                        \
+    lhi   %r2,-1;                                                            \
+    br    %r14;                                                                      \
+2:  .long errno-1b
+# elif defined _LIBC_REENTRANT
+#  if USE___THREAD
+#   ifndef NOT_IN_libc
+#    define SYSCALL_ERROR_ERRNO __libc_errno
+#   else
+#    define SYSCALL_ERROR_ERRNO errno
+#   endif
+#   define SYSCALL_ERROR_LABEL 0f
+#   define SYSCALL_ERROR_HANDLER \
+0:  lcr   %r0,%r2;                                                           \
+    basr  %r1,0;                                                             \
+1:  al    %r1,2f-1b(%r1);                                                    \
+    l     %r1,SYSCALL_ERROR_ERRNO@gotntpoff(%r1)                             \
+    ear   %r2,%a0                                                            \
+    st    %r0,0(%r1,%r2);                                                    \
+    lhi   %r2,-1;                                                            \
+    br    %r14;                                                                      \
+2:  .long _GLOBAL_OFFSET_TABLE_-1b
+#  else
+#   define SYSCALL_ERROR_LABEL 0f
+#   define SYSCALL_ERROR_HANDLER \
+0:  basr  %r1,0;                                                             \
+1:  al    %r1,2f-1b(%r1);                                                    \
+    br    %r1;                                                               \
+2:  .long syscall_error@plt-1b
+#  endif
+# else
+#  define SYSCALL_ERROR_LABEL 0f
+#  define SYSCALL_ERROR_HANDLER \
+0:  basr  %r1,0;                                                             \
+1:  al    %r1,2f-1b(%r1);                                                    \
+    l     %r1,errno@GOT(%r1);                                                \
+    lcr   %r2,%r2;                                                           \
+    st    %r2,0(%r1);                                                        \
+    lhi   %r2,-1;                                                            \
+    br    %r14;                                                                      \
+2:  .long _GLOBAL_OFFSET_TABLE_-1b
+# endif /* _LIBC_REENTRANT */
 #endif /* PIC */
-#else
-#define SYSCALL_ERROR_HANDLER                                                 \
-0:  basr    %r1,0 ;                                                           \
-1:  al      %r1,2f-1b(%r1) ;                                                  \
-    br      %r1 ;                                                             \
-2:  .long   __syscall_error@PLT-1b
-#endif /* _LIBC_REENTRANT */
 
 /* Linux takes system call arguments in registers:
 
index 992cb2f..1174118 100644 (file)
 #define _ERRNO_H       1
 #include <bits/errno.h>
 
+/* int __clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
+               void *tls, pid_t *parent_tid, pid_t *child_tid);  */
+/* sys_clone  (void *child_stack, unsigned long flags,
+               pid_t *parent_tid, pid_t *child_tid, void *tls);  */
+
        .text
 ENTRY(__clone)
        /* Sanity check arguments & move registers */
+       lgr     %r0,%r5                 /* move *arg out of the way */
        ltgr    %r1,%r2                 /* no NULL function pointers */
        lghi    %r2,-EINVAL
-       j     SYSCALL_ERROR_LABEL
+       jgz     SYSCALL_ERROR_LABEL
        ltgr    %r3,%r3                 /* no NULL stack pointers */
-       j     SYSCALL_ERROR_LABEL
-       /* move child_stack and flags, then call SVC */
+       jgz     SYSCALL_ERROR_LABEL
+       /* set up registers, then call SVC */
        lgr     %r2,%r3
        lgr     %r3,%r4
+       lmg     %r4,%r5,160(%r15)
        svc     SYS_ify(clone)
        ltgr    %r2,%r2                 /* check return code */
-       j     SYSCALL_ERROR_LABEL
+       jgm     SYSCALL_ERROR_LABEL
        jz      thread_start
        br      %r14
 
 thread_start:
-       /* fn is in gpr 1, arg in gpr 5 */
-       lgr     %r2,%r5         /* set first parameter to void *arg */
-       sgr     %r11,%r11       /* terminate the stack frame */
+       /* fn is in gpr 1, arg in gpr 0 */
+       lgr     %r2,%r0         /* set first parameter to void *arg */
        aghi    %r15,-160       /* make room on the stack for the save area */
+       xc      0(8,%r15),0(%r15)
        basr    %r14,%r1        /* jump to fn */
 #ifdef PIC
-       larl    %r12,_GLOBAL_OFFSET_TABLE_
-#endif
        jg      _exit@PLT       /* branch to _exit -> thread termination */
+#else
+       jg      _exit           /* branch to _exit -> thread termination */
+#endif
 PSEUDO_END (__clone)
 weak_alias (__clone, clone)
index 2320590..8c94fd4 100644 (file)
@@ -55,7 +55,7 @@ ENTRY(__mmap)
         /* Check gpr 2 for error.  */ 
         lghi    %r0,-4096
         clgr    %r2,%r0
-        jnl     SYSCALL_ERROR_LABEL
+        jgnl    SYSCALL_ERROR_LABEL
 
         /* Successful; return the syscall's value.  */
         br      %r14
index c9bd02b..3a2454e 100644 (file)
@@ -93,7 +93,7 @@ ENTRY(__socket)
        /* gpr2 is < 0 if there was an error.  */
         lghi    %r0,-125 
         clgr    %r2,%r0
-        jnl     SYSCALL_ERROR_LABEL
+        jgnl    SYSCALL_ERROR_LABEL
  
        /* Successful; return the syscall's value.  */
        br      %r14
index 047c667..718d559 100644 (file)
@@ -45,7 +45,7 @@ ENTRY (syscall)
 
        lghi   %r0,-4095
        clgr   %r2,%r0             /* Check R2 for error.  */
-       jnl    SYSCALL_ERROR_LABEL
+       jgnl   SYSCALL_ERROR_LABEL
        br     %r14                /* Return to caller.  */
 .L1:   .word  0x0A00              /* Opcode for SVC 0.  */
 PSEUDO_END (syscall)
index a29b0b9..84c747a 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
    Contributed by Martin Schwidefsky (schwidefsky@de.ibm.com).
    This file is part of the GNU C Library.
 
 #undef CALL_MCOUNT
 #define CALL_MCOUNT
 
-        .text
+.text
 ENTRY(__syscall_error)
 #ifndef PIC
-#ifndef _LIBC_REENTRANT
-       lcr     %r2,%r2
-       larl    %r1,errno
-       st      %r2,0(%r1)
-       lghi    %r2,-1
-       br      %r14
-#else
-        stmg    %r13,%r15,104(%r15)
-        lgr     %r0,%r15
-        aghi    %r15,-160
-        lcr     %r13,%r2
-        stg     %r0,0(%r15)
-       brasl   %r14,__errno_location
-       st      %r13,0(%r2)
-       lmg     %r13,%r15,264(%r15)
-       lghi    %r2,-1
-       br      %r14
+# if USE___THREAD
+#  ifndef NOT_IN_libc
+#   define SYSCALL_ERROR_ERRNO __libc_errno
+#  else
+#   define SYSCALL_ERROR_ERRNO errno
+#  endif
+       basr    %r1,0
+0:     lg      %r1,1f-0b(%r1)
+       ear     %r3,%a0
+       sllg    %r3,%r3,32
+       ear     %r3,%a1
+       lcr     %r2,%r2
+       st      %r2,0(%r1,%r3)
+       lghi    %r2,-1
+       br      %r14
+1:     .quad   SYSCALL_ERROR_ERRNO@ntpoff
+# elif !defined _LIBC_REENTRANT
+       larl    %r1,errno
+       lcr     %r2,%r2
+       st      %r2,0(%r1)
+       lghi    %r2,-1
+       br      %r14
+# else
+       stmg    %r13,%r15,104(%r15)
+       lgr     %r0,%r15
+       aghi    %r15,-160
+       lcr     %r13,%r2
+       stg     %r0,0(%r15)
+       brasl   %r14,__errno_location
+       st      %r13,0(%r2)
+       lmg     %r13,%r15,264(%r15)
+       lghi    %r2,-1
+       br      %r14
 #endif
 #else
-#ifndef _LIBC_REENTRANT
-       larl    %r1,_GLOBAL_OFFSET_TABLE_
-       lg      %r1,errno@GOT(%r1)
-       lcr     %r2,%r2
-       st      %r2,0(%r1)
-       lghi    %r2,-1
-       br      %r14
-#else
-        stmg    %r13,%r15,104(%r15)
-        lgr     %r0,%r15
-        aghi    %r15,-160
-        lcr     %r13,%r2
-        stg     %r0,0(%r15)
-       brasl   %r14,__errno_location@PLT
-       st      %r13,0(%r2)
-       lmg     %r13,%r15,264(%r15)
-       lghi    %r2,-1
-       br      %r14
-#endif
+# if RTLD_PRIVATE_ERRNO
+       larl    %r1,errno
+       lcr     %r2,%r2
+       st      %r2,0(%r1)
+       lghi    %r2,-1
+       br      %r14
+# elif USE___THREAD
+#  ifndef NOT_IN_libc
+#   define SYSCALL_ERROR_ERRNO __libc_errno
+#  else
+#   define SYSCALL_ERROR_ERRNO errno
+#  endif
+       larl    %r1,_GLOBAL_OFFSET_TABLE_
+       lg      %r1,SYSCALL_ERROR_ERRNO@gotntpoff(%r1)
+       ear     %r3,%a0
+       sllg    %r3,%r3,32
+       ear     %r3,%a1
+       lcr     %r2,%r2
+       st      %r2,0(%r1,%r3)
+       lghi    %r2,-1
+       br      %r14
+# elif !defined _LIBC_REENTRANT
+       larl    %r1,_GLOBAL_OFFSET_TABLE_
+       lg      %r1,errno@GOT(%r1)
+       lcr     %r2,%r2
+       st      %r2,0(%r1)
+       lghi    %r2,-1
+       br      %r14    
+# else
+       stmg    %r13,%r15,104(%r15)
+       lgr     %r0,%r15
+       aghi    %r15,-160
+       lcr     %r13,%r2
+       stg     %r0,0(%r15)
+       brasl   %r14,__errno_location@PLT
+       st      %r13,0(%r2)
+       lmg     %r13,%r15,264(%r15)
+       lghi    %r2,-1
+       br      %r14
+# endif
 #endif
 
 END (__syscall_error)
index dbe77df..976fd26 100644 (file)
@@ -46,8 +46,6 @@
    number.  Linus said he will make sure the no syscall returns a value
    in -1 .. -4095 as a valid result so we can savely test with -4095.  */
 
-#define SYSCALL_ERROR_LABEL 0f
-
 #undef PSEUDO
 #define        PSEUDO(name, syscall_name, args)                                      \
   .text;                                                                     \
     DO_CALL (syscall_name, args);                                            \
     lghi %r4,-4095 ;                                                         \
     clgr %r2,%r4 ;                                                           \
-    jnl SYSCALL_ERROR_LABEL ;                                                \
-  L(pseudo_end):
+    jgnl SYSCALL_ERROR_LABEL
 
 #undef PSEUDO_END
 #define PSEUDO_END(name)                                                     \
   SYSCALL_ERROR_HANDLER;                                                     \
   END (name)
 
-#ifndef _LIBC_REENTRANT
 #ifndef PIC
-#define SYSCALL_ERROR_HANDLER                                                \
-0:  lcr            %r2,%r2 ;                                                         \
-    larl    %r1,errno ;                                                              \
-    st     %r2,0(%r1) ;                                                      \
-    lghi    %r2,-1 ;                                                         \
-    br     %r14
+# define SYSCALL_ERROR_LABEL syscall_error
+# define SYSCALL_ERROR_HANDLER
 #else
-#define SYSCALL_ERROR_HANDLER                                                \
-0:  larl    %r1,_GLOBAL_OFFSET_TABLE_ ;                                              \
-    lg     %r1,errno@GOT(%r1) ;                                              \
-    lcr            %r2,%r2 ;                                                         \
-    st     %r2,0(%r1) ;                                                      \
-    lghi    %r2,-1 ;                                                         \
-    br     %r14
+# if RTLD_PRIVATE_ERRNO
+#  define SYSCALL_ERROR_LABEL 0f
+#  define SYSCALL_ERROR_HANDLER \
+0:  larl  %r1,errno;                                                         \
+    lcr   %r2,%r2;                                                           \
+    st    %r2,0(%r1);                                                        \
+    lghi  %r2,-1;                                                            \
+    br    %r14
+# elif defined _LIBC_REENTRANT
+#  if USE___THREAD
+#   ifndef NOT_IN_libc
+#    define SYSCALL_ERROR_ERRNO __libc_errno
+#   else
+#    define SYSCALL_ERROR_ERRNO errno
+#   endif
+#   define SYSCALL_ERROR_LABEL 0f
+#   define SYSCALL_ERROR_HANDLER \
+0:  lcr   %r0,%r2;                                                           \
+    larl  %r1,SYSCALL_ERROR_ERRNO@indntpoff;                                 \
+    lg    %r1,0(%r1);                                                        \
+    ear   %r2,%a0;                                                           \
+    sllg  %r2,%r2,32;                                                        \
+    ear   %r2,%a1;                                                           \
+    st    %r0,0(%r1,%r2);                                                    \
+    lghi   %r2,-1;                                                           \
+    br    %r14
+#  else
+#   define SYSCALL_ERROR_LABEL syscall_error@plt
+#   define SYSCALL_ERROR_HANDLER
+#  endif
+# else
+#  define SYSCALL_ERROR_LABEL 0f
+#  define SYSCALL_ERROR_HANDLER \
+0:  larl  %r1,_GLOBAL_OFFSET_TABLE_;                                         \
+    lg    %r1,errno@GOT(%r1);                                                \
+    lcr   %r2,%r2;                                                           \
+    st    %r2,0(%r1);                                                        \
+    lghi  %r2,-1;                                                            \
+    br    %r14
+# endif /* _LIBC_REENTRANT */
 #endif /* PIC */
-#else
-#define SYSCALL_ERROR_HANDLER                                                \
-0:  jg     __syscall_error@PLT
-#endif /* _LIBC_REENTRANT */
 
 /* Linux takes system call arguments in registers: