aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2003-01-28 10:42:28 +0000
committerUlrich Drepper <drepper@redhat.com>2003-01-28 10:42:28 +0000
commite6ebd2e4db59da6c1726ecfa3516f1f1b3048442 (patch)
treedfa3797737a8e4dc76ed38e52cf7baa27e936003
parent772e3426a7b6f5200cb1029d41308b8b666cdbab (diff)
downloadglibc-e6ebd2e4db59da6c1726ecfa3516f1f1b3048442.tar
glibc-e6ebd2e4db59da6c1726ecfa3516f1f1b3048442.tar.gz
glibc-e6ebd2e4db59da6c1726ecfa3516f1f1b3048442.tar.bz2
glibc-e6ebd2e4db59da6c1726ecfa3516f1f1b3048442.zip
Update.
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.
-rw-r--r--ChangeLog34
-rw-r--r--elf/elf.h103
-rw-r--r--elf/tls-macros.h190
-rw-r--r--linuxthreads/ChangeLog14
-rw-r--r--linuxthreads/sysdeps/s390/s390-32/pt-machine.h8
-rw-r--r--linuxthreads/sysdeps/s390/s390-64/pt-machine.h8
-rw-r--r--linuxthreads/sysdeps/s390/tls.h87
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h2
-rw-r--r--linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S2
-rw-r--r--nptl/ChangeLog7
-rw-r--r--nptl/sysdeps/pthread/createthread.c145
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/createthread.c170
-rw-r--r--sysdeps/s390/Versions6
-rw-r--r--sysdeps/s390/dl-tls.h73
-rw-r--r--sysdeps/s390/libc-tls.c37
-rw-r--r--sysdeps/s390/s390-32/dl-machine.h92
-rw-r--r--sysdeps/s390/s390-32/elf/configure52
-rw-r--r--sysdeps/s390/s390-32/elf/configure.in37
-rw-r--r--sysdeps/s390/s390-64/dl-machine.h92
-rw-r--r--sysdeps/s390/s390-64/elf/configure52
-rw-r--r--sysdeps/s390/s390-64/elf/configure.in37
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/clone.S16
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S139
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h84
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/clone.S26
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/mmap.S2
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/socket.S2
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/syscall.S2
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S113
-rw-r--r--sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h65
30 files changed, 1346 insertions, 351 deletions
diff --git a/ChangeLog b/ChangeLog
index ef422b7f5e..bf8f96fe5e 100644
--- 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
diff --git a/elf/elf.h b/elf/elf.h
index 89ce5684db..30d0669040 100644
--- 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
diff --git a/elf/tls-macros.h b/elf/tls-macros.h
index 2de4b1a1af..ea9ec56376 100644
--- a/elf/tls-macros.h
+++ b/elf/tls-macros.h
@@ -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
diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog
index 2949321c65..80de0debab 100644
--- a/linuxthreads/ChangeLog
+++ b/linuxthreads/ChangeLog
@@ -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,
diff --git a/linuxthreads/sysdeps/s390/s390-32/pt-machine.h b/linuxthreads/sysdeps/s390/s390-32/pt-machine.h
index 18b5919544..ee35320059 100644
--- a/linuxthreads/sysdeps/s390/s390-32/pt-machine.h
+++ b/linuxthreads/sysdeps/s390/s390-32/pt-machine.h
@@ -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
diff --git a/linuxthreads/sysdeps/s390/s390-64/pt-machine.h b/linuxthreads/sysdeps/s390/s390-64/pt-machine.h
index 92ebe1ecc4..c0f30789c2 100644
--- a/linuxthreads/sysdeps/s390/s390-64/pt-machine.h
+++ b/linuxthreads/sysdeps/s390/s390-64/pt-machine.h
@@ -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
diff --git a/linuxthreads/sysdeps/s390/tls.h b/linuxthreads/sysdeps/s390/tls.h
index d872bb7553..11f31ba88a 100644
--- a/linuxthreads/sysdeps/s390/tls.h
+++ b/linuxthreads/sysdeps/s390/tls.h
@@ -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 */
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
index ce4afb1d7b..4e54e550c2 100644
--- a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
+++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h
@@ -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
diff --git a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S
index e01d4389d3..efc9710d7b 100644
--- a/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S
+++ b/linuxthreads/sysdeps/unix/sysv/linux/s390/s390-64/vfork.S
@@ -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
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 9f5080b8aa..1f293f505a 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -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
index 0000000000..b6898368ef
--- /dev/null
+++ b/nptl/sysdeps/pthread/createthread.c
@@ -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;
+}
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/createthread.c b/nptl/sysdeps/unix/sysv/linux/i386/createthread.c
index def163350f..37e3d94996 100644
--- a/nptl/sysdeps/unix/sysv/linux/i386/createthread.c
+++ b/nptl/sysdeps/unix/sysv/linux/i386/createthread.c
@@ -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.
@@ -17,141 +17,33 @@
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
index 0000000000..7136af2760
--- /dev/null
+++ b/sysdeps/s390/Versions
@@ -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
index 0000000000..fbd85c1753
--- /dev/null
+++ b/sysdeps/s390/dl-tls.h
@@ -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
index 0000000000..bc433f8f6f
--- /dev/null
+++ b/sysdeps/s390/libc-tls.c
@@ -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
+
diff --git a/sysdeps/s390/s390-32/dl-machine.h b/sysdeps/s390/s390-32/dl-machine.h
index 557c04e4ea..6905814c41 100644
--- a/sysdeps/s390/s390-32/dl-machine.h
+++ b/sysdeps/s390/s390-32/dl-machine.h
@@ -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
index 0000000000..64eff1f05f
--- /dev/null
+++ b/sysdeps/s390/s390-32/elf/configure
@@ -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
index 0000000000..fcf9329995
--- /dev/null
+++ b/sysdeps/s390/s390-32/elf/configure.in
@@ -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)
diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h
index a4033eeed1..e7ae3f77f8 100644
--- a/sysdeps/s390/s390-64/dl-machine.h
+++ b/sysdeps/s390/s390-64/dl-machine.h
@@ -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
index 0000000000..42fc6e6a5f
--- /dev/null
+++ b/sysdeps/s390/s390-64/elf/configure
@@ -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
index 0000000000..ac953fcff3
--- /dev/null
+++ b/sysdeps/s390/s390-64/elf/configure.in
@@ -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)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/clone.S b/sysdeps/unix/sysv/linux/s390/s390-32/clone.S
index c93570ed72..23fb4647ee 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/clone.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/clone.S
@@ -24,20 +24,24 @@
#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
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S
index 98b00722d8..94d772f67e 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.S
@@ -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.
@@ -31,59 +31,94 @@
.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)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
index e89e6a1425..f7bfb8dac1 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/sysdep.h
@@ -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; \
@@ -54,42 +52,70 @@
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:
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/clone.S b/sysdeps/unix/sysv/linux/s390/s390-64/clone.S
index 992cb2f10f..117411824f 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/clone.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/clone.S
@@ -25,32 +25,40 @@
#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
- jz SYSCALL_ERROR_LABEL
+ jgz SYSCALL_ERROR_LABEL
ltgr %r3,%r3 /* no NULL stack pointers */
- jz 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 */
- jm 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)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/mmap.S b/sysdeps/unix/sysv/linux/s390/s390-64/mmap.S
index 23205901d4..8c94fd4c28 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/mmap.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/mmap.S
@@ -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
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/socket.S b/sysdeps/unix/sysv/linux/s390/s390-64/socket.S
index c9bd02baee..3a2454eba4 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/socket.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/socket.S
@@ -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
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/syscall.S b/sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
index 047c667542..718d559c3b 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/syscall.S
@@ -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)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S b/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S
index a29b0b983a..84c747aef0 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.S
@@ -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.
@@ -29,47 +29,84 @@
#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)
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h b/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
index dbe77df979..976fd26f50 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/sysdep.h
@@ -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; \
@@ -55,35 +53,58 @@
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: