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