Update.
[glibc.git] / linuxthreads / attr.c
blob580da03b4072d22c9c595f3391803d6a7fd5866b
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)
197 struct rlimit limit;
199 getrlimit(RLIMIT_STACK, &limit);
200 # ifdef NEED_SEPARATE_REGISTER_STACK
201 __pthread_max_stacksize = limit.rlim_max / 2;
202 # else
203 __pthread_max_stacksize = limit.rlim_max;
204 # endif
207 if (stacksize > __pthread_max_stacksize)
208 return EINVAL;
209 #else
210 /* We have a fixed size limit. */
211 if (stacksize > STACK_SIZE)
212 return EINVAL;
213 #endif
215 /* We don't accept value smaller than PTHREAD_STACK_MIN. */
216 if (stacksize < PTHREAD_STACK_MIN)
217 return EINVAL;
219 attr->__stacksize = stacksize;
220 return 0;
222 weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
224 int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
226 *stacksize = attr->__stacksize;
227 return 0;
229 weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
231 int __pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
232 size_t stacksize)
234 int err;
236 if ((((uintptr_t) stackaddr)
237 & ~__alignof__ (struct _pthread_descr_struct)) != 0)
238 err = EINVAL;
239 else
240 err = __pthread_attr_setstacksize (attr, stacksize);
241 if (err == 0)
243 #ifndef _STACK_GROWS_UP
244 attr->__stackaddr = (char *) stackaddr + stacksize;
245 #else
246 attr->__stackaddr = stackaddr;
247 #endif
248 attr->__stackaddr_set = 1;
251 return err;
253 weak_alias (__pthread_attr_setstack, pthread_attr_setstack)
255 int __pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr,
256 size_t *stacksize)
258 /* XXX This function has a stupid definition. The standard specifies
259 no error value but what is if no stack address was set? We simply
260 return the value we have in the member. */
261 #ifndef _STACK_GROWS_UP
262 *stackaddr = (char *) attr->__stackaddr - attr->__stacksize;
263 #else
264 *stackaddr = attr->__stackaddr;
265 #endif
266 *stacksize = attr->__stacksize;
267 return 0;
269 weak_alias (__pthread_attr_getstack, pthread_attr_getstack)