Home | History | Annotate | Line # | Download | only in libpthread
pthread_attr.c revision 1.14
      1 /*	$NetBSD: pthread_attr.c,v 1.14 2010/08/06 14:23:06 christos Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2001, 2002, 2003, 2008 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Nathan J. Williams.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __RCSID("$NetBSD: pthread_attr.c,v 1.14 2010/08/06 14:23:06 christos Exp $");
     34 
     35 #include <errno.h>
     36 #include <stdio.h>
     37 #include <stdlib.h>
     38 #include <string.h>
     39 #include <unistd.h>
     40 
     41 #include "pthread.h"
     42 #include "pthread_int.h"
     43 
     44 #ifndef __lint__
     45 #define pthread_attr_get_np _pthread_attr_get_np
     46 #endif
     47 
     48 __weak_alias(pthread_attr_get_np, _pthread_attr_get_np)
     49 
     50 static struct pthread_attr_private *pthread__attr_init_private(
     51     pthread_attr_t *);
     52 
     53 static struct pthread_attr_private *
     54 pthread__attr_init_private(pthread_attr_t *attr)
     55 {
     56 	struct pthread_attr_private *p;
     57 
     58 	if ((p = attr->pta_private) != NULL)
     59 		return p;
     60 
     61 	p = malloc(sizeof(*p));
     62 	if (p != NULL) {
     63 		memset(p, 0, sizeof(*p));
     64 		attr->pta_private = p;
     65 		p->ptap_policy = SCHED_OTHER;
     66 	}
     67 	return p;
     68 }
     69 
     70 
     71 int
     72 pthread_attr_init(pthread_attr_t *attr)
     73 {
     74 
     75 	attr->pta_magic = PT_ATTR_MAGIC;
     76 	attr->pta_flags = 0;
     77 	attr->pta_private = NULL;
     78 
     79 	return 0;
     80 }
     81 
     82 
     83 int
     84 pthread_attr_destroy(pthread_attr_t *attr)
     85 {
     86 	struct pthread_attr_private *p;
     87 
     88 	if ((p = attr->pta_private) != NULL)
     89 		free(p);
     90 
     91 	return 0;
     92 }
     93 
     94 
     95 int
     96 pthread_attr_get_np(pthread_t thread, pthread_attr_t *attr)
     97 {
     98 	struct pthread_attr_private *p;
     99 
    100 	p = pthread__attr_init_private(attr);
    101 	if (p == NULL)
    102 		return ENOMEM;
    103 
    104 	attr->pta_flags = thread->pt_flags &
    105 	    (PT_FLAG_DETACHED | PT_FLAG_SCOPE_SYSTEM | PT_FLAG_EXPLICIT_SCHED);
    106 
    107 	p->ptap_namearg = thread->pt_name;
    108 	p->ptap_stackaddr = thread->pt_stack.ss_sp;
    109 	p->ptap_stacksize = thread->pt_stack.ss_size;
    110 	p->ptap_guardsize = (size_t)sysconf(_SC_PAGESIZE);
    111 	return pthread_getschedparam(thread, &p->ptap_policy, &p->ptap_sp);
    112 }
    113 
    114 
    115 int
    116 pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
    117 {
    118 
    119 	if (attr->pta_flags & PT_FLAG_DETACHED)
    120 		*detachstate = PTHREAD_CREATE_DETACHED;
    121 	else
    122 		*detachstate = PTHREAD_CREATE_JOINABLE;
    123 
    124 	return 0;
    125 }
    126 
    127 
    128 int
    129 pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
    130 {
    131 
    132 	switch (detachstate) {
    133 	case PTHREAD_CREATE_JOINABLE:
    134 		attr->pta_flags &= ~PT_FLAG_DETACHED;
    135 		break;
    136 	case PTHREAD_CREATE_DETACHED:
    137 		attr->pta_flags |= PT_FLAG_DETACHED;
    138 		break;
    139 	default:
    140 		return EINVAL;
    141 	}
    142 
    143 	return 0;
    144 }
    145 
    146 
    147 int
    148 pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guard)
    149 {
    150 	struct pthread_attr_private *p;
    151 
    152 	if ((p = attr->pta_private) == NULL)
    153 		*guard = (size_t)sysconf(_SC_PAGESIZE);
    154 	else
    155 		*guard = p->ptap_guardsize;
    156 
    157 	return 0;
    158 }
    159 
    160 
    161 int
    162 pthread_attr_setguardsize(pthread_attr_t *attr, size_t guard)
    163 {
    164 	struct pthread_attr_private *p;
    165 
    166 	p = pthread__attr_init_private(attr);
    167 	if (p == NULL)
    168 		return ENOMEM;
    169 
    170 	p->ptap_guardsize = guard;
    171 
    172 	return 0;
    173 }
    174 
    175 
    176 int
    177 pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
    178 {
    179 
    180 	if (attr->pta_flags & PT_FLAG_EXPLICIT_SCHED)
    181 		*inherit = PTHREAD_EXPLICIT_SCHED;
    182 	else
    183 		*inherit = PTHREAD_INHERIT_SCHED;
    184 
    185 	return 0;
    186 }
    187 
    188 
    189 int
    190 pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
    191 {
    192 
    193 	switch (inherit) {
    194 	case PTHREAD_INHERIT_SCHED:
    195 		attr->pta_flags &= ~PT_FLAG_EXPLICIT_SCHED;
    196 		break;
    197 	case PTHREAD_EXPLICIT_SCHED:
    198 		attr->pta_flags |= PT_FLAG_EXPLICIT_SCHED;
    199 		break;
    200 	default:
    201 		return EINVAL;
    202 	}
    203 
    204 	return 0;
    205 }
    206 
    207 
    208 int
    209 pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
    210 {
    211 
    212 	if (attr->pta_flags & PT_FLAG_SCOPE_SYSTEM)
    213 		*scope = PTHREAD_SCOPE_SYSTEM;
    214 	else
    215 		*scope = PTHREAD_SCOPE_PROCESS;
    216 
    217 	return 0;
    218 }
    219 
    220 
    221 int
    222 pthread_attr_setscope(pthread_attr_t *attr, int scope)
    223 {
    224 
    225 	switch (scope) {
    226 	case PTHREAD_SCOPE_PROCESS:
    227 		attr->pta_flags &= ~PT_FLAG_SCOPE_SYSTEM;
    228 		break;
    229 	case PTHREAD_SCOPE_SYSTEM:
    230 		attr->pta_flags |= PT_FLAG_SCOPE_SYSTEM;
    231 		break;
    232 	default:
    233 		return EINVAL;
    234 	}
    235 
    236 	return 0;
    237 }
    238 
    239 
    240 int
    241 pthread_attr_setschedparam(pthread_attr_t *attr,
    242 			   const struct sched_param *param)
    243 {
    244 	struct pthread_attr_private *p;
    245 	int error;
    246 
    247 	if (param == NULL)
    248 		return EINVAL;
    249 	p = pthread__attr_init_private(attr);
    250 	if (p == NULL)
    251 		return ENOMEM;
    252 	error = pthread__checkpri(param->sched_priority);
    253 	if (error == 0)
    254 		p->ptap_sp = *param;
    255 	return error;
    256 }
    257 
    258 
    259 int
    260 pthread_attr_getschedparam(const pthread_attr_t *attr,
    261 			   struct sched_param *param)
    262 {
    263 	struct pthread_attr_private *p;
    264 
    265 	if (param == NULL)
    266 		return EINVAL;
    267 	p = attr->pta_private;
    268 	if (p == NULL)
    269 		memset(param, 0, sizeof(*param));
    270 	else
    271 		*param = p->ptap_sp;
    272 	return 0;
    273 }
    274 
    275 
    276 int
    277 pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy)
    278 {
    279 	struct pthread_attr_private *p;
    280 
    281 
    282 	switch (policy) {
    283 	case SCHED_OTHER:
    284 	case SCHED_FIFO:
    285 	case SCHED_RR:
    286 		p = pthread__attr_init_private(attr);
    287 		if (p == NULL)
    288 			return ENOMEM;
    289 		p->ptap_policy = policy;
    290 		return 0;
    291 	default:
    292 		return ENOTSUP;
    293 	}
    294 }
    295 
    296 
    297 int
    298 pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy)
    299 {
    300 	struct pthread_attr_private *p;
    301 
    302 	p = attr->pta_private;
    303 	if (p == NULL) {
    304 		*policy = SCHED_OTHER;
    305 		return 0;
    306 	}
    307 	*policy = p->ptap_policy;
    308 	return 0;
    309 }
    310 
    311 
    312 int
    313 pthread_attr_getstack(const pthread_attr_t *attr, void **addr, size_t *size)
    314 {
    315 	struct pthread_attr_private *p;
    316 
    317 	if ((p = attr->pta_private) == NULL) {
    318 		*addr = NULL;
    319 		*size = pthread__stacksize;
    320 	} else {
    321 		*addr = p->ptap_stackaddr;
    322 		*size = p->ptap_stacksize;
    323 	}
    324 
    325 	return 0;
    326 }
    327 
    328 
    329 int
    330 pthread_attr_setstack(pthread_attr_t *attr, void *addr, size_t size)
    331 {
    332 	struct pthread_attr_private *p;
    333 
    334 	p = pthread__attr_init_private(attr);
    335 	if (p == NULL)
    336 		return ENOMEM;
    337 
    338 	p->ptap_stackaddr = addr;
    339 	p->ptap_stacksize = size;
    340 
    341 	return 0;
    342 }
    343 
    344 
    345 int
    346 pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *size)
    347 {
    348 	struct pthread_attr_private *p;
    349 
    350 	if ((p = attr->pta_private) == NULL)
    351 		*size = pthread__stacksize;
    352 	else
    353 		*size = p->ptap_stacksize;
    354 
    355 	return 0;
    356 }
    357 
    358 
    359 int
    360 pthread_attr_setstacksize(pthread_attr_t *attr, size_t size)
    361 {
    362 	struct pthread_attr_private *p;
    363 
    364 	if (size < (size_t)sysconf(_SC_THREAD_STACK_MIN))
    365 		return EINVAL;
    366 
    367 	p = pthread__attr_init_private(attr);
    368 	if (p == NULL)
    369 		return ENOMEM;
    370 
    371 	p->ptap_stacksize = size;
    372 
    373 	return 0;
    374 }
    375 
    376 
    377 int
    378 pthread_attr_getstackaddr(const pthread_attr_t *attr, void **addr)
    379 {
    380 	struct pthread_attr_private *p;
    381 
    382 	if ((p = attr->pta_private) == NULL)
    383 		*addr = NULL;
    384 	else
    385 		*addr = p->ptap_stackaddr;
    386 
    387 	return 0;
    388 }
    389 
    390 
    391 int
    392 pthread_attr_setstackaddr(pthread_attr_t *attr, void *addr)
    393 {
    394 	struct pthread_attr_private *p;
    395 
    396 	p = pthread__attr_init_private(attr);
    397 	if (p == NULL)
    398 		return ENOMEM;
    399 
    400 	p->ptap_stackaddr = addr;
    401 
    402 	return 0;
    403 }
    404 
    405 
    406 int
    407 pthread_attr_getname_np(const pthread_attr_t *attr, char *name, size_t len,
    408     void **argp)
    409 {
    410 	struct pthread_attr_private *p;
    411 
    412 	if ((p = attr->pta_private) == NULL) {
    413 		name[0] = '\0';
    414 		if (argp != NULL)
    415 			*argp = NULL;
    416 	} else {
    417 		strlcpy(name, p->ptap_name, len);
    418 		if (argp != NULL)
    419 			*argp = p->ptap_namearg;
    420 	}
    421 
    422 	return 0;
    423 }
    424 
    425 
    426 int
    427 pthread_attr_setname_np(pthread_attr_t *attr, const char *name, void *arg)
    428 {
    429 	struct pthread_attr_private *p;
    430 	int namelen;
    431 
    432 	p = pthread__attr_init_private(attr);
    433 	if (p == NULL)
    434 		return ENOMEM;
    435 
    436 	namelen = snprintf(p->ptap_name, PTHREAD_MAX_NAMELEN_NP, name, arg);
    437 	if (namelen >= PTHREAD_MAX_NAMELEN_NP) {
    438 		p->ptap_name[0] = '\0';
    439 		return EINVAL;
    440 	}
    441 	p->ptap_namearg = arg;
    442 
    443 	return 0;
    444 }
    445 
    446 int
    447 pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
    448 {
    449 	attr->pta_flags |= PT_FLAG_SUSPENDED;
    450 	return 0;
    451 }
    452 
    453 int
    454 pthread_getattr_np(pthread_t thread, pthread_attr_t *attr)
    455 {
    456 	int error;
    457 	if ((error = pthread_attr_init(attr)) != 0)
    458 		return error;
    459 	if ((error = pthread_attr_get_np(thread, attr)) != 0) {
    460 		(void)pthread_attr_destroy(attr);
    461 		return error;
    462 	}
    463 	return 0;
    464 }
    465