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