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 2018, Joyent, Inc.
32 #include "thr_uberdata.h"
33 #include <sys/ctype.h>
38 * Default attribute object for pthread_create() with NULL attr pointer.
39 * Note that the 'guardsize' field is initialized on the first call.
44 static thrattr_t thrattr
= {
47 PTHREAD_CREATE_JOINABLE
, /* detachstate */
48 PTHREAD_CREATE_NONDAEMON_NP
, /* daemonstate */
49 PTHREAD_SCOPE_PROCESS
, /* scope */
51 SCHED_OTHER
, /* policy */
52 PTHREAD_INHERIT_SCHED
, /* inherit */
56 if (thrattr
.guardsize
== 0)
57 thrattr
.guardsize
= _sysconf(_SC_PAGESIZE
);
62 * pthread_attr_init: allocates the attribute object and initializes it
63 * with the default values.
65 #pragma weak _pthread_attr_init = pthread_attr_init
67 pthread_attr_init(pthread_attr_t
*attr
)
71 if ((ap
= lmalloc(sizeof (thrattr_t
))) != NULL
) {
73 attr
->__pthread_attrp
= ap
;
80 * pthread_attr_destroy: frees the attribute object and invalidates it
84 pthread_attr_destroy(pthread_attr_t
*attr
)
86 if (attr
== NULL
|| attr
->__pthread_attrp
== NULL
)
88 lfree(attr
->__pthread_attrp
, sizeof (thrattr_t
));
89 attr
->__pthread_attrp
= NULL
;
94 * pthread_attr_clone: make a copy of a pthread_attr_t.
97 pthread_attr_clone(pthread_attr_t
*attr
, const pthread_attr_t
*old_attr
)
100 const thrattr_t
*old_ap
=
101 old_attr
? old_attr
->__pthread_attrp
: def_thrattr();
105 if ((ap
= lmalloc(sizeof (thrattr_t
))) == NULL
)
108 attr
->__pthread_attrp
= ap
;
113 * pthread_attr_equal: compare two pthread_attr_t's, return 1 if equal.
114 * A NULL pthread_attr_t pointer implies default attributes.
115 * This is a consolidation-private interface, for librt.
118 pthread_attr_equal(const pthread_attr_t
*attr1
, const pthread_attr_t
*attr2
)
120 const thrattr_t
*ap1
= attr1
? attr1
->__pthread_attrp
: def_thrattr();
121 const thrattr_t
*ap2
= attr2
? attr2
->__pthread_attrp
: def_thrattr();
123 if (ap1
== NULL
|| ap2
== NULL
)
125 return (ap1
== ap2
|| memcmp(ap1
, ap2
, sizeof (thrattr_t
)) == 0);
129 * pthread_attr_setstacksize: sets the user stack size, minimum should
130 * be PTHREAD_STACK_MIN (MINSTACK).
131 * This is equivalent to stksize argument in thr_create().
134 pthread_attr_setstacksize(pthread_attr_t
*attr
, size_t stacksize
)
138 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
139 stacksize
>= MINSTACK
) {
140 ap
->stksize
= stacksize
;
147 * pthread_attr_getstacksize: gets the user stack size.
149 #pragma weak _pthread_attr_getstacksize = pthread_attr_getstacksize
151 pthread_attr_getstacksize(const pthread_attr_t
*attr
, size_t *stacksize
)
155 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
157 *stacksize
= ap
->stksize
;
164 * pthread_attr_setstackaddr: sets the user stack addr.
165 * This is equivalent to stkaddr argument in thr_create().
168 pthread_attr_setstackaddr(pthread_attr_t
*attr
, void *stackaddr
)
172 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
) {
173 ap
->stkaddr
= stackaddr
;
180 * pthread_attr_getstackaddr: gets the user stack addr.
182 #pragma weak _pthread_attr_getstackaddr = pthread_attr_getstackaddr
184 pthread_attr_getstackaddr(const pthread_attr_t
*attr
, void **stackaddr
)
188 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
190 *stackaddr
= ap
->stkaddr
;
197 * pthread_attr_setdetachstate: sets the detach state to DETACHED or JOINABLE.
198 * PTHREAD_CREATE_DETACHED is equivalent to thr_create(THR_DETACHED).
201 pthread_attr_setdetachstate(pthread_attr_t
*attr
, int detachstate
)
205 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
206 (detachstate
== PTHREAD_CREATE_DETACHED
||
207 detachstate
== PTHREAD_CREATE_JOINABLE
)) {
208 ap
->detachstate
= detachstate
;
215 * pthread_attr_getdetachstate: gets the detach state.
217 #pragma weak _pthread_attr_getdetachstate = pthread_attr_getdetachstate
219 pthread_attr_getdetachstate(const pthread_attr_t
*attr
, int *detachstate
)
223 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
224 detachstate
!= NULL
) {
225 *detachstate
= ap
->detachstate
;
232 * pthread_attr_setdaemonstate_np: sets the daemon state to DAEMON or NONDAEMON.
233 * PTHREAD_CREATE_DAEMON is equivalent to thr_create(THR_DAEMON).
234 * For now, this is a private interface in libc.
237 pthread_attr_setdaemonstate_np(pthread_attr_t
*attr
, int daemonstate
)
241 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
242 (daemonstate
== PTHREAD_CREATE_DAEMON_NP
||
243 daemonstate
== PTHREAD_CREATE_NONDAEMON_NP
)) {
244 ap
->daemonstate
= daemonstate
;
251 * pthread_attr_getdaemonstate_np: gets the daemon state.
252 * For now, this is a private interface in libc, but it is exposed in the
253 * mapfile for the purposes of testing only.
256 pthread_attr_getdaemonstate_np(const pthread_attr_t
*attr
, int *daemonstate
)
260 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
261 daemonstate
!= NULL
) {
262 *daemonstate
= ap
->daemonstate
;
269 * pthread_attr_setscope: sets the scope to SYSTEM or PROCESS.
270 * This is equivalent to setting THR_BOUND flag in thr_create().
273 pthread_attr_setscope(pthread_attr_t
*attr
, int scope
)
277 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
278 (scope
== PTHREAD_SCOPE_SYSTEM
||
279 scope
== PTHREAD_SCOPE_PROCESS
)) {
287 * pthread_attr_getscope: gets the scheduling scope.
289 #pragma weak _pthread_attr_getscope = pthread_attr_getscope
291 pthread_attr_getscope(const pthread_attr_t
*attr
, int *scope
)
295 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
304 * pthread_attr_setinheritsched: sets the scheduling parameters to be
305 * EXPLICIT or INHERITED from parent thread.
308 pthread_attr_setinheritsched(pthread_attr_t
*attr
, int inherit
)
312 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
313 (inherit
== PTHREAD_EXPLICIT_SCHED
||
314 inherit
== PTHREAD_INHERIT_SCHED
)) {
315 ap
->inherit
= inherit
;
322 * pthread_attr_getinheritsched: gets the scheduling inheritance.
324 #pragma weak _pthread_attr_getinheritsched = pthread_attr_getinheritsched
326 pthread_attr_getinheritsched(const pthread_attr_t
*attr
, int *inherit
)
330 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
332 *inherit
= ap
->inherit
;
339 * pthread_attr_setschedpolicy: sets the scheduling policy.
342 pthread_attr_setschedpolicy(pthread_attr_t
*attr
, int policy
)
346 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
347 policy
!= SCHED_SYS
&& get_info_by_policy(policy
) != NULL
) {
355 * pthread_attr_getpolicy: gets the scheduling policy.
357 #pragma weak _pthread_attr_getschedpolicy = pthread_attr_getschedpolicy
359 pthread_attr_getschedpolicy(const pthread_attr_t
*attr
, int *policy
)
363 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
365 *policy
= ap
->policy
;
372 * pthread_attr_setschedparam: sets the scheduling parameters.
373 * Currently, we support priority only.
376 pthread_attr_setschedparam(pthread_attr_t
*attr
,
377 const struct sched_param
*param
)
381 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
383 ap
->prio
= param
->sched_priority
;
390 * pthread_attr_getschedparam: gets the scheduling parameters.
391 * Currently, only priority is defined as sched parameter.
393 #pragma weak _pthread_attr_getschedparam = pthread_attr_getschedparam
395 pthread_attr_getschedparam(const pthread_attr_t
*attr
,
396 struct sched_param
*param
)
400 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
402 param
->sched_priority
= ap
->prio
;
410 * pthread_attr_setguardsize: sets the guardsize
413 pthread_attr_setguardsize(pthread_attr_t
*attr
, size_t guardsize
)
417 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
) {
418 ap
->guardsize
= guardsize
;
426 * pthread_attr_getguardsize: gets the guardsize
429 pthread_attr_getguardsize(const pthread_attr_t
*attr
, size_t *guardsize
)
433 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
435 *guardsize
= ap
->guardsize
;
442 * pthread_attr_setstack: sets the user stack addr and stack size.
443 * This is equivalent to the stack_base and stack_size arguments
447 pthread_attr_setstack(pthread_attr_t
*attr
,
448 void *stackaddr
, size_t stacksize
)
452 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
453 stacksize
>= MINSTACK
) {
454 ap
->stkaddr
= stackaddr
;
455 ap
->stksize
= stacksize
;
456 if (stackaddr
!= NULL
&&
457 setup_top_frame(stackaddr
, stacksize
, NULL
) == NULL
)
465 * pthread_attr_getstack: gets the user stack addr and stack size.
468 pthread_attr_getstack(const pthread_attr_t
*attr
,
469 void **stackaddr
, size_t *stacksize
)
473 if (attr
!= NULL
&& (ap
= attr
->__pthread_attrp
) != NULL
&&
474 stackaddr
!= NULL
&& stacksize
!= NULL
) {
475 *stackaddr
= ap
->stkaddr
;
476 *stacksize
= ap
->stksize
;
483 pthread_attr_setname_np(pthread_attr_t
*attr
, const char *name
)
487 if (attr
== NULL
|| (ap
= attr
->__pthread_attrp
) == NULL
)
491 bzero(ap
->name
, sizeof (ap
->name
));
495 if (strlen(name
) >= sizeof (ap
->name
))
499 * We really want the ASCII version of isprint() here...
501 for (size_t i
= 0; name
[i
] != '\0'; i
++) {
502 if (!ISPRINT(name
[i
]))
507 * not having garbage after the end of the string simplifies attr
510 bzero(ap
->name
, sizeof (ap
->name
));
511 (void) strlcpy(ap
->name
, name
, sizeof (ap
->name
));
516 pthread_attr_getname_np(pthread_attr_t
*attr
, char *buf
, size_t len
)
520 if (buf
== NULL
|| attr
== NULL
||
521 (ap
= attr
->__pthread_attrp
) == NULL
)
524 if (strlcpy(buf
, ap
->name
, len
) > len
)
530 * This function is a common BSD extension to pthread which is used to obtain
531 * the attributes of a thread that might have changed after its creation, for
532 * example, it's stack address.
534 * Note, there is no setattr analogue, nor do we desire to add one at this time.
535 * Similarly there is no native threads API analogue (nor should we add one for
538 * The astute reader may note that there is a GNU version of this called
539 * pthread_getattr_np(). The two functions are similar, but subtley different in
540 * a rather important way. While the pthread_attr_get_np() expects to be given
541 * a pthread_attr_t that has had pthread_attr_init() called on in,
542 * pthread_getattr_np() does not. However, on GNU systems, where the function
543 * originates, the pthread_attr_t is not opaque and thus it is entirely safe to
544 * both call pthread_attr_init() and then call pthread_getattr_np() on the same
545 * attributes object. On illumos, since the pthread_attr_t is opaque, that would
546 * be a memory leak. As such, we don't provide it.
549 pthread_attr_get_np(pthread_t tid
, pthread_attr_t
*attr
)
552 ulwp_t
*self
= curthread
;
553 uberdata_t
*udp
= self
->ul_uberdata
;
554 ulwp_t
*target
= NULL
;
558 * To ensure that information about the target thread does not change or
559 * disappear while we're trying to interrogate it, we grab the uwlp
562 if (self
->ul_lwpid
== tid
) {
563 ulwp_lock(self
, udp
);
566 target
= find_lwp(tid
);
576 if ((ap
= attr
->__pthread_attrp
) == NULL
) {
581 ap
->stksize
= target
->ul_stksiz
;
582 ap
->stkaddr
= target
->ul_stk
;
583 if (target
->ul_usropts
& THR_DETACHED
) {
584 ap
->detachstate
= PTHREAD_CREATE_DETACHED
;
586 ap
->detachstate
= PTHREAD_CREATE_JOINABLE
;
589 if (target
->ul_usropts
& THR_DAEMON
) {
590 ap
->daemonstate
= PTHREAD_CREATE_DAEMON_NP
;
592 ap
->daemonstate
= PTHREAD_CREATE_NONDAEMON_NP
;
595 if (target
->ul_usropts
& THR_BOUND
) {
596 ap
->scope
= PTHREAD_SCOPE_SYSTEM
;
598 ap
->scope
= PTHREAD_SCOPE_PROCESS
;
600 ap
->prio
= target
->ul_pri
;
601 ap
->policy
= target
->ul_policy
;
602 ap
->inherit
= target
->ul_ptinherit
;
603 ap
->guardsize
= target
->ul_guardsize
;
604 (void) pthread_getname_np(tid
, ap
->name
, sizeof (ap
->name
));
608 ulwp_unlock(target
, udp
);