libc: build tsd only when tls is enabled
[uclibc-ng.git] / libpthread / linuxthreads / attr.c
blob52e115c8eeb63904e2500f3395398edfaba49c91
1 /* Linuxthreads - a simple clone()-based implementation of Posix */
2 /* threads for Linux. */
3 /* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
4 /* */
5 /* This program is free software; you can redistribute it and/or */
6 /* modify it under the terms of the GNU Library General Public License */
7 /* as published by the Free Software Foundation; either version 2 */
8 /* of the License, or (at your option) any later version. */
9 /* */
10 /* This program 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 */
13 /* GNU Library General Public License for more details. */
15 /* Handling of thread attributes */
17 #include <errno.h>
18 #include <inttypes.h>
19 #include <stdio.h>
20 #include <stdio_ext.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/param.h>
25 #include <sys/resource.h>
26 #include "pthread.h"
27 #include "internals.h"
30 int __pthread_attr_init(pthread_attr_t *attr)
32 size_t ps = __getpagesize ();
34 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
35 attr->__schedpolicy = SCHED_OTHER;
36 attr->__schedparam.sched_priority = 0;
37 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
38 attr->__scope = PTHREAD_SCOPE_SYSTEM;
39 #ifdef NEED_SEPARATE_REGISTER_STACK
40 attr->__guardsize = ps + ps;
41 #else
42 attr->__guardsize = ps;
43 #endif
44 attr->__stackaddr = NULL;
45 attr->__stackaddr_set = 0;
46 attr->__stacksize = STACK_SIZE - ps;
47 return 0;
49 strong_alias (__pthread_attr_init, pthread_attr_init)
51 int __pthread_attr_destroy(pthread_attr_t *attr)
53 return 0;
55 strong_alias (__pthread_attr_destroy, pthread_attr_destroy)
57 int __pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
59 if (detachstate < PTHREAD_CREATE_JOINABLE ||
60 detachstate > PTHREAD_CREATE_DETACHED)
61 return EINVAL;
62 attr->__detachstate = detachstate;
63 return 0;
65 strong_alias (__pthread_attr_setdetachstate, pthread_attr_setdetachstate)
67 int __pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
69 *detachstate = attr->__detachstate;
70 return 0;
72 strong_alias (__pthread_attr_getdetachstate, pthread_attr_getdetachstate)
74 int __pthread_attr_setschedparam(pthread_attr_t *attr,
75 const struct sched_param *param)
77 int max_prio = __sched_get_priority_max(attr->__schedpolicy);
78 int min_prio = __sched_get_priority_min(attr->__schedpolicy);
80 if (param->sched_priority < min_prio || param->sched_priority > max_prio)
81 return EINVAL;
82 memcpy (&attr->__schedparam, param, sizeof (struct sched_param));
83 return 0;
85 strong_alias (__pthread_attr_setschedparam, pthread_attr_setschedparam)
87 int __pthread_attr_getschedparam(const pthread_attr_t *attr,
88 struct sched_param *param)
90 memcpy (param, &attr->__schedparam, sizeof (struct sched_param));
91 return 0;
93 strong_alias (__pthread_attr_getschedparam, pthread_attr_getschedparam)
95 int __pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
97 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
98 return EINVAL;
99 attr->__schedpolicy = policy;
100 return 0;
102 strong_alias (__pthread_attr_setschedpolicy, pthread_attr_setschedpolicy)
104 int __pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
106 *policy = attr->__schedpolicy;
107 return 0;
109 strong_alias (__pthread_attr_getschedpolicy, pthread_attr_getschedpolicy)
111 int __pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
113 if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED)
114 return EINVAL;
115 attr->__inheritsched = inherit;
116 return 0;
118 strong_alias (__pthread_attr_setinheritsched, pthread_attr_setinheritsched)
120 int __pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
122 *inherit = attr->__inheritsched;
123 return 0;
125 strong_alias (__pthread_attr_getinheritsched, pthread_attr_getinheritsched)
127 int __pthread_attr_setscope(pthread_attr_t *attr, int scope)
129 switch (scope) {
130 case PTHREAD_SCOPE_SYSTEM:
131 attr->__scope = scope;
132 return 0;
133 case PTHREAD_SCOPE_PROCESS:
134 return ENOTSUP;
135 default:
136 return EINVAL;
139 strong_alias (__pthread_attr_setscope, pthread_attr_setscope)
141 int __pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
143 *scope = attr->__scope;
144 return 0;
146 strong_alias (__pthread_attr_getscope, pthread_attr_getscope)
148 int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
150 /* The guard size must not be larger than the stack itself */
151 if (guardsize >= attr->__stacksize) return EINVAL;
153 attr->__guardsize = guardsize;
155 return 0;
157 weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize)
159 int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
161 *guardsize = attr->__guardsize;
162 return 0;
164 weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize)
166 #if 0 /* uClibc: deprecated stuff disabled */
167 int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
169 attr->__stackaddr = stackaddr;
170 attr->__stackaddr_set = 1;
171 return 0;
173 weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr)
175 link_warning (pthread_attr_setstackaddr,
176 "the use of `pthread_attr_setstackaddr' is deprecated, use `pthread_attr_setstack'")
178 int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
180 /* XXX This function has a stupid definition. The standard specifies
181 no error value but what is if no stack address was set? We simply
182 return the value we have in the member. */
183 *stackaddr = attr->__stackaddr;
184 return 0;
186 weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr)
188 link_warning (pthread_attr_getstackaddr,
189 "the use of `pthread_attr_getstackaddr' is deprecated, use `pthread_attr_getstack'")
190 #endif
193 int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
195 #ifdef FLOATING_STACKS
196 /* We have to check against the maximum allowed stack size. This is no
197 problem if the manager is already started and we determined it. If
198 this hasn't happened, we have to find the limit outself. */
199 if (__pthread_max_stacksize == 0)
200 __pthread_init_max_stacksize ();
202 if (stacksize > __pthread_max_stacksize)
203 return EINVAL;
204 #else
205 /* We have a fixed size limit. */
206 if (stacksize > STACK_SIZE)
207 return EINVAL;
208 #endif
210 /* We don't accept value smaller than PTHREAD_STACK_MIN. */
211 if (stacksize < PTHREAD_STACK_MIN)
212 return EINVAL;
214 attr->__stacksize = stacksize;
215 return 0;
218 #if PTHREAD_STACK_MIN == 16384 || defined __UCLIBC__
219 weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
220 #else
221 versioned_symbol (libpthread, __pthread_attr_setstacksize,
222 pthread_attr_setstacksize, GLIBC_2_3_3);
224 # if SHLIB_COMPAT(libpthread, GLIBC_2_1, GLIBC_2_3_3)
226 int __old_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
228 # ifdef FLOATING_STACKS
229 /* We have to check against the maximum allowed stack size. This is no
230 problem if the manager is already started and we determined it. If
231 this hasn't happened, we have to find the limit outself. */
232 if (__pthread_max_stacksize == 0)
233 __pthread_init_max_stacksize ();
235 if (stacksize > __pthread_max_stacksize)
236 return EINVAL;
237 # else
238 /* We have a fixed size limit. */
239 if (stacksize > STACK_SIZE)
240 return EINVAL;
241 # endif
243 /* We don't accept value smaller than old PTHREAD_STACK_MIN. */
244 if (stacksize < 16384)
245 return EINVAL;
247 attr->__stacksize = stacksize;
248 return 0;
250 compat_symbol (libpthread, __old_pthread_attr_setstacksize,
251 pthread_attr_setstacksize, GLIBC_2_1);
252 # endif
253 #endif
256 int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
258 *stacksize = attr->__stacksize;
259 return 0;
261 weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
263 int __pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
264 size_t stacksize)
266 int err;
268 if ((((uintptr_t) stackaddr)
269 & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0)
270 err = EINVAL;
271 else
272 err = __pthread_attr_setstacksize (attr, stacksize);
273 if (err == 0)
275 #ifndef _STACK_GROWS_UP
276 attr->__stackaddr = (char *) stackaddr + stacksize;
277 #else
278 attr->__stackaddr = stackaddr;
279 #endif
280 attr->__stackaddr_set = 1;
283 return err;
286 #if PTHREAD_STACK_MIN == 16384 || defined __UCLIBC__
287 weak_alias (__pthread_attr_setstack, pthread_attr_setstack)
288 #else
289 versioned_symbol (libpthread, __pthread_attr_setstack, pthread_attr_setstack,
290 GLIBC_2_3_3);
291 # if SHLIB_COMPAT(libpthread, GLIBC_2_2, GLIBC_2_3_3)
292 int __old_pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
293 size_t stacksize)
295 int err;
297 if ((((uintptr_t) stackaddr)
298 & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0)
299 err = EINVAL;
300 else
301 err = __old_pthread_attr_setstacksize (attr, stacksize);
302 if (err == 0)
304 # ifndef _STACK_GROWS_UP
305 attr->__stackaddr = (char *) stackaddr + stacksize;
306 # else
307 attr->__stackaddr = stackaddr;
308 # endif
309 attr->__stackaddr_set = 1;
312 return err;
315 compat_symbol (libpthread, __old_pthread_attr_setstack, pthread_attr_setstack,
316 GLIBC_2_2);
318 # endif
319 #endif
321 int __pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr,
322 size_t *stacksize)
324 /* XXX This function has a stupid definition. The standard specifies
325 no error value but what is if no stack address was set? We simply
326 return the value we have in the member. */
327 #ifndef _STACK_GROWS_UP
328 *stackaddr = (char *) attr->__stackaddr - attr->__stacksize;
329 #else
330 *stackaddr = attr->__stackaddr;
331 #endif
332 *stacksize = attr->__stacksize;
333 return 0;
335 weak_alias (__pthread_attr_getstack, pthread_attr_getstack)
337 int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
339 pthread_handle handle = thread_handle (thread);
340 pthread_descr descr;
341 int ret = 0;
343 if (handle == NULL)
344 return ENOENT;
346 descr = handle->h_descr;
348 attr->__detachstate = (descr->p_detached
349 ? PTHREAD_CREATE_DETACHED
350 : PTHREAD_CREATE_JOINABLE);
352 attr->__schedpolicy = __sched_getscheduler (descr->p_pid);
353 if (attr->__schedpolicy == -1)
354 return errno;
356 if (__sched_getparam (descr->p_pid,
357 (struct sched_param *) &attr->__schedparam) != 0)
358 return errno;
360 attr->__inheritsched = descr->p_inheritsched;
361 attr->__scope = PTHREAD_SCOPE_SYSTEM;
363 #ifdef _STACK_GROWS_DOWN
364 # ifdef USE_TLS
365 attr->__stacksize = descr->p_stackaddr - (char *)descr->p_guardaddr
366 - descr->p_guardsize;
367 # else
368 attr->__stacksize = (char *)(descr + 1) - (char *)descr->p_guardaddr
369 - descr->p_guardsize;
370 # endif
371 #else
372 # ifdef USE_TLS
373 attr->__stacksize = (char *)descr->p_guardaddr - descr->p_stackaddr;
374 # else
375 attr->__stacksize = (char *)descr->p_guardaddr - (char *)descr;
376 # endif
377 #endif
378 attr->__guardsize = descr->p_guardsize;
379 attr->__stackaddr_set = descr->p_userstack;
380 #ifdef NEED_SEPARATE_REGISTER_STACK
381 if (descr->p_userstack == 0)
382 attr->__stacksize *= 2;
383 /* XXX This is awkward. The guard pages are in the middle of the
384 two stacks. We must count the guard size in the stack size since
385 otherwise the range of the stack area cannot be computed. */
386 attr->__stacksize += attr->__guardsize;
387 #endif
388 #ifdef USE_TLS
389 attr->__stackaddr = descr->p_stackaddr;
390 #else
391 # ifndef _STACK_GROWS_UP
392 attr->__stackaddr = (char *)(descr + 1);
393 # else
394 attr->__stackaddr = (char *)descr;
395 # endif
396 #endif
398 #ifdef USE_TLS
399 if (attr->__stackaddr == NULL)
400 #else
401 if (descr == &__pthread_initial_thread)
402 #endif
404 /* Stack size limit. */
405 struct rlimit rl;
407 /* The safest way to get the top of the stack is to read
408 /proc/self/maps and locate the line into which
409 __libc_stack_end falls. */
410 FILE *fp = fopen ("/proc/self/maps", "rc");
411 if (fp == NULL)
412 ret = errno;
413 /* We need the limit of the stack in any case. */
414 else if (getrlimit (RLIMIT_STACK, &rl) != 0)
415 ret = errno;
416 else
418 /* We need no locking. */
419 __fsetlocking (fp, FSETLOCKING_BYCALLER);
421 /* Until we found an entry (which should always be the case)
422 mark the result as a failure. */
423 ret = ENOENT;
425 char *line = NULL;
426 size_t linelen = 0;
427 uintptr_t last_to = 0;
429 while (! feof_unlocked (fp))
431 if (getdelim (&line, &linelen, '\n', fp) <= 0)
432 break;
434 uintptr_t from;
435 uintptr_t to;
436 if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2)
437 continue;
438 if (from <= (uintptr_t) __libc_stack_end
439 && (uintptr_t) __libc_stack_end < to)
441 /* Found the entry. Now we have the info we need. */
442 attr->__stacksize = rl.rlim_cur;
443 #ifdef _STACK_GROWS_UP
444 /* Don't check to enforce a limit on the __stacksize */
445 attr->__stackaddr = (void *) from;
446 #else
447 attr->__stackaddr = (void *) to;
449 /* The limit might be too high. */
450 if ((size_t) attr->__stacksize
451 > (size_t) attr->__stackaddr - last_to)
452 attr->__stacksize = (size_t) attr->__stackaddr - last_to;
453 #endif
455 /* We succeed and no need to look further. */
456 ret = 0;
457 break;
459 last_to = to;
462 fclose (fp);
463 free (line);
467 return 0;