OSDN Git Service

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