1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
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: #include <smp.h>
35: #include <lowlevellock.h>
36: #include <kernel-features.h>
37:
38:
39:
40: size_t __static_tls_size;
41: size_t __static_tls_align_m1;
42:
43: #ifndef __ASSUME_SET_ROBUST_LIST
44:
45: int __set_robust_list_avail;
46: # define set_robust_list_not_avail() \
47: __set_robust_list_avail = -1
48: #else
49: # define set_robust_list_not_avail() do { } while (0)
50: #endif
51:
52:
53: static const char nptl_version[] __attribute_used__ = VERSION;
54:
55:
56: #ifndef SHARED
57: extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign);
58: #endif
59:
60:
61: #ifdef SHARED
62: static const struct pthread_functions pthread_functions =
63: {
64: .ptr_pthread_attr_destroy = __pthread_attr_destroy,
65: # if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
66: .ptr___pthread_attr_init_2_0 = __pthread_attr_init_2_0,
67: # endif
68: .ptr___pthread_attr_init_2_1 = __pthread_attr_init_2_1,
69: .ptr_pthread_attr_getdetachstate = __pthread_attr_getdetachstate,
70: .ptr_pthread_attr_setdetachstate = __pthread_attr_setdetachstate,
71: .ptr_pthread_attr_getinheritsched = __pthread_attr_getinheritsched,
72: .ptr_pthread_attr_setinheritsched = __pthread_attr_setinheritsched,
73: .ptr_pthread_attr_getschedparam = __pthread_attr_getschedparam,
74: .ptr_pthread_attr_setschedparam = __pthread_attr_setschedparam,
75: .ptr_pthread_attr_getschedpolicy = __pthread_attr_getschedpolicy,
76: .ptr_pthread_attr_setschedpolicy = __pthread_attr_setschedpolicy,
77: .ptr_pthread_attr_getscope = __pthread_attr_getscope,
78: .ptr_pthread_attr_setscope = __pthread_attr_setscope,
79: .ptr_pthread_condattr_destroy = __pthread_condattr_destroy,
80: .ptr_pthread_condattr_init = __pthread_condattr_init,
81: .ptr___pthread_cond_broadcast = __pthread_cond_broadcast,
82: .ptr___pthread_cond_destroy = __pthread_cond_destroy,
83: .ptr___pthread_cond_init = __pthread_cond_init,
84: .ptr___pthread_cond_signal = __pthread_cond_signal,
85: .ptr___pthread_cond_wait = __pthread_cond_wait,
86: .ptr___pthread_cond_timedwait = __pthread_cond_timedwait,
87: # if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_3_2)
88: .ptr___pthread_cond_broadcast_2_0 = __pthread_cond_broadcast_2_0,
89: .ptr___pthread_cond_destroy_2_0 = __pthread_cond_destroy_2_0,
90: .ptr___pthread_cond_init_2_0 = __pthread_cond_init_2_0,
91: .ptr___pthread_cond_signal_2_0 = __pthread_cond_signal_2_0,
92: .ptr___pthread_cond_wait_2_0 = __pthread_cond_wait_2_0,
93: .ptr___pthread_cond_timedwait_2_0 = __pthread_cond_timedwait_2_0,
94: # endif
95: .ptr_pthread_equal = __pthread_equal,
96: .ptr___pthread_exit = __pthread_exit,
97: .ptr_pthread_getschedparam = __pthread_getschedparam,
98: .ptr_pthread_setschedparam = __pthread_setschedparam,
99: .ptr_pthread_mutex_destroy = INTUSE(__pthread_mutex_destroy),
100: .ptr_pthread_mutex_init = INTUSE(__pthread_mutex_init),
101: .ptr_pthread_mutex_lock = INTUSE(__pthread_mutex_lock),
102: .ptr_pthread_mutex_unlock = INTUSE(__pthread_mutex_unlock),
103: .ptr_pthread_self = __pthread_self,
104: .ptr_pthread_setcancelstate = __pthread_setcancelstate,
105: .ptr_pthread_setcanceltype = __pthread_setcanceltype,
106: .ptr___pthread_cleanup_upto = __pthread_cleanup_upto,
107: .ptr___pthread_once = __pthread_once_internal,
108: .ptr___pthread_rwlock_rdlock = __pthread_rwlock_rdlock_internal,
109: .ptr___pthread_rwlock_wrlock = __pthread_rwlock_wrlock_internal,
110: .ptr___pthread_rwlock_unlock = __pthread_rwlock_unlock_internal,
111: .ptr___pthread_key_create = __pthread_key_create_internal,
112: .ptr___pthread_getspecific = __pthread_getspecific_internal,
113: .ptr___pthread_setspecific = __pthread_setspecific_internal,
114: .ptr__pthread_cleanup_push_defer = __pthread_cleanup_push_defer,
115: .ptr__pthread_cleanup_pop_restore = __pthread_cleanup_pop_restore,
116: .ptr_nthreads = &__nptl_nthreads,
117: .ptr___pthread_unwind = &__pthread_unwind,
118: .ptr__nptl_deallocate_tsd = __nptl_deallocate_tsd,
119: .ptr__nptl_setxid = __nptl_setxid,
120:
121: .ptr_freeres = __free_stack_cache
122: };
123: # define ptr_pthread_functions &pthread_functions
124: #else
125: # define ptr_pthread_functions NULL
126: #endif
127:
128:
129:
130: static void
131: sigcancel_handler (int sig, siginfo_t *si, void *ctx)
132: {
133: #ifdef __ASSUME_CORRECT_SI_PID
134:
135:
136: pid_t pid = THREAD_GETMEM (THREAD_SELF, pid);
137: if (__builtin_expect (pid < 0, 0))
138: pid = -pid;
139: #endif
140:
141:
142:
143:
144:
145: if (sig != SIGCANCEL
146: #ifdef __ASSUME_CORRECT_SI_PID
147:
148:
149: || si->si_pid != pid
150: #endif
151: || si->si_code != SI_TKILL)
152: return;
153:
154: struct pthread *self = THREAD_SELF;
155:
156: int oldval = THREAD_GETMEM (self, cancelhandling);
157: while (1)
158: {
159:
160:
161:
162: int newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK;
163:
164: if (oldval == newval || (oldval & EXITING_BITMASK) != 0)
165:
166: break;
167:
168: int curval = THREAD_ATOMIC_CMPXCHG_VAL (self, cancelhandling, newval,
169: oldval);
170: if (curval == oldval)
171: {
172:
173: THREAD_SETMEM (self, result, PTHREAD_CANCELED);
174:
175:
176: if ((newval & CANCELTYPE_BITMASK) != 0)
177:
178: __do_cancel ();
179:
180: break;
181: }
182:
183: oldval = curval;
184: }
185: }
186:
187:
188: struct xid_command *__xidcmd attribute_hidden;
189:
190:
191: static void
192: sighandler_setxid (int sig, siginfo_t *si, void *ctx)
193: {
194: #ifdef __ASSUME_CORRECT_SI_PID
195:
196:
197: pid_t pid = THREAD_GETMEM (THREAD_SELF, pid);
198: if (__builtin_expect (pid < 0, 0))
199: pid = -pid;
200: #endif
201:
202:
203:
204:
205:
206: if (sig != SIGSETXID
207: #ifdef __ASSUME_CORRECT_SI_PID
208:
209:
210: || si->si_pid != pid
211: #endif
212: || si->si_code != SI_TKILL)
213: return;
214:
215: INTERNAL_SYSCALL_DECL (err);
216: INTERNAL_SYSCALL_NCS (__xidcmd->syscall_no, err, 3, __xidcmd->id[0],
217: __xidcmd->id[1], __xidcmd->id[2]);
218:
219: if (atomic_decrement_val (&__xidcmd->cntr) == 0)
220: lll_futex_wake (&__xidcmd->cntr, 1, LLL_PRIVATE);
221:
222:
223: struct pthread *self = THREAD_SELF;
224: int flags = THREAD_GETMEM (self, cancelhandling);
225: THREAD_SETMEM (self, cancelhandling, flags & ~SETXID_BITMASK);
226:
227:
228: self->setxid_futex = 1;
229: lll_futex_wake (&self->setxid_futex, 1, LLL_PRIVATE);
230: }
231:
232:
233:
234:
235: extern void **__libc_dl_error_tsd (void) __attribute__ ((const));
236:
237:
238:
239: static bool __nptl_initial_report_events;
240:
241: void
242: __pthread_initialize_minimal_internal (void)
243: {
244: #ifndef SHARED
245:
246:
247: __libc_setup_tls (TLS_TCB_SIZE, TLS_TCB_ALIGN);
248:
249:
250:
251:
252:
253: __asm __volatile ("");
254: #endif
255:
256:
257: struct pthread *pd = THREAD_SELF;
258: INTERNAL_SYSCALL_DECL (err);
259: pd->pid = pd->tid = INTERNAL_SYSCALL (set_tid_address, err, 1, &pd->tid);
260: THREAD_SETMEM (pd, specific[0], &pd->specific_1stblock[0]);
261: THREAD_SETMEM (pd, user_stack, true);
262: if (LLL_LOCK_INITIALIZER != 0)
263: THREAD_SETMEM (pd, lock, LLL_LOCK_INITIALIZER);
264: #if HP_TIMING_AVAIL
265: THREAD_SETMEM (pd, cpuclock_offset, GL(dl_cpuclock_offset));
266: #endif
267:
268:
269: #ifdef __PTHREAD_MUTEX_HAVE_PREV
270: pd->robust_prev = &pd->robust_head;
271: #endif
272: pd->robust_head.list = &pd->robust_head;
273: #ifdef __NR_set_robust_list
274: pd->robust_head.futex_offset = (offsetof (pthread_mutex_t, __data.__lock)
275: - offsetof (pthread_mutex_t,
276: __data.__list.__next));
277: int res = INTERNAL_SYSCALL (set_robust_list, err, 2, &pd->robust_head,
278: sizeof (struct robust_list_head));
279: if (INTERNAL_SYSCALL_ERROR_P (res, err))
280: #endif
281: set_robust_list_not_avail ();
282:
283: #ifndef __ASSUME_PRIVATE_FUTEX
284:
285:
286: {
287: int word = 0;
288: word = INTERNAL_SYSCALL (futex, err, 3, &word,
289: FUTEX_WAKE | FUTEX_PRIVATE_FLAG, 1);
290: if (!INTERNAL_SYSCALL_ERROR_P (word, err))
291: THREAD_SETMEM (pd, header.private_futex, FUTEX_PRIVATE_FLAG);
292: }
293: #endif
294:
295:
296:
297:
298: THREAD_SETMEM (pd, stackblock_size, (size_t) __libc_stack_end);
299:
300:
301: INIT_LIST_HEAD (&__stack_user);
302: list_add (&pd->list, &__stack_user);
303:
304:
305:
306: THREAD_SETMEM (pd, report_events, __nptl_initial_report_events);
307:
308:
309:
310:
311: struct sigaction sa;
312: sa.sa_sigaction = sigcancel_handler;
313: sa.sa_flags = SA_SIGINFO;
314: __sigemptyset (&sa.sa_mask);
315:
316: (void) __libc_sigaction (SIGCANCEL, &sa, NULL);
317:
318:
319: sa.sa_sigaction = sighandler_setxid;
320: sa.sa_flags = SA_SIGINFO | SA_RESTART;
321:
322: (void) __libc_sigaction (SIGSETXID, &sa, NULL);
323:
324:
325:
326:
327: __sigaddset (&sa.sa_mask, SIGCANCEL);
328: __sigaddset (&sa.sa_mask, SIGSETXID);
329: (void) INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_UNBLOCK, &sa.sa_mask,
330: NULL, _NSIG / 8);
331:
332:
333:
334: size_t static_tls_align;
335: _dl_get_tls_static_info (&__static_tls_size, &static_tls_align);
336:
337:
338: if (STACK_ALIGN > static_tls_align)
339: static_tls_align = STACK_ALIGN;
340: __static_tls_align_m1 = static_tls_align - 1;
341:
342: __static_tls_size = roundup (__static_tls_size, static_tls_align);
343:
344:
345:
346: struct rlimit limit;
347: if (getrlimit (RLIMIT_STACK, &limit) != 0
348: || limit.rlim_cur == RLIM_INFINITY)
349:
350:
351: limit.rlim_cur = ARCH_STACK_DEFAULT_SIZE;
352: else if (limit.rlim_cur < PTHREAD_STACK_MIN)
353:
354:
355: limit.rlim_cur = PTHREAD_STACK_MIN;
356:
357:
358:
359: const uintptr_t pagesz = __sysconf (_SC_PAGESIZE);
360: const size_t minstack = pagesz + __static_tls_size + MINIMAL_REST_STACK;
361: if (limit.rlim_cur < minstack)
362: limit.rlim_cur = minstack;
363:
364:
365: limit.rlim_cur = (limit.rlim_cur + pagesz - 1) & -pagesz;
366: __default_stacksize = limit.rlim_cur;
367:
368: #ifdef SHARED
369:
370: *__libc_dl_error_tsd () = *(*GL(dl_error_catch_tsd)) ();
371: GL(dl_error_catch_tsd) = &__libc_dl_error_tsd;
372:
373:
374:
375: GL(dl_rtld_lock_recursive) = (void *) INTUSE (__pthread_mutex_lock);
376: GL(dl_rtld_unlock_recursive) = (void *) INTUSE (__pthread_mutex_unlock);
377: unsigned int rtld_lock_count = GL(dl_load_lock).mutex.__data.__count;
378: GL(dl_load_lock).mutex.__data.__count = 0;
379: while (rtld_lock_count-- > 0)
380: INTUSE (__pthread_mutex_lock) (&GL(dl_load_lock).mutex);
381:
382: GL(dl_make_stack_executable_hook) = &__make_stacks_executable;
383: #endif
384:
385: GL(dl_init_static_tls) = &__pthread_init_static_tls;
386:
387: GL(dl_wait_lookup_done) = &__wait_lookup_done;
388:
389:
390: #ifndef TLS_MULTIPLE_THREADS_IN_TCB
391: __libc_multiple_threads_ptr =
392: #endif
393: __libc_pthread_init (&__fork_generation, __reclaim_stacks,
394: ptr_pthread_functions);
395:
396:
397: __is_smp = is_smp_system ();
398: }
399: strong_alias (__pthread_initialize_minimal_internal,
400: __pthread_initialize_minimal)