(__pthread_attr_setguardsize): Don't round guardsize here.
[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   /* The guard size must not be larger than the stack itself */
149   if (guardsize >= attr->__stacksize) return EINVAL;
150
151   attr->__guardsize = guardsize;
152
153   return 0;
154 }
155 weak_alias (__pthread_attr_setguardsize, pthread_attr_setguardsize)
156
157 int __pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
158 {
159   *guardsize = attr->__guardsize;
160   return 0;
161 }
162 weak_alias (__pthread_attr_getguardsize, pthread_attr_getguardsize)
163
164 int __pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
165 {
166   attr->__stackaddr = stackaddr;
167   attr->__stackaddr_set = 1;
168   return 0;
169 }
170 weak_alias (__pthread_attr_setstackaddr, pthread_attr_setstackaddr)
171
172 int __pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
173 {
174   /* XXX This function has a stupid definition.  The standard specifies
175      no error value but what is if no stack address was set?  We simply
176      return the value we have in the member.  */
177   *stackaddr = attr->__stackaddr;
178   return 0;
179 }
180 weak_alias (__pthread_attr_getstackaddr, pthread_attr_getstackaddr)
181
182 int __pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
183 {
184 #ifdef FLOATING_STACKS
185   /* We have to check against the maximum allowed stack size.  This is no
186      problem if the manager is already started and we determined it.  If
187      this hasn't happened, we have to find the limit outself.  */
188   if (__pthread_max_stacksize == 0)
189     {
190       struct rlimit limit;
191
192       getrlimit(RLIMIT_STACK, &limit);
193 # ifdef NEED_SEPARATE_REGISTER_STACK
194       __pthread_max_stacksize = limit.rlim_max / 2;
195 # else
196       __pthread_max_stacksize = limit.rlim_max;
197 # endif
198     }
199
200   if (stacksize > __pthread_max_stacksize)
201     return EINVAL;
202 #else
203   /* We have a fixed size limit.  */
204   if (stacksize > STACK_SIZE)
205     return EINVAL;
206 #endif
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 weak_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize)
216
217 int __pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
218 {
219   *stacksize = attr->__stacksize;
220   return 0;
221 }
222 weak_alias (__pthread_attr_getstacksize, pthread_attr_getstacksize)
223
224 int __pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr,
225                              size_t stacksize)
226 {
227   int err;
228
229   if ((((uintptr_t) stackaddr)
230        & ~__alignof__ (struct _pthread_descr_struct)) != 0)
231     err = EINVAL;
232   else
233     err = __pthread_attr_setstacksize (attr, stacksize);
234   if (err == 0)
235     {
236 #ifdef _STACK_GROWS_UP
237       attr->__stackaddr = (char *) stackaddr + stacksize;
238 #else
239       attr->__stackaddr = stackaddr;
240 #endif
241       attr->__stackaddr_set = 1;
242     }
243
244   return err;
245 }
246 weak_alias (__pthread_attr_setstack, pthread_attr_setstack)
247
248 int __pthread_attr_getstack (const pthread_attr_t *attr, void **stackaddr,
249                              size_t *stacksize)
250 {
251   /* XXX This function has a stupid definition.  The standard specifies
252      no error value but what is if no stack address was set?  We simply
253      return the value we have in the member.  */
254   *stackaddr = attr->__stackaddr;
255   *stacksize = attr->__stacksize;
256   return 0;
257 }
258 weak_alias (__pthread_attr_getstack, pthread_attr_getstack)