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"
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
;
42 attr
->__guardsize
= ps
;
44 attr
->__stackaddr
= NULL
;
45 attr
->__stackaddr_set
= 0;
46 attr
->__stacksize
= STACK_SIZE
- ps
;
49 strong_alias (__pthread_attr_init
, pthread_attr_init
)
51 int __pthread_attr_destroy(pthread_attr_t
*attr
)
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
)
62 attr
->__detachstate
= detachstate
;
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
;
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
)
82 memcpy (&attr
->__schedparam
, param
, sizeof (struct sched_param
));
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
));
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
)
99 attr
->__schedpolicy
= policy
;
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
;
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
)
115 attr
->__inheritsched
= inherit
;
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
;
125 strong_alias (__pthread_attr_getinheritsched
, pthread_attr_getinheritsched
)
127 int __pthread_attr_setscope(pthread_attr_t
*attr
, int scope
)
130 case PTHREAD_SCOPE_SYSTEM
:
131 attr
->__scope
= scope
;
133 case PTHREAD_SCOPE_PROCESS
:
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
;
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
;
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
;
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;
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
;
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'")
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
)
205 /* We have a fixed size limit. */
206 if (stacksize
> STACK_SIZE
)
210 /* We don't accept value smaller than PTHREAD_STACK_MIN. */
211 if (stacksize
< PTHREAD_STACK_MIN
)
214 attr
->__stacksize
= stacksize
;
218 #if PTHREAD_STACK_MIN == 16384 || defined __UCLIBC__
219 weak_alias (__pthread_attr_setstacksize
, pthread_attr_setstacksize
)
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
)
238 /* We have a fixed size limit. */
239 if (stacksize
> STACK_SIZE
)
243 /* We don't accept value smaller than old PTHREAD_STACK_MIN. */
244 if (stacksize
< 16384)
247 attr
->__stacksize
= stacksize
;
250 compat_symbol (libpthread
, __old_pthread_attr_setstacksize
,
251 pthread_attr_setstacksize
, GLIBC_2_1
);
256 int __pthread_attr_getstacksize(const pthread_attr_t
*attr
, size_t *stacksize
)
258 *stacksize
= attr
->__stacksize
;
261 weak_alias (__pthread_attr_getstacksize
, pthread_attr_getstacksize
)
263 int __pthread_attr_setstack (pthread_attr_t
*attr
, void *stackaddr
,
268 if ((((uintptr_t) stackaddr
)
269 & (__alignof__ (struct _pthread_descr_struct
) - 1)) != 0)
272 err
= __pthread_attr_setstacksize (attr
, stacksize
);
275 #ifndef _STACK_GROWS_UP
276 attr
->__stackaddr
= (char *) stackaddr
+ stacksize
;
278 attr
->__stackaddr
= stackaddr
;
280 attr
->__stackaddr_set
= 1;
286 #if PTHREAD_STACK_MIN == 16384 || defined __UCLIBC__
287 weak_alias (__pthread_attr_setstack
, pthread_attr_setstack
)
289 versioned_symbol (libpthread
, __pthread_attr_setstack
, pthread_attr_setstack
,
291 # if SHLIB_COMPAT(libpthread, GLIBC_2_2, GLIBC_2_3_3)
292 int __old_pthread_attr_setstack (pthread_attr_t
*attr
, void *stackaddr
,
297 if ((((uintptr_t) stackaddr
)
298 & (__alignof__ (struct _pthread_descr_struct
) - 1)) != 0)
301 err
= __old_pthread_attr_setstacksize (attr
, stacksize
);
304 # ifndef _STACK_GROWS_UP
305 attr
->__stackaddr
= (char *) stackaddr
+ stacksize
;
307 attr
->__stackaddr
= stackaddr
;
309 attr
->__stackaddr_set
= 1;
315 compat_symbol (libpthread
, __old_pthread_attr_setstack
, pthread_attr_setstack
,
321 int __pthread_attr_getstack (const pthread_attr_t
*attr
, void **stackaddr
,
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
;
330 *stackaddr
= attr
->__stackaddr
;
332 *stacksize
= attr
->__stacksize
;
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
);
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)
356 if (__sched_getparam (descr
->p_pid
,
357 (struct sched_param
*) &attr
->__schedparam
) != 0)
360 attr
->__inheritsched
= descr
->p_inheritsched
;
361 attr
->__scope
= PTHREAD_SCOPE_SYSTEM
;
363 #ifdef _STACK_GROWS_DOWN
365 attr
->__stacksize
= descr
->p_stackaddr
- (char *)descr
->p_guardaddr
366 - descr
->p_guardsize
;
368 attr
->__stacksize
= (char *)(descr
+ 1) - (char *)descr
->p_guardaddr
369 - descr
->p_guardsize
;
373 attr
->__stacksize
= (char *)descr
->p_guardaddr
- descr
->p_stackaddr
;
375 attr
->__stacksize
= (char *)descr
->p_guardaddr
- (char *)descr
;
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
;
389 attr
->__stackaddr
= descr
->p_stackaddr
;
391 # ifndef _STACK_GROWS_UP
392 attr
->__stackaddr
= (char *)(descr
+ 1);
394 attr
->__stackaddr
= (char *)descr
;
399 if (attr
->__stackaddr
== NULL
)
401 if (descr
== &__pthread_initial_thread
)
404 /* Stack size limit. */
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");
413 /* We need the limit of the stack in any case. */
414 else if (getrlimit (RLIMIT_STACK
, &rl
) != 0)
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. */
427 uintptr_t last_to
= 0;
429 while (! feof_unlocked (fp
))
431 if (getdelim (&line
, &linelen
, '\n', fp
) <= 0)
436 if (sscanf (line
, "%" SCNxPTR
"-%" SCNxPTR
, &from
, &to
) != 2)
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
;
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
;
455 /* We succeed and no need to look further. */