Adjust for new form of compare&exchange macros.
[kopensolaris-gnu/glibc.git] / nptl / init.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 <assert.h>
21 #include <limits.h>
22 #include <signal.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/param.h>
26 #include <sys/resource.h>
27 #include <pthreadP.h>
28 #include <atomic.h>
29 #include <ldsodefs.h>
30 #include <tls.h>
31 #include <fork.h>
32 #include <version.h>
33 #include <shlib-compat.h>
34
35
36 #ifndef __NR_set_tid_address
37 /* XXX For the time being...  Once we can rely on the kernel headers
38    having the definition remove these lines.  */
39 #if defined __s390__
40 # define __NR_set_tid_address   252
41 #elif defined __ia64__
42 # define __NR_set_tid_address   1233
43 #elif defined __i386__
44 # define __NR_set_tid_address   258
45 #elif defined __x86_64__
46 # define __NR_set_tid_address   218
47 #elif defined __powerpc__
48 # define __NR_set_tid_address   232
49 #else
50 # error "define __NR_set_tid_address"
51 #endif
52 #endif
53
54
55 /* Default stack size.  */
56 size_t __default_stacksize attribute_hidden;
57
58 /* Size and alignment of static TLS block.  */
59 size_t __static_tls_size;
60 size_t __static_tls_align_m1;
61
62 /* Version of the library, used in libthread_db to detect mismatches.  */
63 static const char nptl_version[] = VERSION;
64
65
66 #if defined USE_TLS && !defined SHARED
67 extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign);
68 #endif
69
70
71 #ifdef SHARED
72 static struct pthread_functions pthread_functions =
73   {
74     .ptr_pthread_attr_destroy = __pthread_attr_destroy,
75 # if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
76     .ptr___pthread_attr_init_2_0 = __pthread_attr_init_2_0,
77 # endif
78     .ptr___pthread_attr_init_2_1 = __pthread_attr_init_2_1,
79     .ptr_pthread_attr_getdetachstate = __pthread_attr_getdetachstate,
80     .ptr_pthread_attr_setdetachstate = __pthread_attr_setdetachstate,
81     .ptr_pthread_attr_getinheritsched = __pthread_attr_getinheritsched,
82     .ptr_pthread_attr_setinheritsched = __pthread_attr_setinheritsched,
83     .ptr_pthread_attr_getschedparam = __pthread_attr_getschedparam,
84     .ptr_pthread_attr_setschedparam = __pthread_attr_setschedparam,
85     .ptr_pthread_attr_getschedpolicy = __pthread_attr_getschedpolicy,
86     .ptr_pthread_attr_setschedpolicy = __pthread_attr_setschedpolicy,
87     .ptr_pthread_attr_getscope = __pthread_attr_getscope,
88     .ptr_pthread_attr_setscope = __pthread_attr_setscope,
89     .ptr_pthread_condattr_destroy = __pthread_condattr_destroy,
90     .ptr_pthread_condattr_init = __pthread_condattr_init,
91     .ptr___pthread_cond_broadcast = __pthread_cond_broadcast,
92     .ptr___pthread_cond_destroy = __pthread_cond_destroy,
93     .ptr___pthread_cond_init = __pthread_cond_init,
94     .ptr___pthread_cond_signal = __pthread_cond_signal,
95     .ptr___pthread_cond_wait = __pthread_cond_wait,
96 # if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
97     .ptr___pthread_cond_broadcast_2_0 = __pthread_cond_broadcast_2_0,
98     .ptr___pthread_cond_destroy_2_0 = __pthread_cond_destroy_2_0,
99     .ptr___pthread_cond_init_2_0 = __pthread_cond_init_2_0,
100     .ptr___pthread_cond_signal_2_0 = __pthread_cond_signal_2_0,
101     .ptr___pthread_cond_wait_2_0 = __pthread_cond_wait_2_0,
102 # endif
103     .ptr_pthread_equal = __pthread_equal,
104     .ptr___pthread_exit = __pthread_exit,
105     .ptr_pthread_getschedparam = __pthread_getschedparam,
106     .ptr_pthread_setschedparam = __pthread_setschedparam,
107     .ptr_pthread_mutex_destroy = INTUSE(__pthread_mutex_destroy),
108     .ptr_pthread_mutex_init = INTUSE(__pthread_mutex_init),
109     .ptr_pthread_mutex_lock = INTUSE(__pthread_mutex_lock),
110     .ptr_pthread_mutex_unlock = INTUSE(__pthread_mutex_unlock),
111     .ptr_pthread_self = __pthread_self,
112     .ptr_pthread_setcancelstate = __pthread_setcancelstate,
113     .ptr_pthread_setcanceltype = __pthread_setcanceltype,
114     .ptr___pthread_cleanup_upto = __pthread_cleanup_upto,
115     .ptr___pthread_once = __pthread_once_internal,
116     .ptr___pthread_rwlock_rdlock = __pthread_rwlock_rdlock_internal,
117     .ptr___pthread_rwlock_wrlock = __pthread_rwlock_wrlock_internal,
118     .ptr___pthread_rwlock_unlock = __pthread_rwlock_unlock_internal,
119     .ptr___pthread_key_create = __pthread_key_create_internal,
120     .ptr___pthread_getspecific = __pthread_getspecific_internal,
121     .ptr___pthread_setspecific = __pthread_setspecific_internal,
122     .ptr__pthread_cleanup_push_defer = __pthread_cleanup_push_defer,
123     .ptr__pthread_cleanup_pop_restore = __pthread_cleanup_pop_restore,
124     .ptr_nthreads = &__nptl_nthreads
125   };
126 # define ptr_pthread_functions &pthread_functions
127 #else
128 # define ptr_pthread_functions NULL
129 #endif
130
131
132 /* For asynchronous cancellation we use a signal.  This is the handler.  */
133 static void
134 sigcancel_handler (int sig __attribute ((unused)))
135 {
136   struct pthread *self = THREAD_SELF;
137
138   while (1)
139     {
140       /* We are canceled now.  When canceled by another thread this flag
141          is already set but if the signal is directly send (internally or
142          from another process) is has to be done here.  */
143       int oldval = THREAD_GETMEM (self, cancelhandling);
144       int newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK;
145
146       if (oldval == newval || (oldval & EXITING_BITMASK) != 0)
147         /* Already canceled or exiting.  */
148         break;
149
150       if (! atomic_compare_and_exchange_bool_acq (&self->cancelhandling,
151                                                   newval, oldval))
152         {
153           /* Set the return value.  */
154           THREAD_SETMEM (self, result, PTHREAD_CANCELED);
155
156           /* Make sure asynchronous cancellation is still enabled.  */
157           if ((newval & CANCELTYPE_BITMASK) != 0)
158             {
159               /* The thread is exiting now.  */
160               atomic_bit_set (&self->cancelhandling, EXITING_BIT);
161
162               /* Run the registered destructors and terminate the
163                  thread.  */
164               __do_cancel ();
165             }
166
167           break;
168         }
169     }
170 }
171
172
173 /* When using __thread for this, we do it in libc so as not
174    to give libpthread its own TLS segment just for this.  */
175 extern void **__libc_dl_error_tsd (void) __attribute__ ((const));
176
177
178 void
179 __pthread_initialize_minimal_internal (void)
180 {
181 #ifndef SHARED
182   /* Unlike in the dynamically linked case the dynamic linker has not
183      taken care of initializing the TLS data structures.  */
184   __libc_setup_tls (TLS_TCB_SIZE, TLS_TCB_ALIGN);
185
186   /* We must prevent gcc from being clever and move any of the
187      following code ahead of the __libc_setup_tls call.  This function
188      will initialize the thread register which is subsequently
189      used.  */
190   __asm __volatile ("");
191 #endif
192
193   /* Minimal initialization of the thread descriptor.  */
194   struct pthread *pd = THREAD_SELF;
195   INTERNAL_SYSCALL_DECL (err);
196   pd->tid = INTERNAL_SYSCALL (set_tid_address, err, 1, &pd->tid);
197   THREAD_SETMEM (pd, specific[0], &pd->specific_1stblock[0]);
198   THREAD_SETMEM (pd, user_stack, true);
199   if (LLL_LOCK_INITIALIZER != 0)
200     THREAD_SETMEM (pd, lock, LLL_LOCK_INITIALIZER);
201 #if HP_TIMING_AVAIL
202   THREAD_SETMEM (pd, cpuclock_offset, GL(dl_cpuclock_offset));
203 #endif
204
205   /* Initialize the list of all running threads with the main thread.  */
206   INIT_LIST_HEAD (&__stack_user);
207   list_add (&pd->list, &__stack_user);
208
209
210   /* Install the cancellation signal handler.  If for some reason we
211      cannot install the handler we do not abort.  Maybe we should, but
212      it is only asynchronous cancellation which is affected.  */
213   struct sigaction sa;
214   sa.sa_handler = sigcancel_handler;
215   sa.sa_flags = 0;
216   sigemptyset (&sa.sa_mask);
217
218   (void) __libc_sigaction (SIGCANCEL, &sa, NULL);
219
220   /* The parent process might have left the signal blocked.  Just in
221      case, unblock it.  We reuse the signal mask in the sigaction
222      structure.  It is already cleared.  */
223   __sigaddset (&sa.sa_mask, SIGCANCEL);
224   (void) INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_UNBLOCK, &sa.sa_mask,
225                            NULL, _NSIG / 8);
226
227
228   /* Determine the default allowed stack size.  This is the size used
229      in case the user does not specify one.  */
230   struct rlimit limit;
231   if (getrlimit (RLIMIT_STACK, &limit) != 0
232       || limit.rlim_cur == RLIM_INFINITY)
233     /* The system limit is not usable.  Use an architecture-specific
234        default.  */
235     limit.rlim_cur = ARCH_STACK_DEFAULT_SIZE;
236
237 #ifdef NEED_SEPARATE_REGISTER_STACK
238   __default_stacksize = MAX (limit.rlim_cur / 2, PTHREAD_STACK_MIN);
239 #else
240   __default_stacksize = MAX (limit.rlim_cur, PTHREAD_STACK_MIN);
241 #endif
242   /* The maximum page size better should be a multiple of the page
243      size.  */
244   assert (__default_stacksize % __sysconf (_SC_PAGESIZE) == 0);
245
246   /* Get the size of the static and alignment requirements for the TLS
247      block.  */
248   size_t static_tls_align;
249   _dl_get_tls_static_info (&__static_tls_size, &static_tls_align);
250
251   /* Make sure the size takes all the alignments into account.  */
252   if (STACK_ALIGN > static_tls_align)
253     static_tls_align = STACK_ALIGN;
254   __static_tls_align_m1 = static_tls_align - 1;
255
256   __static_tls_size = roundup (__static_tls_size, static_tls_align);
257
258 #ifdef SHARED
259   /* Transfer the old value from the dynamic linker's internal location.  */
260   *__libc_dl_error_tsd () = *(*GL(dl_error_catch_tsd)) ();
261   GL(dl_error_catch_tsd) = &__libc_dl_error_tsd;
262 #endif
263
264   /* Register the fork generation counter with the libc.  */
265 #ifndef TLS_MULTIPLE_THREADS_IN_TCB
266   __libc_multiple_threads_ptr =
267 #endif
268     __libc_pthread_init (&__fork_generation, __reclaim_stacks,
269                          ptr_pthread_functions);
270 }
271 strong_alias (__pthread_initialize_minimal_internal,
272               __pthread_initialize_minimal)