1 /* Linuxthreads - a simple clone()-based implementation of Posix */
2 /* threads for Linux. */
3 /* Copyright (C) 1996 Xavier Leroy (Xavier.Leroy@inria.fr) */
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. */
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 */
20 #include <stdio_ext.h>
24 #include <sys/param.h>
25 #include <sys/resource.h>
27 #include "internals.h"
28 #include <shlib-compat.h>
32 int __pthread_attr_init_2_1(pthread_attr_t
*attr
)
34 size_t ps
= __getpagesize ();
36 attr
->__detachstate
= PTHREAD_CREATE_JOINABLE
;
37 attr
->__schedpolicy
= SCHED_OTHER
;
38 attr
->__schedparam
.sched_priority
= 0;
39 attr
->__inheritsched
= PTHREAD_EXPLICIT_SCHED
;
40 attr
->__scope
= PTHREAD_SCOPE_SYSTEM
;
41 #ifdef NEED_SEPARATE_REGISTER_STACK
42 attr
->__guardsize
= ps
+ ps
;
44 attr
->__guardsize
= ps
;
46 attr
->__stackaddr
= NULL
;
47 attr
->__stackaddr_set
= 0;
48 attr
->__stacksize
= STACK_SIZE
- ps
;
52 versioned_symbol (libpthread
, __pthread_attr_init_2_1
, pthread_attr_init
,
55 #if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
56 int __pthread_attr_init_2_0(pthread_attr_t
*attr
)
58 attr
->__detachstate
= PTHREAD_CREATE_JOINABLE
;
59 attr
->__schedpolicy
= SCHED_OTHER
;
60 attr
->__schedparam
.sched_priority
= 0;
61 attr
->__inheritsched
= PTHREAD_EXPLICIT_SCHED
;
62 attr
->__scope
= PTHREAD_SCOPE_SYSTEM
;
65 compat_symbol (libpthread
, __pthread_attr_init_2_0
, pthread_attr_init
,
69 int __pthread_attr_destroy(pthread_attr_t
*attr
)
73 strong_alias (__pthread_attr_destroy
, pthread_attr_destroy
);
75 int __pthread_attr_setdetachstate(pthread_attr_t
*attr
, int detachstate
)
77 if (detachstate
< PTHREAD_CREATE_JOINABLE
||
78 detachstate
> PTHREAD_CREATE_DETACHED
)
80 attr
->__detachstate
= detachstate
;
83 strong_alias (__pthread_attr_setdetachstate
, pthread_attr_setdetachstate
);
85 int __pthread_attr_getdetachstate(const pthread_attr_t
*attr
, int *detachstate
)
87 *detachstate
= attr
->__detachstate
;
90 strong_alias (__pthread_attr_getdetachstate
, pthread_attr_getdetachstate
);
92 int __pthread_attr_setschedparam(pthread_attr_t
*attr
,
93 const struct sched_param
*param
)
95 int max_prio
= __sched_get_priority_max(attr
->__schedpolicy
);
96 int min_prio
= __sched_get_priority_min(attr
->__schedpolicy
);
98 if (param
->sched_priority
< min_prio
|| param
->sched_priority
> max_prio
)
100 memcpy (&attr
->__schedparam
, param
, sizeof (struct sched_param
));
103 strong_alias (__pthread_attr_setschedparam
, pthread_attr_setschedparam
);
105 int __pthread_attr_getschedparam(const pthread_attr_t
*attr
,
106 struct sched_param
*param
)
108 memcpy (param
, &attr
->__schedparam
, sizeof (struct sched_param
));
111 strong_alias (__pthread_attr_getschedparam
, pthread_attr_getschedparam
);
113 int __pthread_attr_setschedpolicy(pthread_attr_t
*attr
, int policy
)
115 if (policy
!= SCHED_OTHER
&& policy
!= SCHED_FIFO
&& policy
!= SCHED_RR
)
117 attr
->__schedpolicy
= policy
;
120 strong_alias (__pthread_attr_setschedpolicy
, pthread_attr_setschedpolicy
);
122 int __pthread_attr_getschedpolicy(const pthread_attr_t
*attr
, int *policy
)
124 *policy
= attr
->__schedpolicy
;
127 strong_alias (__pthread_attr_getschedpolicy
, pthread_attr_getschedpolicy
);
129 int __pthread_attr_setinheritsched(pthread_attr_t
*attr
, int inherit
)
131 if (inherit
!= PTHREAD_INHERIT_SCHED
&& inherit
!= PTHREAD_EXPLICIT_SCHED
)
133 attr
->__inheritsched
= inherit
;
136 strong_alias (__pthread_attr_setinheritsched
, pthread_attr_setinheritsched
);
138 int __pthread_attr_getinheritsched(const pthread_attr_t
*attr
, int *inherit
)
140 *inherit
= attr
->__inheritsched
;
143 strong_alias (__pthread_attr_getinheritsched
, pthread_attr_getinheritsched
);
145 int __pthread_attr_setscope(pthread_attr_t
*attr
, int scope
)
148 case PTHREAD_SCOPE_SYSTEM
:
149 attr
->__scope
= scope
;
151 case PTHREAD_SCOPE_PROCESS
:
157 strong_alias (__pthread_attr_setscope
, pthread_attr_setscope
);
159 int __pthread_attr_getscope(const pthread_attr_t
*attr
, int *scope
)
161 *scope
= attr
->__scope
;
164 strong_alias (__pthread_attr_getscope
, pthread_attr_getscope
);
166 int __pthread_attr_setguardsize(pthread_attr_t
*attr
, size_t guardsize
)
168 /* The guard size must not be larger than the stack itself */
169 if (guardsize
>= attr
->__stacksize
) return EINVAL
;
171 attr
->__guardsize
= guardsize
;
175 weak_alias (__pthread_attr_setguardsize
, pthread_attr_setguardsize
)
177 int __pthread_attr_getguardsize(const pthread_attr_t
*attr
, size_t *guardsize
)
179 *guardsize
= attr
->__guardsize
;
182 weak_alias (__pthread_attr_getguardsize
, pthread_attr_getguardsize
)
184 int __pthread_attr_setstackaddr(pthread_attr_t
*attr
, void *stackaddr
)
186 attr
->__stackaddr
= stackaddr
;
187 attr
->__stackaddr_set
= 1;
190 weak_alias (__pthread_attr_setstackaddr
, pthread_attr_setstackaddr
)
192 link_warning (pthread_attr_setstackaddr
,
193 "the use of `pthread_attr_setstackaddr' is deprecated, use `pthread_attr_setstack'")
195 int __pthread_attr_getstackaddr(const pthread_attr_t
*attr
, void **stackaddr
)
197 /* XXX This function has a stupid definition. The standard specifies
198 no error value but what is if no stack address was set? We simply
199 return the value we have in the member. */
200 *stackaddr
= attr
->__stackaddr
;
203 weak_alias (__pthread_attr_getstackaddr
, pthread_attr_getstackaddr
)
205 link_warning (pthread_attr_getstackaddr
,
206 "the use of `pthread_attr_getstackaddr' is deprecated, use `pthread_attr_getstack'")
209 int __pthread_attr_setstacksize(pthread_attr_t
*attr
, size_t stacksize
)
211 #ifdef FLOATING_STACKS
212 /* We have to check against the maximum allowed stack size. This is no
213 problem if the manager is already started and we determined it. If
214 this hasn't happened, we have to find the limit outself. */
215 if (__pthread_max_stacksize
== 0)
216 __pthread_init_max_stacksize ();
218 if (stacksize
> __pthread_max_stacksize
)
221 /* We have a fixed size limit. */
222 if (stacksize
> STACK_SIZE
)
226 /* We don't accept value smaller than PTHREAD_STACK_MIN. */
227 if (stacksize
< PTHREAD_STACK_MIN
)
230 attr
->__stacksize
= stacksize
;
234 #if PTHREAD_STACK_MIN == 16384
235 weak_alias (__pthread_attr_setstacksize
, pthread_attr_setstacksize
)
237 versioned_symbol (libpthread
, __pthread_attr_setstacksize
,
238 pthread_attr_setstacksize
, GLIBC_2_3_3
);
240 # if SHLIB_COMPAT(libpthread, GLIBC_2_1, GLIBC_2_3_3)
242 int __old_pthread_attr_setstacksize(pthread_attr_t
*attr
, size_t stacksize
)
244 # ifdef FLOATING_STACKS
245 /* We have to check against the maximum allowed stack size. This is no
246 problem if the manager is already started and we determined it. If
247 this hasn't happened, we have to find the limit outself. */
248 if (__pthread_max_stacksize
== 0)
249 __pthread_init_max_stacksize ();
251 if (stacksize
> __pthread_max_stacksize
)
254 /* We have a fixed size limit. */
255 if (stacksize
> STACK_SIZE
)
259 /* We don't accept value smaller than old PTHREAD_STACK_MIN. */
260 if (stacksize
< 16384)
263 attr
->__stacksize
= stacksize
;
266 compat_symbol (libpthread
, __old_pthread_attr_setstacksize
,
267 pthread_attr_setstacksize
, GLIBC_2_1
);
272 int __pthread_attr_getstacksize(const pthread_attr_t
*attr
, size_t *stacksize
)
274 *stacksize
= attr
->__stacksize
;
277 weak_alias (__pthread_attr_getstacksize
, pthread_attr_getstacksize
)
279 int __pthread_attr_setstack (pthread_attr_t
*attr
, void *stackaddr
,
284 if ((((uintptr_t) stackaddr
)
285 & (__alignof__ (struct _pthread_descr_struct
) - 1)) != 0)
288 err
= __pthread_attr_setstacksize (attr
, stacksize
);
291 #ifndef _STACK_GROWS_UP
292 attr
->__stackaddr
= (char *) stackaddr
+ stacksize
;
294 attr
->__stackaddr
= stackaddr
;
296 attr
->__stackaddr_set
= 1;
302 #if PTHREAD_STACK_MIN == 16384
303 weak_alias (__pthread_attr_setstack
, pthread_attr_setstack
)
305 versioned_symbol (libpthread
, __pthread_attr_setstack
, pthread_attr_setstack
,
307 # if SHLIB_COMPAT(libpthread, GLIBC_2_2, GLIBC_2_3_3)
308 int __old_pthread_attr_setstack (pthread_attr_t
*attr
, void *stackaddr
,
313 if ((((uintptr_t) stackaddr
)
314 & (__alignof__ (struct _pthread_descr_struct
) - 1)) != 0)
317 err
= __old_pthread_attr_setstacksize (attr
, stacksize
);
320 # ifndef _STACK_GROWS_UP
321 attr
->__stackaddr
= (char *) stackaddr
+ stacksize
;
323 attr
->__stackaddr
= stackaddr
;
325 attr
->__stackaddr_set
= 1;
331 compat_symbol (libpthread
, __old_pthread_attr_setstack
, pthread_attr_setstack
,
337 int __pthread_attr_getstack (const pthread_attr_t
*attr
, void **stackaddr
,
340 /* XXX This function has a stupid definition. The standard specifies
341 no error value but what is if no stack address was set? We simply
342 return the value we have in the member. */
343 #ifndef _STACK_GROWS_UP
344 *stackaddr
= (char *) attr
->__stackaddr
- attr
->__stacksize
;
346 *stackaddr
= attr
->__stackaddr
;
348 *stacksize
= attr
->__stacksize
;
351 weak_alias (__pthread_attr_getstack
, pthread_attr_getstack
)
353 int pthread_getattr_np (pthread_t thread
, pthread_attr_t
*attr
)
355 pthread_handle handle
= thread_handle (thread
);
362 descr
= handle
->h_descr
;
364 attr
->__detachstate
= (descr
->p_detached
365 ? PTHREAD_CREATE_DETACHED
366 : PTHREAD_CREATE_JOINABLE
);
368 attr
->__schedpolicy
= __sched_getscheduler (descr
->p_pid
);
369 if (attr
->__schedpolicy
== -1)
372 if (__sched_getparam (descr
->p_pid
,
373 (struct sched_param
*) &attr
->__schedparam
) != 0)
376 attr
->__inheritsched
= descr
->p_inheritsched
;
377 attr
->__scope
= PTHREAD_SCOPE_SYSTEM
;
379 #ifdef _STACK_GROWS_DOWN
381 attr
->__stacksize
= descr
->p_stackaddr
- (char *)descr
->p_guardaddr
382 - descr
->p_guardsize
;
384 attr
->__stacksize
= (char *)(descr
+ 1) - (char *)descr
->p_guardaddr
385 - descr
->p_guardsize
;
389 attr
->__stacksize
= (char *)descr
->p_guardaddr
- descr
->p_stackaddr
;
391 attr
->__stacksize
= (char *)descr
->p_guardaddr
- (char *)descr
;
394 attr
->__guardsize
= descr
->p_guardsize
;
395 attr
->__stackaddr_set
= descr
->p_userstack
;
396 #ifdef NEED_SEPARATE_REGISTER_STACK
397 if (descr
->p_userstack
== 0)
398 attr
->__stacksize
*= 2;
399 /* XXX This is awkward. The guard pages are in the middle of the
400 two stacks. We must count the guard size in the stack size since
401 otherwise the range of the stack area cannot be computed. */
402 attr
->__stacksize
+= attr
->__guardsize
;
405 attr
->__stackaddr
= descr
->p_stackaddr
;
407 # ifndef _STACK_GROWS_UP
408 attr
->__stackaddr
= (char *)(descr
+ 1);
410 attr
->__stackaddr
= (char *)descr
;
415 if (attr
->__stackaddr
== NULL
)
417 if (descr
== &__pthread_initial_thread
)
420 /* Stack size limit. */
423 /* The safest way to get the top of the stack is to read
424 /proc/self/maps and locate the line into which
425 __libc_stack_end falls. */
426 FILE *fp
= fopen ("/proc/self/maps", "rc");
429 /* We need the limit of the stack in any case. */
430 else if (getrlimit (RLIMIT_STACK
, &rl
) != 0)
434 /* We need no locking. */
435 __fsetlocking (fp
, FSETLOCKING_BYCALLER
);
437 /* Until we found an entry (which should always be the case)
438 mark the result as a failure. */
443 uintptr_t last_to
= 0;
445 while (! feof_unlocked (fp
))
447 if (__getdelim (&line
, &linelen
, '\n', fp
) <= 0)
452 if (sscanf (line
, "%" SCNxPTR
"-%" SCNxPTR
, &from
, &to
) != 2)
454 if (from
<= (uintptr_t) __libc_stack_end
455 && (uintptr_t) __libc_stack_end
< to
)
457 /* Found the entry. Now we have the info we need. */
458 attr
->__stacksize
= rl
.rlim_cur
;
459 #ifdef _STACK_GROWS_UP
460 /* Don't check to enforce a limit on the __stacksize */
461 attr
->__stackaddr
= (void *) from
;
463 attr
->__stackaddr
= (void *) to
;
465 /* The limit might be too high. */
466 if ((size_t) attr
->__stacksize
467 > (size_t) attr
->__stackaddr
- last_to
)
468 attr
->__stacksize
= (size_t) attr
->__stackaddr
- last_to
;
471 /* We succeed and no need to look further. */