mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-30 22:43:12 +03:00
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.
This commit is contained in:
145
nptl/sysdeps/pthread/createthread.c
Normal file
145
nptl/sysdeps/pthread/createthread.c
Normal file
@ -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;
|
||||
}
|
Reference in New Issue
Block a user