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.
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.
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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Copyright 2015, Joyent, Inc.
32 #include "thr_uberdata.h"
36 * Default attribute object for pthread_create() with NULL attr pointer.
37 * Note that the 'guardsize' field is initialized on the first call.
42 static thrattr_t thrattr
= {
45 PTHREAD_CREATE_JOINABLE
, /* detachstate */
46 PTHREAD_CREATE_NONDAEMON_NP
, /* daemonstate */
47 PTHREAD_SCOPE_PROCESS
, /* scope */
49 SCHED_OTHER
, /* policy */
50 PTHREAD_INHERIT_SCHED
, /* inherit */
53 if (thrattr
.guardsize
== 0)
54 thrattr
.guardsize
= _sysconf(_SC_PAGESIZE
);
59 * pthread_attr_init: allocates the attribute object and initializes it
60 * with the default values.
62 #pragma weak _pthread_attr_init = pthread_attr_init
64 pthread_attr_init(pthread_attr_t
*attr
)
68 if ((ap
= lmalloc(sizeof (thrattr_t
))) != NULL
) {
70 attr
->__pthread_attrp
= ap
;
77 * pthread_attr_destroy: frees the attribute object and invalidates it
81 pthread_attr_destroy(pthread_attr_t
*attr
)
83 if (attr
== NULL
|| attr
->__pthread_attrp
== NULL
)
85 lfree(attr
->__pthread_attrp
, sizeof (thrattr_t
));
86 attr
->__pthread_attrp
= NULL
;
91 * pthread_attr_clone: make a copy of a pthread_attr_t.
94 pthread_attr_clone(pthread_attr_t
*attr
, const pthread_attr_t
*old_attr
)
97 const thrattr_t
*old_ap
=
98 old_attr
? old_attr
->__pthread_attrp
: def_thrattr();
102 if ((ap
= lmalloc(sizeof (thrattr_t
))) == NULL
)
105 attr
->__pthread_attrp
= ap
;
110 * pthread_attr_equal: compare two pthread_attr_t's, return 1 if equal.
111 * A NULL pthread_attr_t pointer implies default attributes.
112 * This is a consolidation-private interface, for librt.
115 pthread_attr_equal(const pthread_attr_t
*attr1
, const pthread_attr_t
*attr2
)
117 const thrattr_t
*ap1
= attr1
? attr1
->__pthread_attrp
: def_thrattr();
118 const thrattr_t
*ap2
= attr2
? attr2
->__pthread_attrp
: def_thrattr();
120 if (ap1
== NULL
|| ap2
== NULL
)
122 return (ap1
== ap2
|| memcmp(ap1
, ap2
, sizeof (thrattr_t
)) == 0);
126 * pthread_attr_setstacksize: sets the user stack size, minimum should
127 * be PTHREAD_STACK_MIN (MINSTACK).
128 * This is equivalent to stksize argument in thr_create().
131 pthread_attr_setstacksize(pthread_attr_t
*attr
, size_t stacksize
)
135 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
136 stacksize
>= MINSTACK
) {
137 ap
->stksize
= stacksize
;
144 * pthread_attr_getstacksize: gets the user stack size.
146 #pragma weak _pthread_attr_getstacksize = pthread_attr_getstacksize
148 pthread_attr_getstacksize(const pthread_attr_t
*attr
, size_t *stacksize
)
152 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
154 *stacksize
= ap
->stksize
;
161 * pthread_attr_setstackaddr: sets the user stack addr.
162 * This is equivalent to stkaddr argument in thr_create().
165 pthread_attr_setstackaddr(pthread_attr_t
*attr
, void *stackaddr
)
169 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
) {
170 ap
->stkaddr
= stackaddr
;
177 * pthread_attr_getstackaddr: gets the user stack addr.
179 #pragma weak _pthread_attr_getstackaddr = pthread_attr_getstackaddr
181 pthread_attr_getstackaddr(const pthread_attr_t
*attr
, void **stackaddr
)
185 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
187 *stackaddr
= ap
->stkaddr
;
194 * pthread_attr_setdetachstate: sets the detach state to DETACHED or JOINABLE.
195 * PTHREAD_CREATE_DETACHED is equivalent to thr_create(THR_DETACHED).
198 pthread_attr_setdetachstate(pthread_attr_t
*attr
, int detachstate
)
202 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
203 (detachstate
== PTHREAD_CREATE_DETACHED
||
204 detachstate
== PTHREAD_CREATE_JOINABLE
)) {
205 ap
->detachstate
= detachstate
;
212 * pthread_attr_getdetachstate: gets the detach state.
214 #pragma weak _pthread_attr_getdetachstate = pthread_attr_getdetachstate
216 pthread_attr_getdetachstate(const pthread_attr_t
*attr
, int *detachstate
)
220 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
221 detachstate
!= NULL
) {
222 *detachstate
= ap
->detachstate
;
229 * pthread_attr_setdaemonstate_np: sets the daemon state to DAEMON or NONDAEMON.
230 * PTHREAD_CREATE_DAEMON is equivalent to thr_create(THR_DAEMON).
231 * For now, this is a private interface in libc.
234 pthread_attr_setdaemonstate_np(pthread_attr_t
*attr
, int daemonstate
)
238 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
239 (daemonstate
== PTHREAD_CREATE_DAEMON_NP
||
240 daemonstate
== PTHREAD_CREATE_NONDAEMON_NP
)) {
241 ap
->daemonstate
= daemonstate
;
248 * pthread_attr_getdaemonstate_np: gets the daemon state.
249 * For now, this is a private interface in libc, but it is exposed in the
250 * mapfile for the purposes of testing only.
253 pthread_attr_getdaemonstate_np(const pthread_attr_t
*attr
, int *daemonstate
)
257 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
258 daemonstate
!= NULL
) {
259 *daemonstate
= ap
->daemonstate
;
266 * pthread_attr_setscope: sets the scope to SYSTEM or PROCESS.
267 * This is equivalent to setting THR_BOUND flag in thr_create().
270 pthread_attr_setscope(pthread_attr_t
*attr
, int scope
)
274 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
275 (scope
== PTHREAD_SCOPE_SYSTEM
||
276 scope
== PTHREAD_SCOPE_PROCESS
)) {
284 * pthread_attr_getscope: gets the scheduling scope.
286 #pragma weak _pthread_attr_getscope = pthread_attr_getscope
288 pthread_attr_getscope(const pthread_attr_t
*attr
, int *scope
)
292 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
301 * pthread_attr_setinheritsched: sets the scheduling parameters to be
302 * EXPLICIT or INHERITED from parent thread.
305 pthread_attr_setinheritsched(pthread_attr_t
*attr
, int inherit
)
309 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
310 (inherit
== PTHREAD_EXPLICIT_SCHED
||
311 inherit
== PTHREAD_INHERIT_SCHED
)) {
312 ap
->inherit
= inherit
;
319 * pthread_attr_getinheritsched: gets the scheduling inheritance.
321 #pragma weak _pthread_attr_getinheritsched = pthread_attr_getinheritsched
323 pthread_attr_getinheritsched(const pthread_attr_t
*attr
, int *inherit
)
327 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
329 *inherit
= ap
->inherit
;
336 * pthread_attr_setschedpolicy: sets the scheduling policy.
339 pthread_attr_setschedpolicy(pthread_attr_t
*attr
, int policy
)
343 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
344 policy
!= SCHED_SYS
&& get_info_by_policy(policy
) != NULL
) {
352 * pthread_attr_getpolicy: gets the scheduling policy.
354 #pragma weak _pthread_attr_getschedpolicy = pthread_attr_getschedpolicy
356 pthread_attr_getschedpolicy(const pthread_attr_t
*attr
, int *policy
)
360 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
362 *policy
= ap
->policy
;
369 * pthread_attr_setschedparam: sets the scheduling parameters.
370 * Currently, we support priority only.
373 pthread_attr_setschedparam(pthread_attr_t
*attr
,
374 const struct sched_param
*param
)
378 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
380 ap
->prio
= param
->sched_priority
;
387 * pthread_attr_getschedparam: gets the scheduling parameters.
388 * Currently, only priority is defined as sched parameter.
390 #pragma weak _pthread_attr_getschedparam = pthread_attr_getschedparam
392 pthread_attr_getschedparam(const pthread_attr_t
*attr
,
393 struct sched_param
*param
)
397 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
399 param
->sched_priority
= ap
->prio
;
407 * pthread_attr_setguardsize: sets the guardsize
410 pthread_attr_setguardsize(pthread_attr_t
*attr
, size_t guardsize
)
414 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
) {
415 ap
->guardsize
= guardsize
;
423 * pthread_attr_getguardsize: gets the guardsize
426 pthread_attr_getguardsize(const pthread_attr_t
*attr
, size_t *guardsize
)
430 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
432 *guardsize
= ap
->guardsize
;
439 * pthread_attr_setstack: sets the user stack addr and stack size.
440 * This is equivalent to the stack_base and stack_size arguments
444 pthread_attr_setstack(pthread_attr_t
*attr
,
445 void *stackaddr
, size_t stacksize
)
449 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
450 stacksize
>= MINSTACK
) {
451 ap
->stkaddr
= stackaddr
;
452 ap
->stksize
= stacksize
;
453 if (stackaddr
!= NULL
&&
454 setup_top_frame(stackaddr
, stacksize
, NULL
) == NULL
)
462 * pthread_attr_getstack: gets the user stack addr and stack size.
465 pthread_attr_getstack(const pthread_attr_t
*attr
,
466 void **stackaddr
, size_t *stacksize
)
470 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
471 stackaddr
!= NULL
&& stacksize
!= NULL
) {
472 *stackaddr
= ap
->stkaddr
;
473 *stacksize
= ap
->stksize
;
480 * This function is a common BSD extension to pthread which is used to obtain
481 * the attributes of a thread that might have changed after its creation, for
482 * example, it's stack address.
484 * Note, there is no setattr analogue, nor do we desire to add one at this time.
485 * Similarly there is no native threads API analogue (nor should we add one for
488 * The astute reader may note that there is a GNU version of this called
489 * pthread_getattr_np(). The two functions are similar, but subtley different in
490 * a rather important way. While the pthread_attr_get_np() expects to be given
491 * a pthread_attr_t that has had pthread_attr_init() called on in,
492 * pthread_getattr_np() does not. However, on GNU systems, where the function
493 * originates, the pthread_attr_t is not opaque and thus it is entirely safe to
494 * both call pthread_attr_init() and then call pthread_getattr_np() on the same
495 * attributes object. On illumos, since the pthread_attr_t is opaque, that would
496 * be a memory leak. As such, we don't provide it.
499 pthread_attr_get_np(pthread_t tid
, pthread_attr_t
*attr
)
502 ulwp_t
*self
= curthread
;
503 uberdata_t
*udp
= self
->ul_uberdata
;
504 ulwp_t
*target
= NULL
;
508 * To ensure that information about the target thread does not change or
509 * disappear while we're trying to interrogate it, we grab the uwlp
512 if (self
->ul_lwpid
== tid
) {
513 ulwp_lock(self
, udp
);
516 target
= find_lwp(tid
);
526 if ((ap
= attr
->__pthread_attrp
) == NULL
) {
531 ap
->stksize
= target
->ul_stksiz
;
532 ap
->stkaddr
= target
->ul_stk
;
533 if (target
->ul_usropts
& THR_DETACHED
) {
534 ap
->detachstate
= PTHREAD_CREATE_DETACHED
;
536 ap
->detachstate
= PTHREAD_CREATE_JOINABLE
;
539 if (target
->ul_usropts
& THR_DAEMON
) {
540 ap
->daemonstate
= PTHREAD_CREATE_DAEMON_NP
;
542 ap
->daemonstate
= PTHREAD_CREATE_NONDAEMON_NP
;
545 if (target
->ul_usropts
& THR_BOUND
) {
546 ap
->scope
= PTHREAD_SCOPE_SYSTEM
;
548 ap
->scope
= PTHREAD_SCOPE_PROCESS
;
550 ap
->prio
= target
->ul_pri
;
551 ap
->policy
= target
->ul_policy
;
552 ap
->inherit
= target
->ul_ptinherit
;
553 ap
->guardsize
= target
->ul_guardsize
;
557 ulwp_unlock(target
, udp
);