fc1ab596740e27b66709b87184d24fb4dd268a24
[kopensolaris-gnu/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 <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 #include <stackinfo.h>
26
27 int __pthread_attr_init_2_1(pthread_attr_t *attr)
28 {
29   size_t ps = __getpagesize ();
30
31   attr->__detachstate = PTHREAD_CREATE_JOINABLE;
32   attr->__schedpolicy = SCHED_OTHER;
33   attr->__schedparam.sched_priority = 0;
34   attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
35   attr->__scope = PTHREAD_SCOPE_SYSTEM;
36   attr->__guardsize = ps;
37   attr->__stackaddr = NULL;
38   attr->__stackaddr_set = 0;
39   attr->__stacksize = STACK_SIZE - ps;
40   return 0;
41 }
42
43 versioned_symbol (libpthread, __pthread_attr_init_2_1, pthread_attr_init,
44                   GLIBC_2_1);
45
46 #if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1)
47 int __pthread_attr_init_2_0(pthread_attr_t *attr)
48 {
49   attr->__detachstate = PTHREAD_CREATE_JOINABLE;
50   attr->__schedpolicy = SCHED_OTHER;
51   attr->__schedparam.sched_priority = 0;
52   attr->__inheritsched = PTHREAD_EXPLICIT_SCHED;
53   attr->__scope = PTHREAD_SCOPE_SYSTEM;
54   return 0;
55 }
56 compat_symbol (libpthread, __pthread_attr_init_2_0, pthread_attr_init,
57                GLIBC_2_0);
58 #endif
59
60 int pthread_attr_destroy(pthread_attr_t *attr)
61 {
62   return 0;
63 }
64
65 int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
66 {
67   if (detachstate < PTHREAD_CREATE_JOINABLE ||
68       detachstate > PTHREAD_CREATE_DETACHED)
69     return EINVAL;
70   attr->__detachstate = detachstate;
71   return 0;
72 }
73
74 int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
75 {
76   *detachstate = attr->__detachstate;
77   return 0;
78 }
79
80 int pthread_attr_setschedparam(pthread_attr_t *attr,
81                                const struct sched_param *param)
82 {
83   int max_prio = __sched_get_priority_max(attr->__schedpolicy);
84   int min_prio = __sched_get_priority_min(attr->__schedpolicy);
85
86   if (param->sched_priority < min_prio || param->sched_priority > max_prio)
87     return EINVAL;
88   memcpy (&attr->__schedparam, param, sizeof (struct sched_param));
89   return 0;
90 }
91
92 int pthread_attr_getschedparam(const pthread_attr_t *attr,
93                                struct sched_param *param)
94 {
95   memcpy (param, &attr->__schedparam, sizeof (struct sched_param));
96   return 0;
97 }
98
99 int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
100 {
101   if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR)
102     return EINVAL;
103   attr->__schedpolicy = policy;
104   return 0;
105 }
106
107 int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
108 {
109   *policy = attr->__schedpolicy;
110   return 0;
111 }
112
113 int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
114 {
115   if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED)
116     return EINVAL;
117   attr->__inheritsched = inherit;
118   return 0;
119 }
120
121 int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
122 {
123   *inherit = attr->__inheritsched;
124   return 0;
125 }
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
140 int pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
141 {
142   *scope = attr->__scope;
143   return 0;
144 }
145
146 int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
147 {
148   size_t ps = __getpagesize ();
149
150   /* First round up the guard size.  */
151   guardsize = page_roundup (guardsize, ps);
152
153   /* The guard size must not be larger than the stack itself */
154   if (guardsize >= attr->__stacksize) return EINVAL;
155
156   attr->__guardsize = guardsize;
157
158   return 0;
159 }
160 weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize)
161
162 int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
163 {
164   *guardsize = attr->__guardsize;
165   return 0;
166 }
167 weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize)
168
169 int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
170 {
171   attr->__stackaddr = stackaddr;
172   attr->__stackaddr_set = 1;
173   return 0;
174 }
175 weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr)
176
177 int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
178 {
179   /* XXX This function has a stupid definition.  The standard specifies
180      no error value but what is if no stack address was set?  We simply
181      return the value we have in the member.  */
182   *stackaddr = attr->__stackaddr;
183   return 0;
184 }
185 weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr)
186
187 int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
188 {
189 #ifdef FLOATING_STACKS
190   /* We have to check against the maximum allowed stack size.  This is no
191      problem if the manager is already started and we determined it.  If
192      this hasn't happened, we have to find the limit outself.  */
193   if (__pthread_max_stacksize == 0)
194     {
195       struct rlimit limit;
196
197       getrlimit(RLIMIT_STACK, &limit);
198 # ifdef NEED_SEPARATE_REGISTER_STACK
199       __pthread_max_stacksize = limit.rlim_max / 2;
200 # else
201       __pthread_max_stacksize = limit.rlim_max;
202 # endif
203     }
204
205   if (stacksize > __pthread_max_stacksize)
206     return EINVAL;
207 #else
208   /* We have a fixed size limit.  */
209   if (stacksize > STACK_SIZE)
210     return EINVAL;
211 #endif
212
213   /* We don't accept value smaller than PTHREAD_STACK_MIN.  */
214   if (stacksize < PTHREAD_STACK_MIN)
215     return EINVAL;
216
217   attr->__stacksize = stacksize;
218   return 0;
219 }
220 weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
221
222 int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
223 {
224   *stacksize = attr->__stacksize;
225   return 0;
226 }
227 weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
228
229 int __pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
230                              size_t stacksize)
231 {
232   int err;
233
234   if ((((uintptr_t) stackaddr)
235        & ~__alignof__ (struct _pthread_descr_struct)) != 0)
236     err = EINVAL;
237   else
238     err = __pthread_attr_setstacksize (attr, stacksize);
239   if (err == 0)
240     {
241 #ifdef _STACK_GROWS_UP
242       attr->__stackaddr = (char *) stackaddr + stacksize;
243 #else
244       attr->__stackaddr = stackaddr;
245 #endif
246       attr->__stackaddr_set = 1;
247     }
248
249   return err;
250 }
251 weak_alias (__pthread_attr_setstack, pthread_attr_setstack)
252
253 int __pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr,
254                              size_t *stacksize)
255 {
256   /* XXX This function has a stupid definition.  The standard specifies
257      no error value but what is if no stack address was set?  We simply
258      return the value we have in the member.  */
259   *stackaddr = attr->__stackaddr;
260   *stacksize = attr->__stacksize;
261   return 0;
262 }
263 weak_alias (__pthread_attr_getstack, pthread_attr_getstack)