diff options
author | Ulrich Drepper <drepper@redhat.com> | 2003-01-28 10:42:28 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2003-01-28 10:42:28 +0000 |
commit | e6ebd2e4db59da6c1726ecfa3516f1f1b3048442 (patch) | |
tree | dfa3797737a8e4dc76ed38e52cf7baa27e936003 /nptl/sysdeps | |
parent | 772e3426a7b6f5200cb1029d41308b8b666cdbab (diff) | |
download | glibc-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/sysdeps')
-rw-r--r-- | nptl/sysdeps/pthread/createthread.c | 145 | ||||
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/i386/createthread.c | 170 |
2 files changed, 176 insertions, 139 deletions
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> |