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. */
14
15 /* Handling of thread attributes */
16
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
__pthread_attr_init_2_1(pthread_attr_t * attr)26 int __pthread_attr_init_2_1(pthread_attr_t *attr)
27 {
28 size_t ps = __getpagesize ();
29
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;
39 return 0;
40 }
41
42 versioned_symbol (libpthread, __pthread_attr_init_2_1, pthread_attr_init,
43 GLIBC_2_1);
44
45 #if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
__pthread_attr_init_2_0(pthread_attr_t * attr)46 int __pthread_attr_init_2_0(pthread_attr_t *attr)
47 {
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;
53 return 0;
54 }
55 compat_symbol (libpthread, __pthread_attr_init_2_0, pthread_attr_init,
56 GLIBC_2_0);
57 #endif
58
pthread_attr_destroy(pthread_attr_t * attr)59 int pthread_attr_destroy(pthread_attr_t *attr)
60 {
61 return 0;
62 }
63
pthread_attr_setdetachstate(pthread_attr_t * attr,int detachstate)64 int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
65 {
66 if (detachstate < PTHREAD_CREATE_JOINABLE ||
67 detachstate > PTHREAD_CREATE_DETACHED)
68 return EINVAL;
69 attr->__detachstate = detachstate;
70 return 0;
71 }
72
pthread_attr_getdetachstate(const pthread_attr_t * attr,int * detachstate)73 int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
74 {
75 *detachstate = attr->__detachstate;
76 return 0;
77 }
78
pthread_attr_setschedparam(pthread_attr_t * attr,const struct sched_param * param)79 int pthread_attr_setschedparam(pthread_attr_t *attr,
80 const struct sched_param *param)
81 {
82 int max_prio = __sched_get_priority_max(attr->__schedpolicy);
83 int min_prio = __sched_get_priority_min(attr->__schedpolicy);
84
85 if (param->sched_priority < min_prio || param->sched_priority > max_prio)
86 return EINVAL;
87 memcpy (&attr->__schedparam, param, sizeof (struct sched_param));
88 return 0;
89 }
90
pthread_attr_getschedparam(const pthread_attr_t * attr,struct sched_param * param)91 int pthread_attr_getschedparam(const pthread_attr_t *attr,
92 struct sched_param *param)
93 {
94 memcpy (param, &attr->__schedparam, sizeof (struct sched_param));
95 return 0;
96 }
97
pthread_attr_setschedpolicy(pthread_attr_t * attr,int policy)98 int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
99 {
100 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
101 return EINVAL;
102 attr->__schedpolicy = policy;
103 return 0;
104 }
105
pthread_attr_getschedpolicy(const pthread_attr_t * attr,int * policy)106 int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
107 {
108 *policy = attr->__schedpolicy;
109 return 0;
110 }
111
pthread_attr_setinheritsched(pthread_attr_t * attr,int inherit)112 int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
113 {
114 if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED)
115 return EINVAL;
116 attr->__inheritsched = inherit;
117 return 0;
118 }
119
pthread_attr_getinheritsched(const pthread_attr_t * attr,int * inherit)120 int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
121 {
122 *inherit = attr->__inheritsched;
123 return 0;
124 }
125
pthread_attr_setscope(pthread_attr_t * attr,int scope)126 int pthread_attr_setscope(pthread_attr_t *attr, int scope)
127 {
128 switch (scope) {
129 case PTHREAD_SCOPE_SYSTEM:
130 attr->__scope = scope;
131 return 0;
132 case PTHREAD_SCOPE_PROCESS:
133 return ENOTSUP;
134 default:
135 return EINVAL;
136 }
137 }
138
pthread_attr_getscope(const pthread_attr_t * attr,int * scope)139 int pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
140 {
141 *scope = attr->__scope;
142 return 0;
143 }
144
__pthread_attr_setguardsize(pthread_attr_t * attr,size_t guardsize)145 int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
146 {
147 /* The guard size must not be larger than the stack itself */
148 if (guardsize >= attr->__stacksize) return EINVAL;
149
150 attr->__guardsize = guardsize;
151
152 return 0;
153 }
weak_alias(__pthread_attr_setguardsize,pthread_attr_setguardsize)154 weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize)
155
156 int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
157 {
158 *guardsize = attr->__guardsize;
159 return 0;
160 }
weak_alias(__pthread_attr_getguardsize,pthread_attr_getguardsize)161 weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize)
162
163 int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
164 {
165 attr->__stackaddr = stackaddr;
166 attr->__stackaddr_set = 1;
167 return 0;
168 }
weak_alias(__pthread_attr_setstackaddr,pthread_attr_setstackaddr)169 weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr)
170
171 link_warning (pthread_attr_setstackaddr,
172 "the use of `pthread_attr_setstackaddr' is deprecated, use `pthread_attr_setstack'")
173
174 int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
175 {
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;
180 return 0;
181 }
weak_alias(__pthread_attr_getstackaddr,pthread_attr_getstackaddr)182 weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr)
183
184 link_warning (pthread_attr_getstackaddr,
185 "the use of `pthread_attr_getstackaddr' is deprecated, use `pthread_attr_getstack'")
186
187
188 int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
189 {
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 ();
196
197 if (stacksize > __pthread_max_stacksize)
198 return EINVAL;
199 #else
200 /* We have a fixed size limit. */
201 if (stacksize > STACK_SIZE)
202 return EINVAL;
203 #endif
204
205 /* We don't accept value smaller than PTHREAD_STACK_MIN. */
206 if (stacksize < PTHREAD_STACK_MIN)
207 return EINVAL;
208
209 attr->__stacksize = stacksize;
210 return 0;
211 }
weak_alias(__pthread_attr_setstacksize,pthread_attr_setstacksize)212 weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
213
214 int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
215 {
216 *stacksize = attr->__stacksize;
217 return 0;
218 }
weak_alias(__pthread_attr_getstacksize,pthread_attr_getstacksize)219 weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
220
221 int __pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
222 size_t stacksize)
223 {
224 int err;
225
226 if ((((uintptr_t) stackaddr)
227 & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0)
228 err = EINVAL;
229 else
230 err = __pthread_attr_setstacksize (attr, stacksize);
231 if (err == 0)
232 {
233 #ifndef _STACK_GROWS_UP
234 attr->__stackaddr = (char *) stackaddr + stacksize;
235 #else
236 attr->__stackaddr = stackaddr;
237 #endif
238 attr->__stackaddr_set = 1;
239 }
240
241 return err;
242 }
weak_alias(__pthread_attr_setstack,pthread_attr_setstack)243 weak_alias (__pthread_attr_setstack, pthread_attr_setstack)
244
245 int __pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr,
246 size_t *stacksize)
247 {
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;
253 #else
254 *stackaddr = attr->__stackaddr;
255 #endif
256 *stacksize = attr->__stacksize;
257 return 0;
258 }
weak_alias(__pthread_attr_getstack,pthread_attr_getstack)259 weak_alias (__pthread_attr_getstack, pthread_attr_getstack)
260
261 int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
262 {
263 pthread_handle handle = thread_handle (thread);
264 pthread_descr descr;
265
266 if (handle == NULL)
267 return ENOENT;
268
269 descr = handle->h_descr;
270
271 attr->__detachstate = (descr->p_detached
272 ? PTHREAD_CREATE_DETACHED
273 : PTHREAD_CREATE_JOINABLE);
274
275 attr->__schedpolicy = __sched_getscheduler (descr->p_pid);
276 if (attr->__schedpolicy == -1)
277 return errno;
278
279 if (__sched_getparam (descr->p_pid,
280 (struct sched_param *) &attr->__schedparam) != 0)
281 return errno;
282
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;
288 #else
289 attr->__stacksize = (char *)descr->p_guardaddr - (char *)descr;
290 #endif
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;
300 #endif
301 #ifndef _STACK_GROWS_UP
302 attr->__stackaddr = (char *)(descr + 1);
303 #else
304 attr->__stackaddr = (char *)descr;
305 #endif
306
307 return 0;
308 }
309