aboutsummaryrefslogtreecommitdiff
path: root/nptl
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 /nptl
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.
Diffstat (limited to 'nptl')
-rw-r--r--nptl/ChangeLog7
-rw-r--r--nptl/sysdeps/pthread/createthread.c145
-rw-r--r--nptl/sysdeps/unix/sysv/linux/i386/createthread.c170
3 files changed, 183 insertions, 139 deletions
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>