]> git.ipfire.org Git - thirdparty/glibc.git/blob - linuxthreads/attr.c
(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[thirdparty/glibc.git] / linuxthreads / attr.c
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 <inttypes.h>
19 #include <stdio.h>
20 #include <stdio_ext.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <sys/param.h>
25 #include <sys/resource.h>
26 #include "pthread.h"
27 #include "internals.h"
28 #include <shlib-compat.h>
29 #include <ldsodefs.h>
30
31
32 int __pthread_attr_init_2_1(pthread_attr_t *attr)
33 {
34 size_t ps = __getpagesize ();
35
36 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
37 attr->__schedpolicy = SCHED_OTHER;
38 attr->__schedparam.sched_priority = 0;
39 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
40 attr->__scope = PTHREAD_SCOPE_SYSTEM;
41 #ifdef NEED_SEPARATE_REGISTER_STACK
42 attr->__guardsize = ps + ps;
43 #else
44 attr->__guardsize = ps;
45 #endif
46 attr->__stackaddr = NULL;
47 attr->__stackaddr_set = 0;
48 attr->__stacksize = STACK_SIZE - ps;
49 return 0;
50 }
51
52 versioned_symbol (libpthread, __pthread_attr_init_2_1, pthread_attr_init,
53 GLIBC_2_1);
54
55 #if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
56 int __pthread_attr_init_2_0(pthread_attr_t *attr)
57 {
58 attr->__detachstate = PTHREAD_CREATE_JOINABLE;
59 attr->__schedpolicy = SCHED_OTHER;
60 attr->__schedparam.sched_priority = 0;
61 attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
62 attr->__scope = PTHREAD_SCOPE_SYSTEM;
63 return 0;
64 }
65 compat_symbol (libpthread, __pthread_attr_init_2_0, pthread_attr_init,
66 GLIBC_2_0);
67 #endif
68
69 int __pthread_attr_destroy(pthread_attr_t *attr)
70 {
71 return 0;
72 }
73 strong_alias (__pthread_attr_destroy, pthread_attr_destroy);
74
75 int __pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
76 {
77 if (detachstate < PTHREAD_CREATE_JOINABLE ||
78 detachstate > PTHREAD_CREATE_DETACHED)
79 return EINVAL;
80 attr->__detachstate = detachstate;
81 return 0;
82 }
83 strong_alias (__pthread_attr_setdetachstate, pthread_attr_setdetachstate);
84
85 int __pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
86 {
87 *detachstate = attr->__detachstate;
88 return 0;
89 }
90 strong_alias (__pthread_attr_getdetachstate, pthread_attr_getdetachstate);
91
92 int __pthread_attr_setschedparam(pthread_attr_t *attr,
93 const struct sched_param *param)
94 {
95 int max_prio = __sched_get_priority_max(attr->__schedpolicy);
96 int min_prio = __sched_get_priority_min(attr->__schedpolicy);
97
98 if (param->sched_priority < min_prio || param->sched_priority > max_prio)
99 return EINVAL;
100 memcpy (&attr->__schedparam, param, sizeof (struct sched_param));
101 return 0;
102 }
103 strong_alias (__pthread_attr_setschedparam, pthread_attr_setschedparam);
104
105 int __pthread_attr_getschedparam(const pthread_attr_t *attr,
106 struct sched_param *param)
107 {
108 memcpy (param, &attr->__schedparam, sizeof (struct sched_param));
109 return 0;
110 }
111 strong_alias (__pthread_attr_getschedparam, pthread_attr_getschedparam);
112
113 int __pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
114 {
115 if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
116 return EINVAL;
117 attr->__schedpolicy = policy;
118 return 0;
119 }
120 strong_alias (__pthread_attr_setschedpolicy, pthread_attr_setschedpolicy);
121
122 int __pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
123 {
124 *policy = attr->__schedpolicy;
125 return 0;
126 }
127 strong_alias (__pthread_attr_getschedpolicy, pthread_attr_getschedpolicy);
128
129 int __pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
130 {
131 if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED)
132 return EINVAL;
133 attr->__inheritsched = inherit;
134 return 0;
135 }
136 strong_alias (__pthread_attr_setinheritsched, pthread_attr_setinheritsched);
137
138 int __pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
139 {
140 *inherit = attr->__inheritsched;
141 return 0;
142 }
143 strong_alias (__pthread_attr_getinheritsched, pthread_attr_getinheritsched);
144
145 int __pthread_attr_setscope(pthread_attr_t *attr, int scope)
146 {
147 switch (scope) {
148 case PTHREAD_SCOPE_SYSTEM:
149 attr->__scope = scope;
150 return 0;
151 case PTHREAD_SCOPE_PROCESS:
152 return ENOTSUP;
153 default:
154 return EINVAL;
155 }
156 }
157 strong_alias (__pthread_attr_setscope, pthread_attr_setscope);
158
159 int __pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
160 {
161 *scope = attr->__scope;
162 return 0;
163 }
164 strong_alias (__pthread_attr_getscope, pthread_attr_getscope);
165
166 int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
167 {
168 /* The guard size must not be larger than the stack itself */
169 if (guardsize >= attr->__stacksize) return EINVAL;
170
171 attr->__guardsize = guardsize;
172
173 return 0;
174 }
175 weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize)
176
177 int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
178 {
179 *guardsize = attr->__guardsize;
180 return 0;
181 }
182 weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize)
183
184 int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
185 {
186 attr->__stackaddr = stackaddr;
187 attr->__stackaddr_set = 1;
188 return 0;
189 }
190 weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr)
191
192 link_warning (pthread_attr_setstackaddr,
193 "the use of `pthread_attr_setstackaddr' is deprecated, use `pthread_attr_setstack'")
194
195 int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
196 {
197 /* XXX This function has a stupid definition. The standard specifies
198 no error value but what is if no stack address was set? We simply
199 return the value we have in the member. */
200 *stackaddr = attr->__stackaddr;
201 return 0;
202 }
203 weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr)
204
205 link_warning (pthread_attr_getstackaddr,
206 "the use of `pthread_attr_getstackaddr' is deprecated, use `pthread_attr_getstack'")
207
208
209 int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
210 {
211 #ifdef FLOATING_STACKS
212 /* We have to check against the maximum allowed stack size. This is no
213 problem if the manager is already started and we determined it. If
214 this hasn't happened, we have to find the limit outself. */
215 if (__pthread_max_stacksize == 0)
216 __pthread_init_max_stacksize ();
217
218 if (stacksize > __pthread_max_stacksize)
219 return EINVAL;
220 #else
221 /* We have a fixed size limit. */
222 if (stacksize > STACK_SIZE)
223 return EINVAL;
224 #endif
225
226 /* We don't accept value smaller than PTHREAD_STACK_MIN. */
227 if (stacksize < PTHREAD_STACK_MIN)
228 return EINVAL;
229
230 attr->__stacksize = stacksize;
231 return 0;
232 }
233
234 #if PTHREAD_STACK_MIN == 16384
235 weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
236 #else
237 versioned_symbol (libpthread, __pthread_attr_setstacksize,
238 pthread_attr_setstacksize, GLIBC_2_3_3);
239
240 # if SHLIB_COMPAT(libpthread, GLIBC_2_1, GLIBC_2_3_3)
241
242 int __old_pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
243 {
244 # ifdef FLOATING_STACKS
245 /* We have to check against the maximum allowed stack size. This is no
246 problem if the manager is already started and we determined it. If
247 this hasn't happened, we have to find the limit outself. */
248 if (__pthread_max_stacksize == 0)
249 __pthread_init_max_stacksize ();
250
251 if (stacksize > __pthread_max_stacksize)
252 return EINVAL;
253 # else
254 /* We have a fixed size limit. */
255 if (stacksize > STACK_SIZE)
256 return EINVAL;
257 # endif
258
259 /* We don't accept value smaller than old PTHREAD_STACK_MIN. */
260 if (stacksize < 16384)
261 return EINVAL;
262
263 attr->__stacksize = stacksize;
264 return 0;
265 }
266 compat_symbol (libpthread, __old_pthread_attr_setstacksize,
267 pthread_attr_setstacksize, GLIBC_2_1);
268 # endif
269 #endif
270
271
272 int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
273 {
274 *stacksize = attr->__stacksize;
275 return 0;
276 }
277 weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
278
279 int __pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
280 size_t stacksize)
281 {
282 int err;
283
284 if ((((uintptr_t) stackaddr)
285 & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0)
286 err = EINVAL;
287 else
288 err = __pthread_attr_setstacksize (attr, stacksize);
289 if (err == 0)
290 {
291 #ifndef _STACK_GROWS_UP
292 attr->__stackaddr = (char *) stackaddr + stacksize;
293 #else
294 attr->__stackaddr = stackaddr;
295 #endif
296 attr->__stackaddr_set = 1;
297 }
298
299 return err;
300 }
301
302 #if PTHREAD_STACK_MIN == 16384
303 weak_alias (__pthread_attr_setstack, pthread_attr_setstack)
304 #else
305 versioned_symbol (libpthread, __pthread_attr_setstack, pthread_attr_setstack,
306 GLIBC_2_3_3);
307 # if SHLIB_COMPAT(libpthread, GLIBC_2_2, GLIBC_2_3_3)
308 int __old_pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
309 size_t stacksize)
310 {
311 int err;
312
313 if ((((uintptr_t) stackaddr)
314 & (__alignof__ (struct _pthread_descr_struct) - 1)) != 0)
315 err = EINVAL;
316 else
317 err = __old_pthread_attr_setstacksize (attr, stacksize);
318 if (err == 0)
319 {
320 # ifndef _STACK_GROWS_UP
321 attr->__stackaddr = (char *) stackaddr + stacksize;
322 # else
323 attr->__stackaddr = stackaddr;
324 # endif
325 attr->__stackaddr_set = 1;
326 }
327
328 return err;
329 }
330
331 compat_symbol (libpthread, __old_pthread_attr_setstack, pthread_attr_setstack,
332 GLIBC_2_2);
333
334 # endif
335 #endif
336
337 int __pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr,
338 size_t *stacksize)
339 {
340 /* XXX This function has a stupid definition. The standard specifies
341 no error value but what is if no stack address was set? We simply
342 return the value we have in the member. */
343 #ifndef _STACK_GROWS_UP
344 *stackaddr = (char *) attr->__stackaddr - attr->__stacksize;
345 #else
346 *stackaddr = attr->__stackaddr;
347 #endif
348 *stacksize = attr->__stacksize;
349 return 0;
350 }
351 weak_alias (__pthread_attr_getstack, pthread_attr_getstack)
352
353 int pthread_getattr_np (pthread_t thread, pthread_attr_t *attr)
354 {
355 pthread_handle handle = thread_handle (thread);
356 pthread_descr descr;
357 int ret = 0;
358
359 if (handle == NULL)
360 return ENOENT;
361
362 descr = handle->h_descr;
363
364 attr->__detachstate = (descr->p_detached
365 ? PTHREAD_CREATE_DETACHED
366 : PTHREAD_CREATE_JOINABLE);
367
368 attr->__schedpolicy = __sched_getscheduler (descr->p_pid);
369 if (attr->__schedpolicy == -1)
370 return errno;
371
372 if (__sched_getparam (descr->p_pid,
373 (struct sched_param *) &attr->__schedparam) != 0)
374 return errno;
375
376 attr->__inheritsched = descr->p_inheritsched;
377 attr->__scope = PTHREAD_SCOPE_SYSTEM;
378
379 #ifdef _STACK_GROWS_DOWN
380 # ifdef USE_TLS
381 attr->__stacksize = descr->p_stackaddr - (char *)descr->p_guardaddr
382 - descr->p_guardsize;
383 # else
384 attr->__stacksize = (char *)(descr + 1) - (char *)descr->p_guardaddr
385 - descr->p_guardsize;
386 # endif
387 #else
388 # ifdef USE_TLS
389 attr->__stacksize = (char *)descr->p_guardaddr - descr->p_stackaddr;
390 # else
391 attr->__stacksize = (char *)descr->p_guardaddr - (char *)descr;
392 # endif
393 #endif
394 attr->__guardsize = descr->p_guardsize;
395 attr->__stackaddr_set = descr->p_userstack;
396 #ifdef NEED_SEPARATE_REGISTER_STACK
397 if (descr->p_userstack == 0)
398 attr->__stacksize *= 2;
399 /* XXX This is awkward. The guard pages are in the middle of the
400 two stacks. We must count the guard size in the stack size since
401 otherwise the range of the stack area cannot be computed. */
402 attr->__stacksize += attr->__guardsize;
403 #endif
404 #ifdef USE_TLS
405 attr->__stackaddr = descr->p_stackaddr;
406 #else
407 # ifndef _STACK_GROWS_UP
408 attr->__stackaddr = (char *)(descr + 1);
409 # else
410 attr->__stackaddr = (char *)descr;
411 # endif
412 #endif
413
414 #ifdef USE_TLS
415 if (attr->__stackaddr == NULL)
416 #else
417 if (descr == &__pthread_initial_thread)
418 #endif
419 {
420 /* Stack size limit. */
421 struct rlimit rl;
422
423 /* The safest way to get the top of the stack is to read
424 /proc/self/maps and locate the line into which
425 __libc_stack_end falls. */
426 FILE *fp = fopen ("/proc/self/maps", "rc");
427 if (fp == NULL)
428 ret = errno;
429 /* We need the limit of the stack in any case. */
430 else if (getrlimit (RLIMIT_STACK, &rl) != 0)
431 ret = errno;
432 else
433 {
434 /* We need no locking. */
435 __fsetlocking (fp, FSETLOCKING_BYCALLER);
436
437 /* Until we found an entry (which should always be the case)
438 mark the result as a failure. */
439 ret = ENOENT;
440
441 char *line = NULL;
442 size_t linelen = 0;
443 uintptr_t last_to = 0;
444
445 while (! feof_unlocked (fp))
446 {
447 if (__getdelim (&line, &linelen, '\n', fp) <= 0)
448 break;
449
450 uintptr_t from;
451 uintptr_t to;
452 if (sscanf (line, "%" SCNxPTR "-%" SCNxPTR, &from, &to) != 2)
453 continue;
454 if (from <= (uintptr_t) __libc_stack_end
455 && (uintptr_t) __libc_stack_end < to)
456 {
457 /* Found the entry. Now we have the info we need. */
458 attr->__stacksize = rl.rlim_cur;
459 #ifdef _STACK_GROWS_UP
460 /* Don't check to enforce a limit on the __stacksize */
461 attr->__stackaddr = (void *) from;
462 #else
463 attr->__stackaddr = (void *) to;
464
465 /* The limit might be too high. */
466 if ((size_t) attr->__stacksize
467 > (size_t) attr->__stackaddr - last_to)
468 attr->__stacksize = (size_t) attr->__stackaddr - last_to;
469 #endif
470
471 /* We succeed and no need to look further. */
472 ret = 0;
473 break;
474 }
475 last_to = to;
476 }
477
478 fclose (fp);
479 free (line);
480 }
481 }
482
483 return 0;
484
485 }