chiark / gitweb /
Apply https://sourceware.org/git/?p=glibc.git;a=commit;h=d5dd6189d506068ed11c8bfa1e1e...
[eglibc.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 }