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 <sys/param.h>
21 #include <sys/resource.h>
23 #include "internals.h"
24 #include <shlib-compat.h>
26 int __pthread_attr_init_2_1(pthread_attr_t
*attr
)
28 size_t ps
= __getpagesize ();
30 attr
->__detachstate
= PTHREAD_CREATE_JOINABLE
;
31 attr
->__schedpolicy
= SCHED_OTHER
;
32 attr
->__schedparam
.sched_priority
= 0;
33 attr
->__inheritsched
= PTHREAD_EXPLICIT_SCHED
;
34 attr
->__scope
= PTHREAD_SCOPE_SYSTEM
;
35 attr
->__guardsize
= ps
;
36 attr
->__stackaddr
= NULL
;
37 attr
->__stackaddr_set
= 0;
38 attr
->__stacksize
= STACK_SIZE
- ps
;
42 versioned_symbol (libpthread
, __pthread_attr_init_2_1
, pthread_attr_init
,
45 #if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
46 int __pthread_attr_init_2_0(pthread_attr_t
*attr
)
48 attr
->__detachstate
= PTHREAD_CREATE_JOINABLE
;
49 attr
->__schedpolicy
= SCHED_OTHER
;
50 attr
->__schedparam
.sched_priority
= 0;
51 attr
->__inheritsched
= PTHREAD_EXPLICIT_SCHED
;
52 attr
->__scope
= PTHREAD_SCOPE_SYSTEM
;
55 compat_symbol (libpthread
, __pthread_attr_init_2_0
, pthread_attr_init
,
59 int pthread_attr_destroy(pthread_attr_t
*attr
)
64 int pthread_attr_setdetachstate(pthread_attr_t
*attr
, int detachstate
)
66 if (detachstate
< PTHREAD_CREATE_JOINABLE
||
67 detachstate
> PTHREAD_CREATE_DETACHED
)
69 attr
->__detachstate
= detachstate
;
73 int pthread_attr_getdetachstate(const pthread_attr_t
*attr
, int *detachstate
)
75 *detachstate
= attr
->__detachstate
;
79 int pthread_attr_setschedparam(pthread_attr_t
*attr
,
80 const struct sched_param
*param
)
82 int max_prio
= __sched_get_priority_max(attr
->__schedpolicy
);
83 int min_prio
= __sched_get_priority_min(attr
->__schedpolicy
);
85 if (param
->sched_priority
< min_prio
|| param
->sched_priority
> max_prio
)
87 memcpy (&attr
->__schedparam
, param
, sizeof (struct sched_param
));
91 int pthread_attr_getschedparam(const pthread_attr_t
*attr
,
92 struct sched_param
*param
)
94 memcpy (param
, &attr
->__schedparam
, sizeof (struct sched_param
));
98 int pthread_attr_setschedpolicy(pthread_attr_t
*attr
, int policy
)
100 if (policy
!= SCHED_OTHER
&& policy
!= SCHED_FIFO
&& policy
!= SCHED_RR
)
102 attr
->__schedpolicy
= policy
;
106 int pthread_attr_getschedpolicy(const pthread_attr_t
*attr
, int *policy
)
108 *policy
= attr
->__schedpolicy
;
112 int pthread_attr_setinheritsched(pthread_attr_t
*attr
, int inherit
)
114 if (inherit
!= PTHREAD_INHERIT_SCHED
&& inherit
!= PTHREAD_EXPLICIT_SCHED
)
116 attr
->__inheritsched
= inherit
;
120 int pthread_attr_getinheritsched(const pthread_attr_t
*attr
, int *inherit
)
122 *inherit
= attr
->__inheritsched
;
126 int pthread_attr_setscope(pthread_attr_t
*attr
, int scope
)
129 case PTHREAD_SCOPE_SYSTEM
:
130 attr
->__scope
= scope
;
132 case PTHREAD_SCOPE_PROCESS
:
139 int pthread_attr_getscope(const pthread_attr_t
*attr
, int *scope
)
141 *scope
= attr
->__scope
;
145 int __pthread_attr_setguardsize(pthread_attr_t
*attr
, size_t guardsize
)
147 /* The guard size must not be larger than the stack itself */
148 if (guardsize
>= attr
->__stacksize
) return EINVAL
;
150 attr
->__guardsize
= guardsize
;
154 weak_alias (__pthread_attr_setguardsize
, pthread_attr_setguardsize
)
156 int __pthread_attr_getguardsize(const pthread_attr_t
*attr
, size_t *guardsize
)
158 *guardsize
= attr
->__guardsize
;
161 weak_alias (__pthread_attr_getguardsize
, pthread_attr_getguardsize
)
163 int __pthread_attr_setstackaddr(pthread_attr_t
*attr
, void *stackaddr
)
165 attr
->__stackaddr
= stackaddr
;
166 attr
->__stackaddr_set
= 1;
169 weak_alias (__pthread_attr_setstackaddr
, pthread_attr_setstackaddr
)
171 link_warning (pthread_attr_setstackaddr
,
172 "the use of `pthread_attr_setstackaddr' is deprecated, use `pthread_attr_setstack'")
174 int __pthread_attr_getstackaddr(const pthread_attr_t
*attr
, void **stackaddr
)
176 /* XXX This function has a stupid definition. The standard specifies
177 no error value but what is if no stack address was set? We simply
178 return the value we have in the member. */
179 *stackaddr
= attr
->__stackaddr
;
182 weak_alias (__pthread_attr_getstackaddr
, pthread_attr_getstackaddr
)
184 link_warning (pthread_attr_getstackaddr
,
185 "the use of `pthread_attr_getstackaddr' is deprecated, use `pthread_attr_getstack'")
188 int __pthread_attr_setstacksize(pthread_attr_t
*attr
, size_t stacksize
)
190 #ifdef FLOATING_STACKS
191 /* We have to check against the maximum allowed stack size. This is no
192 problem if the manager is already started and we determined it. If
193 this hasn't happened, we have to find the limit outself. */
194 if (__pthread_max_stacksize
== 0)
195 __pthread_init_max_stacksize ();
197 if (stacksize
> __pthread_max_stacksize
)
200 /* We have a fixed size limit. */
201 if (stacksize
> STACK_SIZE
)
205 /* We don't accept value smaller than PTHREAD_STACK_MIN. */
206 if (stacksize
< PTHREAD_STACK_MIN
)
209 attr
->__stacksize
= stacksize
;
212 weak_alias (__pthread_attr_setstacksize
, pthread_attr_setstacksize
)
214 int __pthread_attr_getstacksize(const pthread_attr_t
*attr
, size_t *stacksize
)
216 *stacksize
= attr
->__stacksize
;
219 weak_alias (__pthread_attr_getstacksize
, pthread_attr_getstacksize
)
221 int __pthread_attr_setstack (pthread_attr_t
*attr
, void *stackaddr
,
226 if ((((uintptr_t) stackaddr
)
227 & (__alignof__ (struct _pthread_descr_struct
) - 1)) != 0)
230 err
= __pthread_attr_setstacksize (attr
, stacksize
);
233 #ifndef _STACK_GROWS_UP
234 attr
->__stackaddr
= (char *) stackaddr
+ stacksize
;
236 attr
->__stackaddr
= stackaddr
;
238 attr
->__stackaddr_set
= 1;
243 weak_alias (__pthread_attr_setstack
, pthread_attr_setstack
)
245 int __pthread_attr_getstack (const pthread_attr_t
*attr
, void **stackaddr
,
248 /* XXX This function has a stupid definition. The standard specifies
249 no error value but what is if no stack address was set? We simply
250 return the value we have in the member. */
251 #ifndef _STACK_GROWS_UP
252 *stackaddr
= (char *) attr
->__stackaddr
- attr
->__stacksize
;
254 *stackaddr
= attr
->__stackaddr
;
256 *stacksize
= attr
->__stacksize
;
259 weak_alias (__pthread_attr_getstack
, pthread_attr_getstack
)
261 int pthread_getattr_np (pthread_t thread
, pthread_attr_t
*attr
)
263 pthread_handle handle
= thread_handle (thread
);
269 descr
= handle
->h_descr
;
271 attr
->__detachstate
= (descr
->p_detached
272 ? PTHREAD_CREATE_DETACHED
273 : PTHREAD_CREATE_JOINABLE
);
275 attr
->__schedpolicy
= __sched_getscheduler (descr
->p_pid
);
276 if (attr
->__schedpolicy
== -1)
279 if (__sched_getparam (descr
->p_pid
,
280 (struct sched_param
*) &attr
->__schedparam
) != 0)
283 attr
->__inheritsched
= descr
->p_inheritsched
;
284 attr
->__scope
= PTHREAD_SCOPE_SYSTEM
;
285 #ifdef _STACK_GROWS_DOWN
286 attr
->__stacksize
= (char *)(descr
+ 1) - (char *)descr
->p_guardaddr
287 - descr
->p_guardsize
;
289 attr
->__stacksize
= (char *)descr
->p_guardaddr
- (char *)descr
;
291 attr
->__guardsize
= descr
->p_guardsize
;
292 attr
->__stackaddr_set
= descr
->p_userstack
;
293 #ifdef NEED_SEPARATE_REGISTER_STACK
294 if (descr
->p_userstack
== 0)
295 attr
->__stacksize
*= 2;
296 /* XXX This is awkward. The guard pages are in the middle of the
297 two stacks. We must count the guard size in the stack size since
298 otherwise the range of the stack area cannot be computed. */
299 attr
->__stacksize
+= attr
->__guardsize
;
301 #ifndef _STACK_GROWS_UP
302 attr
->__stackaddr
= (char *)(descr
+ 1);
304 attr
->__stackaddr
= (char *)descr
;