xref: /illumos-gate/usr/src/lib/libc/port/threads/pthr_attr.c (revision ca9327a6de44d69ddab3668cc1e143ce781387a3)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 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  * Default attribute object for pthread_create() with NULL attr pointer.
35  * Note that the 'guardsize' field is initialized on the first call.
36  */
37 const thrattr_t *
38 def_thrattr(void)
39 {
40 	static thrattr_t thrattr = {
41 		0,				/* stksize */
42 		NULL,				/* stkaddr */
43 		PTHREAD_CREATE_JOINABLE,	/* detachstate */
44 		PTHREAD_CREATE_NONDAEMON_NP,	/* daemonstate */
45 		PTHREAD_SCOPE_PROCESS,		/* scope */
46 		0,				/* prio */
47 		SCHED_OTHER,			/* policy */
48 		PTHREAD_INHERIT_SCHED,		/* inherit */
49 		0				/* guardsize */
50 	};
51 	if (thrattr.guardsize == 0)
52 		thrattr.guardsize = _sysconf(_SC_PAGESIZE);
53 	return (&thrattr);
54 }
55 
56 /*
57  * pthread_attr_init: allocates the attribute object and initializes it
58  * with the default values.
59  */
60 #pragma weak pthread_attr_init = _pthread_attr_init
61 int
62 _pthread_attr_init(pthread_attr_t *attr)
63 {
64 	thrattr_t *ap;
65 
66 	if ((ap = lmalloc(sizeof (thrattr_t))) != NULL) {
67 		*ap = *def_thrattr();
68 		attr->__pthread_attrp = ap;
69 		return (0);
70 	}
71 	return (ENOMEM);
72 }
73 
74 /*
75  * pthread_attr_destroy: frees the attribute object and invalidates it
76  * with NULL value.
77  */
78 #pragma weak pthread_attr_destroy = _pthread_attr_destroy
79 int
80 _pthread_attr_destroy(pthread_attr_t *attr)
81 {
82 	if (attr == NULL || attr->__pthread_attrp == NULL)
83 		return (EINVAL);
84 	lfree(attr->__pthread_attrp, sizeof (thrattr_t));
85 	attr->__pthread_attrp = NULL;
86 	return (0);
87 }
88 
89 /*
90  * _pthread_attr_clone: make a copy of a pthread_attr_t.
91  */
92 int
93 _pthread_attr_clone(pthread_attr_t *attr, const pthread_attr_t *old_attr)
94 {
95 	thrattr_t *ap;
96 	const thrattr_t *old_ap =
97 	    old_attr? old_attr->__pthread_attrp : def_thrattr();
98 
99 	if (old_ap == NULL)
100 		return (EINVAL);
101 	if ((ap = lmalloc(sizeof (thrattr_t))) == NULL)
102 		return (ENOMEM);
103 	*ap = *old_ap;
104 	attr->__pthread_attrp = ap;
105 	return (0);
106 }
107 
108 /*
109  * _pthread_attr_equal: compare two pthread_attr_t's, return 1 if equal.
110  * A NULL pthread_attr_t pointer implies default attributes.
111  * This is a consolidation-private interface, for librt.
112  */
113 int
114 _pthread_attr_equal(const pthread_attr_t *attr1, const pthread_attr_t *attr2)
115 {
116 	const thrattr_t *ap1 = attr1? attr1->__pthread_attrp : def_thrattr();
117 	const thrattr_t *ap2 = attr2? attr2->__pthread_attrp : def_thrattr();
118 
119 	if (ap1 == NULL || ap2 == NULL)
120 		return (0);
121 	return (ap1 == ap2 || memcmp(ap1, ap2, sizeof (thrattr_t)) == 0);
122 }
123 
124 /*
125  * pthread_attr_setstacksize: sets the user stack size, minimum should
126  * be PTHREAD_STACK_MIN (MINSTACK).
127  * This is equivalent to stksize argument in thr_create().
128  */
129 #pragma weak pthread_attr_setstacksize = _pthread_attr_setstacksize
130 int
131 _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
132 {
133 	thrattr_t *ap;
134 
135 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
136 	    stacksize >= MINSTACK) {
137 		ap->stksize = stacksize;
138 		return (0);
139 	}
140 	return (EINVAL);
141 }
142 
143 /*
144  * pthread_attr_getstacksize: gets the user stack size.
145  */
146 #pragma weak pthread_attr_getstacksize = _pthread_attr_getstacksize
147 int
148 _pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize)
149 {
150 	thrattr_t *ap;
151 
152 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
153 	    stacksize != NULL) {
154 		*stacksize = ap->stksize;
155 		return (0);
156 	}
157 	return (EINVAL);
158 }
159 
160 /*
161  * pthread_attr_setstackaddr: sets the user stack addr.
162  * This is equivalent to stkaddr argument in thr_create().
163  */
164 #pragma weak pthread_attr_setstackaddr = _pthread_attr_setstackaddr
165 int
166 _pthread_attr_setstackaddr(pthread_attr_t *attr, void *stackaddr)
167 {
168 	thrattr_t *ap;
169 
170 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL) {
171 		ap->stkaddr = stackaddr;
172 		return (0);
173 	}
174 	return (EINVAL);
175 }
176 
177 /*
178  * pthread_attr_getstackaddr: gets the user stack addr.
179  */
180 #pragma weak pthread_attr_getstackaddr = _pthread_attr_getstackaddr
181 int
182 _pthread_attr_getstackaddr(const pthread_attr_t *attr, void **stackaddr)
183 {
184 	thrattr_t *ap;
185 
186 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
187 	    stackaddr != NULL) {
188 		*stackaddr = ap->stkaddr;
189 		return (0);
190 	}
191 	return (EINVAL);
192 }
193 
194 /*
195  * pthread_attr_setdetachstate: sets the detach state to DETACHED or JOINABLE.
196  * PTHREAD_CREATE_DETACHED is equivalent to thr_create(THR_DETACHED).
197  */
198 #pragma weak pthread_attr_setdetachstate = _pthread_attr_setdetachstate
199 int
200 _pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
201 {
202 	thrattr_t *ap;
203 
204 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
205 	    (detachstate == PTHREAD_CREATE_DETACHED ||
206 	    detachstate == PTHREAD_CREATE_JOINABLE)) {
207 		ap->detachstate = detachstate;
208 		return (0);
209 	}
210 	return (EINVAL);
211 }
212 
213 /*
214  * pthread_attr_getdetachstate: gets the detach state.
215  */
216 #pragma weak pthread_attr_getdetachstate = _pthread_attr_getdetachstate
217 int
218 _pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
219 {
220 	thrattr_t *ap;
221 
222 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
223 	    detachstate != NULL) {
224 		*detachstate = ap->detachstate;
225 		return (0);
226 	}
227 	return (EINVAL);
228 }
229 
230 /*
231  * pthread_attr_setdaemonstate_np: sets the daemon state to DAEMON or NONDAEMON.
232  * PTHREAD_CREATE_DAEMON is equivalent to thr_create(THR_DAEMON).
233  * For now, this is a private interface in libc.
234  */
235 int
236 _pthread_attr_setdaemonstate_np(pthread_attr_t *attr, int daemonstate)
237 {
238 	thrattr_t *ap;
239 
240 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
241 	    (daemonstate == PTHREAD_CREATE_DAEMON_NP ||
242 	    daemonstate == PTHREAD_CREATE_NONDAEMON_NP)) {
243 		ap->daemonstate = daemonstate;
244 		return (0);
245 	}
246 	return (EINVAL);
247 }
248 
249 /*
250  * pthread_attr_getdaemonstate_np: gets the daemon state.
251  * For now, this is a private interface in libc.
252  */
253 int
254 _pthread_attr_getdaemonstate_np(const pthread_attr_t *attr, int *daemonstate)
255 {
256 	thrattr_t *ap;
257 
258 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
259 	    daemonstate != NULL) {
260 		*daemonstate = ap->daemonstate;
261 		return (0);
262 	}
263 	return (EINVAL);
264 }
265 
266 /*
267  * pthread_attr_setscope: sets the scope to SYSTEM or PROCESS.
268  * This is equivalent to setting THR_BOUND flag in thr_create().
269  */
270 #pragma weak pthread_attr_setscope = _pthread_attr_setscope
271 int
272 _pthread_attr_setscope(pthread_attr_t *attr, int scope)
273 {
274 	thrattr_t *ap;
275 
276 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
277 	    (scope == PTHREAD_SCOPE_SYSTEM ||
278 	    scope == PTHREAD_SCOPE_PROCESS)) {
279 		ap->scope = scope;
280 		return (0);
281 	}
282 	return (EINVAL);
283 }
284 
285 /*
286  * pthread_attr_getscope: gets the scheduling scope.
287  */
288 #pragma weak pthread_attr_getscope = _pthread_attr_getscope
289 int
290 _pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
291 {
292 	thrattr_t *ap;
293 
294 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
295 	    scope != NULL) {
296 		*scope = ap->scope;
297 		return (0);
298 	}
299 	return (EINVAL);
300 }
301 
302 /*
303  * pthread_attr_setinheritsched: sets the scheduling parameters to be
304  * EXPLICIT or INHERITED from parent thread.
305  */
306 #pragma weak pthread_attr_setinheritsched = _pthread_attr_setinheritsched
307 int
308 _pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
309 {
310 	thrattr_t *ap;
311 
312 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
313 	    (inherit == PTHREAD_EXPLICIT_SCHED ||
314 	    inherit == PTHREAD_INHERIT_SCHED)) {
315 		ap->inherit = inherit;
316 		return (0);
317 	}
318 	return (EINVAL);
319 }
320 
321 /*
322  * pthread_attr_getinheritsched: gets the scheduling inheritance.
323  */
324 #pragma weak pthread_attr_getinheritsched = _pthread_attr_getinheritsched
325 int
326 _pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
327 {
328 	thrattr_t *ap;
329 
330 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
331 	    inherit != NULL) {
332 		*inherit = ap->inherit;
333 		return (0);
334 	}
335 	return (EINVAL);
336 }
337 
338 /*
339  * pthread_attr_setschedpolicy: sets the scheduling policy.
340  */
341 #pragma weak pthread_attr_setschedpolicy = _pthread_attr_setschedpolicy
342 int
343 _pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
344 {
345 	thrattr_t *ap;
346 
347 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
348 	    policy != SCHED_SYS && get_info_by_policy(policy) != NULL) {
349 		ap->policy = policy;
350 		return (0);
351 	}
352 	return (EINVAL);
353 }
354 
355 /*
356  * pthread_attr_getpolicy: gets the scheduling policy.
357  */
358 #pragma weak pthread_attr_getschedpolicy = _pthread_attr_getschedpolicy
359 int
360 _pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
361 {
362 	thrattr_t *ap;
363 
364 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
365 	    policy != NULL) {
366 		*policy = ap->policy;
367 		return (0);
368 	}
369 	return (EINVAL);
370 }
371 
372 /*
373  * pthread_attr_setschedparam: sets the scheduling parameters.
374  * Currently, we support priority only.
375  */
376 #pragma weak pthread_attr_setschedparam = _pthread_attr_setschedparam
377 int
378 _pthread_attr_setschedparam(pthread_attr_t *attr,
379 	const struct sched_param *param)
380 {
381 	thrattr_t *ap;
382 
383 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
384 	    param != NULL) {
385 		ap->prio = param->sched_priority;
386 		return (0);
387 	}
388 	return (EINVAL);
389 }
390 
391 /*
392  * pthread_attr_getschedparam: gets the scheduling parameters.
393  * Currently, only priority is defined as sched parameter.
394  */
395 #pragma weak pthread_attr_getschedparam = _pthread_attr_getschedparam
396 int
397 _pthread_attr_getschedparam(const pthread_attr_t *attr,
398 					struct sched_param *param)
399 {
400 	thrattr_t *ap;
401 
402 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
403 	    param != NULL) {
404 		param->sched_priority = ap->prio;
405 		return (0);
406 	}
407 	return (EINVAL);
408 }
409 
410 /*
411  * UNIX98
412  * pthread_attr_setguardsize: sets the guardsize
413  */
414 #pragma weak pthread_attr_setguardsize = _pthread_attr_setguardsize
415 int
416 _pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize)
417 {
418 	thrattr_t *ap;
419 
420 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL) {
421 		ap->guardsize = guardsize;
422 		return (0);
423 	}
424 	return (EINVAL);
425 }
426 
427 /*
428  * UNIX98
429  * pthread_attr_getguardsize: gets the guardsize
430  */
431 #pragma weak pthread_attr_getguardsize = _pthread_attr_getguardsize
432 int
433 _pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guardsize)
434 {
435 	thrattr_t *ap;
436 
437 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
438 	    guardsize != NULL) {
439 		*guardsize = ap->guardsize;
440 		return (0);
441 	}
442 	return (EINVAL);
443 }
444 
445 /*
446  * pthread_attr_setstack: sets the user stack addr and stack size.
447  * This is equivalent to the stack_base and stack_size arguments
448  * to thr_create().
449  */
450 #pragma weak pthread_attr_setstack = _pthread_attr_setstack
451 int
452 _pthread_attr_setstack(pthread_attr_t *attr,
453 	void *stackaddr, size_t stacksize)
454 {
455 	thrattr_t *ap;
456 
457 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
458 	    stacksize >= MINSTACK) {
459 		ap->stkaddr = stackaddr;
460 		ap->stksize = stacksize;
461 		return (0);
462 	}
463 	return (EINVAL);
464 }
465 
466 /*
467  * pthread_attr_getstack: gets the user stack addr and stack size.
468  */
469 #pragma weak pthread_attr_getstack = _pthread_attr_getstack
470 int
471 _pthread_attr_getstack(const pthread_attr_t *attr,
472 	void **stackaddr, size_t *stacksize)
473 {
474 	thrattr_t *ap;
475 
476 	if (attr != NULL && (ap = attr->__pthread_attrp) != NULL &&
477 	    stackaddr != NULL && stacksize != NULL) {
478 		*stackaddr = ap->stkaddr;
479 		*stacksize = ap->stksize;
480 		return (0);
481 	}
482 	return (EINVAL);
483 }
484