Home | History | Annotate | Line # | Download | only in libpthread
pthread_attr.c revision 1.7
      1 /*	$NetBSD: pthread_attr.c,v 1.7 2008/01/08 20:56:08 christos Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2001,2002,2003 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  * 3. All advertising materials mentioning features or use of this software
     19  *    must display the following acknowledgement:
     20  *        This product includes software developed by the NetBSD
     21  *        Foundation, Inc. and its contributors.
     22  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  *    contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  * POSSIBILITY OF SUCH DAMAGE.
     37  */
     38 
     39 #include <sys/cdefs.h>
     40 __RCSID("$NetBSD: pthread_attr.c,v 1.7 2008/01/08 20:56:08 christos Exp $");
     41 
     42 #include <errno.h>
     43 #include <stdio.h>
     44 #include <stdlib.h>
     45 #include <string.h>
     46 #include <unistd.h>
     47 
     48 #include "pthread.h"
     49 #include "pthread_int.h"
     50 
     51 static struct pthread_attr_private *pthread__attr_init_private(
     52     pthread_attr_t *);
     53 
     54 static struct pthread_attr_private *
     55 pthread__attr_init_private(pthread_attr_t *attr)
     56 {
     57 	struct pthread_attr_private *p;
     58 
     59 	if ((p = attr->pta_private) != NULL)
     60 		return p;
     61 
     62 	p = malloc(sizeof(*p));
     63 	if (p != NULL) {
     64 		memset(p, 0, sizeof(*p));
     65 		attr->pta_private = p;
     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 
    112 	return 0;
    113 }
    114 
    115 
    116 int
    117 pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate)
    118 {
    119 
    120 	if (attr->pta_flags & PT_FLAG_DETACHED)
    121 		*detachstate = PTHREAD_CREATE_DETACHED;
    122 	else
    123 		*detachstate = PTHREAD_CREATE_JOINABLE;
    124 
    125 	return 0;
    126 }
    127 
    128 
    129 int
    130 pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
    131 {
    132 
    133 	switch (detachstate) {
    134 	case PTHREAD_CREATE_JOINABLE:
    135 		attr->pta_flags &= ~PT_FLAG_DETACHED;
    136 		break;
    137 	case PTHREAD_CREATE_DETACHED:
    138 		attr->pta_flags |= PT_FLAG_DETACHED;
    139 		break;
    140 	default:
    141 		return EINVAL;
    142 	}
    143 
    144 	return 0;
    145 }
    146 
    147 
    148 int
    149 pthread_attr_getguardsize(const pthread_attr_t *attr, size_t *guard)
    150 {
    151 	struct pthread_attr_private *p;
    152 
    153 	if ((p = attr->pta_private) == NULL)
    154 		*guard = (size_t)sysconf(_SC_PAGESIZE);
    155 	else
    156 		*guard = p->ptap_guardsize;
    157 
    158 	return 0;
    159 }
    160 
    161 
    162 int
    163 pthread_attr_setguardsize(pthread_attr_t *attr, size_t guard)
    164 {
    165 	struct pthread_attr_private *p;
    166 
    167 	p = pthread__attr_init_private(attr);
    168 	if (p == NULL)
    169 		return ENOMEM;
    170 
    171 	p->ptap_guardsize = guard;
    172 
    173 	return 0;
    174 }
    175 
    176 
    177 int
    178 pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit)
    179 {
    180 
    181 	if (attr->pta_flags & PT_FLAG_EXPLICIT_SCHED)
    182 		*inherit = PTHREAD_EXPLICIT_SCHED;
    183 	else
    184 		*inherit = PTHREAD_INHERIT_SCHED;
    185 
    186 	return 0;
    187 }
    188 
    189 
    190 int
    191 pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit)
    192 {
    193 
    194 	switch (inherit) {
    195 	case PTHREAD_INHERIT_SCHED:
    196 		attr->pta_flags &= ~PT_FLAG_EXPLICIT_SCHED;
    197 		break;
    198 	case PTHREAD_EXPLICIT_SCHED:
    199 		attr->pta_flags |= PT_FLAG_EXPLICIT_SCHED;
    200 		break;
    201 	default:
    202 		return EINVAL;
    203 	}
    204 
    205 	return 0;
    206 }
    207 
    208 
    209 int
    210 pthread_attr_getscope(const pthread_attr_t *attr, int *scope)
    211 {
    212 
    213 	if (attr->pta_flags & PT_FLAG_SCOPE_SYSTEM)
    214 		*scope = PTHREAD_SCOPE_SYSTEM;
    215 	else
    216 		*scope = PTHREAD_SCOPE_PROCESS;
    217 
    218 	return 0;
    219 }
    220 
    221 
    222 int
    223 pthread_attr_setscope(pthread_attr_t *attr, int scope)
    224 {
    225 
    226 	switch (scope) {
    227 	case PTHREAD_SCOPE_PROCESS:
    228 		attr->pta_flags &= ~PT_FLAG_SCOPE_SYSTEM;
    229 		break;
    230 	case PTHREAD_SCOPE_SYSTEM:
    231 		attr->pta_flags |= PT_FLAG_SCOPE_SYSTEM;
    232 		break;
    233 	default:
    234 		return EINVAL;
    235 	}
    236 
    237 	return 0;
    238 }
    239 
    240 
    241 int
    242 /*ARGSUSED*/
    243 pthread_attr_setschedparam(pthread_attr_t *attr,
    244     const struct sched_param *param)
    245 {
    246 
    247 	if (param == NULL)
    248 		return EINVAL;
    249 
    250 	if (param->sched_priority != 0)
    251 		return EINVAL;
    252 
    253 	return 0;
    254 }
    255 
    256 
    257 int
    258 /*ARGSUSED*/
    259 pthread_attr_getschedparam(const pthread_attr_t *attr,
    260     struct sched_param *param)
    261 {
    262 
    263 	if (param == NULL)
    264 		return EINVAL;
    265 
    266 	param->sched_priority = 0;
    267 
    268 	return 0;
    269 }
    270 
    271 
    272 int
    273 /*ARGSUSED*/
    274 pthread_attr_setschedpolicy(pthread_attr_t *attr,
    275     int policy)
    276 {
    277 
    278 	if (policy != SCHED_OTHER)
    279 		return ENOTSUP;
    280 
    281 	return 0;
    282 }
    283 
    284 
    285 int
    286 /*ARGSUSED*/
    287 pthread_attr_getschedpolicy(const pthread_attr_t *attr,
    288     int *policy)
    289 {
    290 
    291 	*policy = SCHED_OTHER;
    292 
    293 	return 0;
    294 }
    295 
    296 
    297 int
    298 pthread_attr_getstack(const pthread_attr_t *attr, void **addr, size_t *size)
    299 {
    300 	struct pthread_attr_private *p;
    301 
    302 	if ((p = attr->pta_private) == NULL) {
    303 		*addr = NULL;
    304 		*size = pthread__stacksize;
    305 	} else {
    306 		*addr = p->ptap_stackaddr;
    307 		*size = p->ptap_stacksize;
    308 	}
    309 
    310 	return 0;
    311 }
    312 
    313 
    314 int
    315 pthread_attr_setstack(pthread_attr_t *attr, void *addr, size_t size)
    316 {
    317 	struct pthread_attr_private *p;
    318 
    319 	p = pthread__attr_init_private(attr);
    320 	if (p == NULL)
    321 		return ENOMEM;
    322 
    323 	p->ptap_stackaddr = addr;
    324 	p->ptap_stacksize = size;
    325 
    326 	return 0;
    327 }
    328 
    329 
    330 int
    331 pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *size)
    332 {
    333 	struct pthread_attr_private *p;
    334 
    335 	if ((p = attr->pta_private) == NULL)
    336 		*size = pthread__stacksize;
    337 	else
    338 		*size = p->ptap_stacksize;
    339 
    340 	return 0;
    341 }
    342 
    343 
    344 int
    345 pthread_attr_setstacksize(pthread_attr_t *attr, size_t size)
    346 {
    347 	struct pthread_attr_private *p;
    348 
    349 	p = pthread__attr_init_private(attr);
    350 	if (p == NULL)
    351 		return ENOMEM;
    352 
    353 	p->ptap_stacksize = size;
    354 
    355 	return 0;
    356 }
    357 
    358 
    359 int
    360 pthread_attr_getstackaddr(const pthread_attr_t *attr, void **addr)
    361 {
    362 	struct pthread_attr_private *p;
    363 
    364 	if ((p = attr->pta_private) == NULL)
    365 		*addr = NULL;
    366 	else
    367 		*addr = p->ptap_stackaddr;
    368 
    369 	return 0;
    370 }
    371 
    372 
    373 int
    374 pthread_attr_setstackaddr(pthread_attr_t *attr, void *addr)
    375 {
    376 	struct pthread_attr_private *p;
    377 
    378 	p = pthread__attr_init_private(attr);
    379 	if (p == NULL)
    380 		return ENOMEM;
    381 
    382 	p->ptap_stackaddr = addr;
    383 
    384 	return 0;
    385 }
    386 
    387 
    388 int
    389 pthread_attr_getname_np(const pthread_attr_t *attr, char *name, size_t len,
    390     void **argp)
    391 {
    392 	struct pthread_attr_private *p;
    393 
    394 	if ((p = attr->pta_private) == NULL) {
    395 		name[0] = '\0';
    396 		if (argp != NULL)
    397 			*argp = NULL;
    398 	} else {
    399 		strlcpy(name, p->ptap_name, len);
    400 		if (argp != NULL)
    401 			*argp = p->ptap_namearg;
    402 	}
    403 
    404 	return 0;
    405 }
    406 
    407 
    408 int
    409 pthread_attr_setname_np(pthread_attr_t *attr, const char *name, void *arg)
    410 {
    411 	struct pthread_attr_private *p;
    412 	int namelen;
    413 
    414 	p = pthread__attr_init_private(attr);
    415 	if (p == NULL)
    416 		return ENOMEM;
    417 
    418 	namelen = snprintf(p->ptap_name, PTHREAD_MAX_NAMELEN_NP, name, arg);
    419 	if (namelen >= PTHREAD_MAX_NAMELEN_NP) {
    420 		p->ptap_name[0] = '\0';
    421 		return EINVAL;
    422 	}
    423 	p->ptap_namearg = arg;
    424 
    425 	return 0;
    426 }
    427 
    428 int
    429 pthread_attr_setcreatesuspend_np(pthread_attr_t *attr)
    430 {
    431 	attr->pta_flags |= PT_FLAG_SUSPENDED;
    432 	return 0;
    433 }
    434