xref: /illumos-gate/usr/src/lib/libc/port/threads/pthr_attr.c (revision 4de2612967d06c4fdbf524a62556a1e8118a006f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "lint.h"
30 #include "thr_uberdata.h"
31 #include <sched.h>
32 
33 /*
34  * pthread_attr_init: allocates the attribute object and initializes it
35  * with the default values.
36  */
37 #pragma weak pthread_attr_init = _pthread_attr_init
38 int
39 _pthread_attr_init(pthread_attr_t *attr)
40 {
41 	thrattr_t *ap;
42 
43 	if ((ap = lmalloc(sizeof (thrattr_t))) != NULL) {
44 		if (_lpagesize == 0)
45 			_lpagesize = _sysconf(_SC_PAGESIZE);
46 		ap->stksize = 0;
47 		ap->stkaddr = NULL;
48 		ap->prio = 0;
49 		ap->policy = SCHED_OTHER;
50 		ap->inherit = PTHREAD_EXPLICIT_SCHED;
51 		ap->detachstate = PTHREAD_CREATE_JOINABLE;
52 		ap->scope = PTHREAD_SCOPE_PROCESS;
53 		ap->guardsize = _lpagesize;
54 		attr->__pthread_attrp = ap;
55 		return (0);
56 	}
57 	return (ENOMEM);
58 }
59 
60 /*
61  * pthread_attr_destroy: frees the attribute object and invalidates it
62  * with NULL value.
63  */
64 #pragma weak pthread_attr_destroy = _pthread_attr_destroy
65 int
66 _pthread_attr_destroy(pthread_attr_t *attr)
67 {
68 	if (attr == NULL || attr->__pthread_attrp == NULL)
69 		return (EINVAL);
70 	lfree(attr->__pthread_attrp, sizeof (thrattr_t));
71 	attr->__pthread_attrp = NULL;
72 	return (0);
73 }
74 
75 /*
76  * pthread_attr_setstacksize: sets the user stack size, minimum should
77  * be PTHREAD_STACK_MIN (MINSTACK).
78  * This is equivalent to stksize argument in thr_create().
79  */
80 #pragma weak pthread_attr_setstacksize = _pthread_attr_setstacksize
81 int
82 _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
83 {
84 	thrattr_t *ap;
85 
86 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
87 	    stacksize >= MINSTACK) {
88 		ap->stksize = stacksize;
89 		return (0);
90 	}
91 	return (EINVAL);
92 }
93 
94 /*
95  * pthread_attr_getstacksize: gets the user stack size.
96  */
97 #pragma weak pthread_attr_getstacksize = _pthread_attr_getstacksize
98 int
99 _pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
100 {
101 	thrattr_t *ap;
102 
103 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
104 	    stacksize != NULL) {
105 		*stacksize = ap->stksize;
106 		return (0);
107 	}
108 	return (EINVAL);
109 }
110 
111 /*
112  * pthread_attr_setstackaddr: sets the user stack addr.
113  * This is equivalent to stkaddr argument in thr_create().
114  */
115 #pragma weak pthread_attr_setstackaddr = _pthread_attr_setstackaddr
116 int
117 _pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
118 {
119 	thrattr_t *ap;
120 
121 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL) {
122 		ap->stkaddr = stackaddr;
123 		return (0);
124 	}
125 	return (EINVAL);
126 }
127 
128 /*
129  * pthread_attr_getstackaddr: gets the user stack addr.
130  */
131 #pragma weak pthread_attr_getstackaddr = _pthread_attr_getstackaddr
132 int
133 _pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
134 {
135 	thrattr_t *ap;
136 
137 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
138 	    stackaddr != NULL) {
139 		*stackaddr = ap->stkaddr;
140 		return (0);
141 	}
142 	return (EINVAL);
143 }
144 
145 /*
146  * pthread_attr_setdetachstate: sets the detach state to JOINABLE or
147  * DETACHED.
148  * This is equivalent to setting THR_DETACHED flag in thr_create().
149  */
150 #pragma weak pthread_attr_setdetachstate = _pthread_attr_setdetachstate
151 int
152 _pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
153 {
154 	thrattr_t *ap;
155 
156 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
157 	    (detachstate == PTHREAD_CREATE_DETACHED ||
158 	    detachstate == PTHREAD_CREATE_JOINABLE)) {
159 		ap->detachstate = detachstate;
160 		return (0);
161 	}
162 	return (EINVAL);
163 }
164 
165 /*
166  * pthread_attr_getdetachstate: gets the detach state.
167  */
168 #pragma weak pthread_attr_getdetachstate = _pthread_attr_getdetachstate
169 int
170 _pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
171 {
172 	thrattr_t *ap;
173 
174 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
175 	    detachstate != NULL) {
176 		*detachstate = ap->detachstate;
177 		return (0);
178 	}
179 	return (EINVAL);
180 }
181 
182 /*
183  * pthread_attr_setscope: sets the scope to SYSTEM or PROCESS.
184  * This is equivalent to setting THR_BOUND flag in thr_create().
185  */
186 #pragma weak pthread_attr_setscope = _pthread_attr_setscope
187 int
188 _pthread_attr_setscope(pthread_attr_t *attr, int scope)
189 {
190 	thrattr_t *ap;
191 
192 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
193 	    (scope == PTHREAD_SCOPE_SYSTEM ||
194 	    scope == PTHREAD_SCOPE_PROCESS)) {
195 		ap->scope = scope;
196 		return (0);
197 	}
198 	return (EINVAL);
199 }
200 
201 /*
202  * pthread_attr_getscope: gets the scheduling scope.
203  */
204 #pragma weak pthread_attr_getscope = _pthread_attr_getscope
205 int
206 _pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
207 {
208 	thrattr_t *ap;
209 
210 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
211 	    scope != NULL) {
212 		*scope = ap->scope;
213 		return (0);
214 	}
215 	return (EINVAL);
216 }
217 
218 /*
219  * pthread_attr_setinheritsched: sets the scheduling parameters to be
220  * EXPLICIT or INHERITED from parent thread.
221  */
222 #pragma weak pthread_attr_setinheritsched = _pthread_attr_setinheritsched
223 int
224 _pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
225 {
226 	thrattr_t *ap;
227 
228 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
229 	    (inherit == PTHREAD_EXPLICIT_SCHED ||
230 	    inherit == PTHREAD_INHERIT_SCHED)) {
231 		ap->inherit = inherit;
232 		return (0);
233 	}
234 	return (EINVAL);
235 }
236 
237 /*
238  * pthread_attr_getinheritsched: gets the scheduling inheritance.
239  */
240 #pragma weak pthread_attr_getinheritsched = _pthread_attr_getinheritsched
241 int
242 _pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
243 {
244 	thrattr_t *ap;
245 
246 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
247 	    inherit != NULL) {
248 		*inherit = ap->inherit;
249 		return (0);
250 	}
251 	return (EINVAL);
252 }
253 
254 /*
255  * pthread_attr_setschedpolicy: sets the scheduling policy to SCHED_RR,
256  * SCHED_FIFO or SCHED_OTHER.
257  */
258 #pragma weak pthread_attr_setschedpolicy = _pthread_attr_setschedpolicy
259 int
260 _pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
261 {
262 	thrattr_t *ap;
263 
264 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
265 	    (policy == SCHED_OTHER ||
266 	    policy == SCHED_FIFO ||
267 	    policy == SCHED_RR)) {
268 		ap->policy = policy;
269 		return (0);
270 	}
271 	return (EINVAL);
272 }
273 
274 /*
275  * pthread_attr_getpolicy: gets the scheduling policy.
276  */
277 #pragma weak pthread_attr_getschedpolicy = _pthread_attr_getschedpolicy
278 int
279 _pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
280 {
281 	thrattr_t *ap;
282 
283 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
284 	    policy != NULL) {
285 		*policy = ap->policy;
286 		return (0);
287 	}
288 	return (EINVAL);
289 }
290 
291 /*
292  * pthread_attr_setschedparam: sets the scheduling parameters.
293  * Currently, we support priority only.
294  */
295 #pragma weak pthread_attr_setschedparam = _pthread_attr_setschedparam
296 int
297 _pthread_attr_setschedparam(pthread_attr_t *attr,
298 	const struct sched_param *param)
299 {
300 	thrattr_t *ap;
301 	int	policy;
302 	int	pri;
303 
304 	if (attr == NULL || (ap = attr->__pthread_attrp) == NULL)
305 		return (EINVAL);
306 
307 	policy = ap->policy;
308 	pri = param->sched_priority;
309 	if (policy == SCHED_OTHER) {
310 		if ((pri < THREAD_MIN_PRIORITY || pri > THREAD_MAX_PRIORITY) &&
311 		    _validate_rt_prio(policy, pri))
312 			return (EINVAL);
313 	} else if (_validate_rt_prio(policy, pri)) {
314 		return (EINVAL);
315 	}
316 	ap->prio = pri;
317 	return (0);
318 }
319 
320 /*
321  * pthread_attr_getschedparam: gets the scheduling parameters.
322  * Currently, only priority is defined as sched parameter.
323  */
324 #pragma weak pthread_attr_getschedparam = _pthread_attr_getschedparam
325 int
326 _pthread_attr_getschedparam(const pthread_attr_t *attr,
327 					struct sched_param *param)
328 {
329 	thrattr_t *ap;
330 
331 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
332 	    param != NULL) {
333 		param->sched_priority = ap->prio;
334 		return (0);
335 	}
336 	return (EINVAL);
337 }
338 
339 /*
340  * UNIX98
341  * pthread_attr_setguardsize: sets the guardsize
342  */
343 #pragma weak pthread_attr_setguardsize = _pthread_attr_setguardsize
344 int
345 _pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
346 {
347 	thrattr_t *ap;
348 
349 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL) {
350 		ap->guardsize = guardsize;
351 		return (0);
352 	}
353 	return (EINVAL);
354 }
355 
356 /*
357  * UNIX98
358  * pthread_attr_getguardsize: gets the guardsize
359  */
360 #pragma weak pthread_attr_getguardsize = _pthread_attr_getguardsize
361 int
362 _pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
363 {
364 	thrattr_t *ap;
365 
366 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
367 	    guardsize != NULL) {
368 		*guardsize = ap->guardsize;
369 		return (0);
370 	}
371 	return (EINVAL);
372 }
373 
374 /*
375  * pthread_attr_setstack: sets the user stack addr and stack size.
376  * This is equivalent to the stack_base and stack_size arguments
377  * to thr_create().
378  */
379 #pragma weak pthread_attr_setstack = _pthread_attr_setstack
380 int
381 _pthread_attr_setstack(pthread_attr_t *attr,
382 	void *stackaddr, size_t stacksize)
383 {
384 	thrattr_t *ap;
385 
386 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
387 	    stacksize >= MINSTACK) {
388 		ap->stkaddr = stackaddr;
389 		ap->stksize = stacksize;
390 		return (0);
391 	}
392 	return (EINVAL);
393 }
394 
395 /*
396  * pthread_attr_getstack: gets the user stack addr and stack size.
397  */
398 #pragma weak pthread_attr_getstack = _pthread_attr_getstack
399 int
400 _pthread_attr_getstack(const pthread_attr_t *attr,
401 	void **stackaddr, size_t *stacksize)
402 {
403 	thrattr_t *ap;
404 
405 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
406 	    stackaddr != NULL && stacksize != NULL) {
407 		*stackaddr = ap->stkaddr;
408 		*stacksize = ap->stksize;
409 		return (0);
410 	}
411 	return (EINVAL);
412 }
413