Adjust for new form of compare&exchange macros.
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / pthread / createthread.c
1 /* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <sched.h>
21 #include <setjmp.h>
22 #include <signal.h>
23 #include <stdlib.h>
24 #include <atomic.h>
25 #include <ldsodefs.h>
26 #include <tls.h>
27
28
29 #define CLONE_SIGNAL            (CLONE_SIGHAND | CLONE_THREAD)
30
31 /* Unless otherwise specified, the thread "register" is going to be
32    initialized with a pointer to the TCB.  */
33 #ifndef TLS_VALUE
34 # define TLS_VALUE pd
35 #endif
36
37 #ifndef ARCH_CLONE
38 # define ARCH_CLONE __clone
39 #endif
40
41
42 #ifndef TLS_MULTIPLE_THREADS_IN_TCB
43 /* Variable set to a nonzero value if more than one thread runs or ran.  */
44 int __pthread_multiple_threads attribute_hidden;
45 /* Pointer to the corresponding variable in libc.  */
46 int *__libc_multiple_threads_ptr attribute_hidden;
47 #endif
48
49
50 static int
51 create_thread (struct pthread *pd, STACK_VARIABLES_PARMS)
52 {
53 #ifdef PREPARE_CREATE
54   PREPARE_CREATE;
55 #endif
56
57 #ifdef TLS_TCB_AT_TP
58   assert (pd->header.tcb != NULL);
59 #endif
60
61   if (__builtin_expect (THREAD_GETMEM (THREAD_SELF, report_events), 0))
62     {
63       /* The parent thread is supposed to report events.  Check whether
64          the TD_CREATE event is needed, too.  */
65       const int _idx = __td_eventword (TD_CREATE);
66       const uint32_t _mask = __td_eventmask (TD_CREATE);
67
68       if ((_mask & (__nptl_threads_events.event_bits[_idx]
69                     | pd->eventbuf.eventmask.event_bits[_idx])) != 0)
70         {
71           /* We have to report the new thread.  Make sure the thread
72              does not run far by forcing it to get a lock.  We lock it
73              here too so that the new thread cannot continue until we
74              tell it to.  */
75           lll_lock (pd->lock);
76
77           /* Create the thread.  */
78           if (ARCH_CLONE (start_thread_debug, STACK_VARIABLES_ARGS,
79                           CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
80                           CLONE_SETTLS | CLONE_PARENT_SETTID |
81                           CLONE_CHILD_CLEARTID | CLONE_DETACHED | 0,
82                           pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
83             /* Failed.  */
84             return errno;
85
86 #ifdef TLS_MULTIPLE_THREADS_IN_TCB
87           /* We now have for sure more than one thread.  */
88           pd->header.multiple_threads = 1;
89 #else
90           __pthread_multiple_threads = *__libc_multiple_threads_ptr = 1;
91 #endif
92
93           /* Now fill in the information about the new thread in
94              the newly created thread's data structure.  We cannot let
95              the new thread do this since we don't know whether it was
96              already scheduled when we send the event.  */
97           pd->eventbuf.eventnum = TD_CREATE;
98           pd->eventbuf.eventdata = pd;
99
100           /* Enqueue the descriptor.  */
101           do
102             pd->nextevent = __nptl_last_event;
103           while (atomic_compare_and_exchange_bool_acq (&__nptl_last_event, pd,
104                                                        pd->nextevent) != 0);
105
106           /* Now call the function which signals the event.  */
107           __nptl_create_event ();
108
109           /* And finally restart the new thread.  */
110           lll_unlock (pd->lock);
111
112           return 0;
113         }
114     }
115
116 #ifdef NEED_DL_SYSINFO
117   assert (THREAD_GETMEM (THREAD_SELF, header.sysinfo) == pd->header.sysinfo);
118 #endif
119
120   /* We rely heavily on various flags the CLONE function understands:
121
122      CLONE_VM, CLONE_FS, CLONE_FILES
123         These flags select semantics with shared address space and
124         file descriptors according to what POSIX requires.
125
126      CLONE_SIGNAL
127         This flag selects the POSIX signal semantics.
128
129      CLONE_SETTLS
130         The sixth parameter to CLONE determines the TLS area for the
131         new thread.
132
133      CLONE_PARENT_SETTID
134         The kernels writes the thread ID of the newly created thread
135         into the location pointed to by the fifth parameters to CLONE.
136
137         Note that it would be semantically equivalent to use
138         CLONE_CHILD_SETTID but it is be more expensive in the kernel.
139
140      CLONE_CHILD_CLEARTID
141         The kernels clears the thread ID of a thread that has called
142         sys_exit() in the location pointed to by the seventh parameter
143         to CLONE.
144
145      CLONE_DETACHED
146         No signal is generated if the thread exists and it is
147         automatically reaped.
148
149      The termination signal is chosen to be zero which means no signal
150      is sent.  */
151   if (ARCH_CLONE (start_thread, STACK_VARIABLES_ARGS,
152                   CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGNAL |
153                   CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID |
154                   CLONE_DETACHED | 0, pd, &pd->tid, TLS_VALUE, &pd->tid) == -1)
155     /* Failed.  */
156     return errno;
157
158 #ifdef TLS_MULTIPLE_THREADS_IN_TCB
159   /* We now have for sure more than one thread.  */
160   THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
161 #endif
162
163   return 0;
164 }