Adjusted.
[glibc.git] / linuxthreads / attr.c
blob2d06025ba42b605b3a57c069fa9146570b0739fc
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 <string.h>
19 #include <unistd.h>
20 #include <sys/param.h>
21 #include <sys/resource.h>
22 #include "pthread.h"
23 #include "internals.h"
24 #include <shlib-compat.h>
25 #include <stackinfo.h>
27 int __pthread_attr_init_2_1(pthread_attr_t *attr)
29 size_t ps = __getpagesize ();
31 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
32 attr->__schedpolicy = SCHED_OTHER;
33 attr->__schedparam.sched_priority = 0;
34 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
35 attr->__scope = PTHREAD_SCOPE_SYSTEM;
36 attr->__guardsize = ps;
37 attr->__stackaddr = NULL;
38 attr->__stackaddr_set = 0;
39 attr->__stacksize = STACK_SIZE - ps;
40 return 0;
43 versioned_symbol (libpthread, __pthread_attr_init_2_1, pthread_attr_init,
44 GLIBC_2_1);
46 #if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
47 int __pthread_attr_init_2_0(pthread_attr_t *attr)
49 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
50 attr->__schedpolicy = SCHED_OTHER;
51 attr->__schedparam.sched_priority = 0;
52 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
53 attr->__scope = PTHREAD_SCOPE_SYSTEM;
54 return 0;
56 compat_symbol (libpthread, __pthread_attr_init_2_0, pthread_attr_init,
57 GLIBC_2_0);
58 #endif
60 int pthread_attr_destroy(pthread_attr_t *attr)
62 return 0;
65 int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
67 if (detachstate < PTHREAD_CREATE_JOINABLE ||
68 detachstate > PTHREAD_CREATE_DETACHED)
69 return EINVAL;
70 attr->__detachstate = detachstate;
71 return 0;
74 int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
76 *detachstate = attr->__detachstate;
77 return 0;
80 int pthread_attr_setschedparam(pthread_attr_t *attr,
81 const struct sched_param *param)
83 int max_prio = __sched_get_priority_max(attr->__schedpolicy);
84 int min_prio = __sched_get_priority_min(attr->__schedpolicy);
86 if (param->sched_priority < min_prio || param->sched_priority > max_prio)
87 return EINVAL;
88 memcpy (&attr->__schedparam, param, sizeof (struct sched_param));
89 return 0;
92 int pthread_attr_getschedparam(const pthread_attr_t *attr,
93 struct sched_param *param)
95 memcpy (param, &attr->__schedparam, sizeof (struct sched_param));
96 return 0;
99 int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
101 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
102 return EINVAL;
103 attr->__schedpolicy = policy;
104 return 0;
107 int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
109 *policy = attr->__schedpolicy;
110 return 0;
113 int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
115 if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED)
116 return EINVAL;
117 attr->__inheritsched = inherit;
118 return 0;
121 int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
123 *inherit = attr->__inheritsched;
124 return 0;
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;
140 int pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
142 *scope = attr->__scope;
143 return 0;
146 int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
148 /* The guard size must not be larger than the stack itself */
149 if (guardsize >= attr->__stacksize) return EINVAL;
151 attr->__guardsize = guardsize;
153 return 0;
155 weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize)
157 int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
159 *guardsize = attr->__guardsize;
160 return 0;
162 weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize)
164 int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
166 attr->__stackaddr = stackaddr;
167 attr->__stackaddr_set = 1;
168 return 0;
170 weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr)
172 link_warning (pthread_attr_setstackaddr,
173 "the use of `pthread_attr_setstackaddr' is deprecated, use `pthread_attr_setstack'")
175 int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
177 /* XXX This function has a stupid definition. The standard specifies
178 no error value but what is if no stack address was set? We simply
179 return the value we have in the member. */
180 *stackaddr = attr->__stackaddr;
181 return 0;
183 weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr)
185 link_warning (pthread_attr_getstackaddr,
186 "the use of `pthread_attr_getstackaddr' is deprecated, use `pthread_attr_getstack'")
189 int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
191 #ifdef FLOATING_STACKS
192 /* We have to check against the maximum allowed stack size. This is no
193 problem if the manager is already started and we determined it. If
194 this hasn't happened, we have to find the limit outself. */
195 if (__pthread_max_stacksize == 0)
196 __pthread_init_max_stacksize ();
198 if (stacksize > __pthread_max_stacksize)
199 return EINVAL;
200 #else
201 /* We have a fixed size limit. */
202 if (stacksize > STACK_SIZE)
203 return EINVAL;
204 #endif
206 /* We don't accept value smaller than PTHREAD_STACK_MIN. */
207 if (stacksize < PTHREAD_STACK_MIN)
208 return EINVAL;
210 attr->__stacksize = stacksize;
211 return 0;
213 weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
215 int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
217 *stacksize = attr->__stacksize;
218 return 0;
220 weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
222 int __pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
223 size_t stacksize)
225 int err;
227 if ((((uintptr_t) stackaddr)
228 & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0)
229 err = EINVAL;
230 else
231 err = __pthread_attr_setstacksize (attr, stacksize);
232 if (err == 0)
234 #ifndef _STACK_GROWS_UP
235 attr->__stackaddr = (char *) stackaddr + stacksize;
236 #else
237 attr->__stackaddr = stackaddr;
238 #endif
239 attr->__stackaddr_set = 1;
242 return err;
244 weak_alias (__pthread_attr_setstack, pthread_attr_setstack)
246 int __pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr,
247 size_t *stacksize)
249 /* XXX This function has a stupid definition. The standard specifies
250 no error value but what is if no stack address was set? We simply
251 return the value we have in the member. */
252 #ifndef _STACK_GROWS_UP
253 *stackaddr = (char *) attr->__stackaddr - attr->__stacksize;
254 #else
255 *stackaddr = attr->__stackaddr;
256 #endif
257 *stacksize = attr->__stacksize;
258 return 0;
260 weak_alias (__pthread_attr_getstack, pthread_attr_getstack)
262 int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
264 pthread_handle handle = thread_handle (thread);
265 pthread_descr descr;
267 if (handle == NULL)
268 return ENOENT;
270 descr = handle->h_descr;
272 attr->__detachstate = (descr->p_detached
273 ? PTHREAD_CREATE_DETACHED
274 : PTHREAD_CREATE_JOINABLE);
276 attr->__schedpolicy = __sched_getscheduler (descr->p_pid);
277 if (attr->__schedpolicy == -1)
278 return errno;
280 if (__sched_getparam (descr->p_pid,
281 (struct sched_param *) &attr->__schedparam) != 0)
282 return errno;
284 attr->__inheritsched = descr->p_inheritsched;
285 attr->__scope = PTHREAD_SCOPE_SYSTEM;
286 attr->__stacksize = (char *)(descr + 1) - (char *)descr->p_guardaddr
287 - descr->p_guardsize;
288 attr->__guardsize = descr->p_guardsize;
289 attr->__stackaddr_set = descr->p_userstack;
290 #ifdef NEED_SEPARATE_REGISTER_STACK
291 if (descr->p_userstack == 0)
292 attr->__stacksize *= 2;
293 /* XXX This is awkward. The guard pages are in the middle of the
294 two stacks. We must count the guard size in the stack size since
295 otherwise the range of the stack area cannot be computed. */
296 attr->__stacksize += attr->__guardsize;
297 #endif
298 #ifndef _STACK_GROWS_UP
299 attr->__stackaddr = (char *)(descr + 1);
300 #else
301 # error __stackaddr not handled
302 #endif
304 return 0;