Home | History | Annotate | Download | only in threads
      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 #include "lint.h"
     28 #include "thr_uberdata.h"
     29 #include <pthread.h>
     30 
     31 /*
     32  * pthread_mutexattr_init: allocates the mutex attribute object and
     33  * initializes it with the default values.
     34  */
     35 #pragma weak _pthread_mutexattr_init = pthread_mutexattr_init
     36 int
     37 pthread_mutexattr_init(pthread_mutexattr_t *attr)
     38 {
     39 	mattr_t	*ap;
     40 
     41 	if ((ap = lmalloc(sizeof (mattr_t))) == NULL)
     42 		return (ENOMEM);
     43 	ap->pshared = DEFAULT_TYPE;
     44 	ap->type = PTHREAD_MUTEX_DEFAULT;
     45 	ap->protocol = PTHREAD_PRIO_NONE;
     46 	ap->robustness = PTHREAD_MUTEX_STALLED;
     47 	attr->__pthread_mutexattrp = ap;
     48 	return (0);
     49 }
     50 
     51 /*
     52  * pthread_mutexattr_destroy: frees the mutex attribute object and
     53  * invalidates it with NULL value.
     54  */
     55 int
     56 pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
     57 {
     58 	if (attr == NULL || attr->__pthread_mutexattrp == NULL)
     59 		return (EINVAL);
     60 	lfree(attr->__pthread_mutexattrp, sizeof (mattr_t));
     61 	attr->__pthread_mutexattrp = NULL;
     62 	return (0);
     63 }
     64 
     65 /*
     66  * pthread_mutexattr_setpshared: sets the shared attribute
     67  * to PTHREAD_PROCESS_PRIVATE or PTHREAD_PROCESS_SHARED.
     68  * This is equivalent to setting the USYNC_THREAD/USYNC_PROCESS
     69  * flag in mutex_init().
     70  */
     71 int
     72 pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared)
     73 {
     74 	mattr_t	*ap;
     75 
     76 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
     77 	    (pshared != PTHREAD_PROCESS_PRIVATE &&
     78 	    pshared != PTHREAD_PROCESS_SHARED))
     79 		return (EINVAL);
     80 	ap->pshared = pshared;
     81 	return (0);
     82 }
     83 
     84 /*
     85  * pthread_mutexattr_getpshared: gets the shared attribute.
     86  */
     87 #pragma weak _pthread_mutexattr_getpshared = pthread_mutexattr_getpshared
     88 int
     89 pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared)
     90 {
     91 	mattr_t	*ap;
     92 
     93 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
     94 	    pshared == NULL)
     95 		return (EINVAL);
     96 	*pshared = ap->pshared;
     97 	return (0);
     98 }
     99 
    100 /*
    101  * pthread_mutexattr_setprioceiling: sets the prioceiling attribute.
    102  */
    103 int
    104 pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling)
    105 {
    106 	const pcclass_t *pccp = get_info_by_policy(SCHED_FIFO);
    107 	mattr_t	*ap;
    108 
    109 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
    110 	    prioceiling < pccp->pcc_primin || prioceiling > pccp->pcc_primax)
    111 		return (EINVAL);
    112 	ap->prioceiling = prioceiling;
    113 	return (0);
    114 }
    115 
    116 /*
    117  * pthread_mutexattr_getprioceiling: gets the prioceiling attribute.
    118  */
    119 #pragma weak _pthread_mutexattr_getprioceiling = \
    120 			pthread_mutexattr_getprioceiling
    121 int
    122 pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *ceiling)
    123 {
    124 	mattr_t	*ap;
    125 
    126 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
    127 	    ceiling == NULL)
    128 		return (EINVAL);
    129 	*ceiling = ap->prioceiling;
    130 	return (0);
    131 }
    132 
    133 /*
    134  * pthread_mutexattr_setprotocol: sets the protocol attribute.
    135  */
    136 int
    137 pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol)
    138 {
    139 	mattr_t	*ap;
    140 
    141 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL)
    142 		return (EINVAL);
    143 	if (protocol != PTHREAD_PRIO_NONE &&
    144 	    protocol != PTHREAD_PRIO_INHERIT &&
    145 	    protocol != PTHREAD_PRIO_PROTECT)
    146 		return (ENOTSUP);
    147 	ap->protocol = protocol;
    148 	return (0);
    149 }
    150 
    151 /*
    152  * pthread_mutexattr_getprotocol: gets the protocol attribute.
    153  */
    154 #pragma weak _pthread_mutexattr_getprotocol = pthread_mutexattr_getprotocol
    155 int
    156 pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol)
    157 {
    158 	mattr_t	*ap;
    159 
    160 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
    161 	    protocol == NULL)
    162 		return (EINVAL);
    163 	*protocol = ap->protocol;
    164 	return (0);
    165 }
    166 
    167 /*
    168  * pthread_mutexattr_setrobust: set the mutex robust attribute.
    169  * pthread_mutexattr_setrobust_np: the historical name.
    170  */
    171 #pragma weak pthread_mutexattr_setrobust_np = pthread_mutexattr_setrobust
    172 int
    173 pthread_mutexattr_setrobust(pthread_mutexattr_t *attr, int robust)
    174 {
    175 	mattr_t	*ap;
    176 
    177 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
    178 	    (robust != PTHREAD_MUTEX_ROBUST && robust != PTHREAD_MUTEX_STALLED))
    179 		return (EINVAL);
    180 	ap->robustness = robust;
    181 	return (0);
    182 }
    183 
    184 /*
    185  * pthread_mutexattr_getrobust: get the mutex robust attribute.
    186  * pthread_mutexattr_getrobust_np: the historical name.
    187  */
    188 #pragma weak pthread_mutexattr_getrobust_np = pthread_mutexattr_getrobust
    189 int
    190 pthread_mutexattr_getrobust(const pthread_mutexattr_t *attr, int *robust)
    191 {
    192 	mattr_t	*ap;
    193 
    194 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
    195 	    robust == NULL)
    196 		return (EINVAL);
    197 	*robust = ap->robustness;
    198 	return (0);
    199 }
    200 
    201 /*
    202  * pthread_mutex_init: Initializes the mutex object.  It copies the
    203  * various attributes into one type argument and calls mutex_init().
    204  */
    205 #pragma weak _pthread_mutex_init = pthread_mutex_init
    206 int
    207 pthread_mutex_init(pthread_mutex_t *_RESTRICT_KYWD mutex,
    208     const pthread_mutexattr_t *_RESTRICT_KYWD attr)
    209 {
    210 	mattr_t *ap;
    211 	int	type;
    212 	int	prioceiling = 0;
    213 
    214 	/*
    215 	 * All of the pshared, type, protocol, robust attributes
    216 	 * translate to bits in the mutex_type field.
    217 	 */
    218 	if (attr != NULL) {
    219 		if ((ap = attr->__pthread_mutexattrp) == NULL)
    220 			return (EINVAL);
    221 		type = ap->pshared | ap->type | ap->protocol | ap->robustness;
    222 		if (ap->protocol == PTHREAD_PRIO_PROTECT)
    223 			prioceiling = ap->prioceiling;
    224 	} else {
    225 		type = DEFAULT_TYPE | PTHREAD_MUTEX_DEFAULT |
    226 		    PTHREAD_PRIO_NONE | PTHREAD_MUTEX_STALLED;
    227 	}
    228 
    229 	return (mutex_init((mutex_t *)mutex, type, &prioceiling));
    230 }
    231 
    232 /*
    233  * pthread_mutex_setprioceiling: sets the prioceiling.
    234  * From the SUSv3 (POSIX) specification for pthread_mutex_setprioceiling():
    235  *	The process of locking the mutex need not
    236  *	adhere to the priority protect protocol.
    237  * We pass the MUTEX_NOCEIL flag to mutex_lock_internal() so that
    238  * a non-realtime thread can successfully execute this operation.
    239  */
    240 int
    241 pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int ceil, int *oceil)
    242 {
    243 	mutex_t *mp = (mutex_t *)mutex;
    244 	const pcclass_t *pccp = get_info_by_policy(SCHED_FIFO);
    245 	int error;
    246 
    247 	if (!(mp->mutex_type & PTHREAD_PRIO_PROTECT) ||
    248 	    ceil < pccp->pcc_primin || ceil > pccp->pcc_primax)
    249 		return (EINVAL);
    250 	error = mutex_lock_internal(mp, NULL, MUTEX_LOCK | MUTEX_NOCEIL);
    251 	if (error == 0 || error == EOWNERDEAD || error == ELOCKUNMAPPED) {
    252 		if (oceil)
    253 			*oceil = mp->mutex_ceiling;
    254 		mp->mutex_ceiling = ceil;
    255 		error = mutex_unlock_internal(mp, 1);
    256 	}
    257 	return (error);
    258 }
    259 
    260 /*
    261  * pthread_mutex_getprioceiling: gets the prioceiling.
    262  */
    263 #pragma weak _pthread_mutex_getprioceiling = pthread_mutex_getprioceiling
    264 int
    265 pthread_mutex_getprioceiling(const pthread_mutex_t *mp, int *ceiling)
    266 {
    267 	*ceiling = ((mutex_t *)mp)->mutex_ceiling;
    268 	return (0);
    269 }
    270 
    271 /*
    272  * UNIX98
    273  * pthread_mutexattr_settype: sets the type attribute
    274  */
    275 int
    276 pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
    277 {
    278 	mattr_t	*ap;
    279 
    280 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL)
    281 		return (EINVAL);
    282 	switch (type) {
    283 	case PTHREAD_MUTEX_NORMAL:
    284 		type = LOCK_NORMAL;
    285 		break;
    286 	case PTHREAD_MUTEX_ERRORCHECK:
    287 		type = LOCK_ERRORCHECK;
    288 		break;
    289 	case PTHREAD_MUTEX_RECURSIVE:
    290 		type = LOCK_RECURSIVE | LOCK_ERRORCHECK;
    291 		break;
    292 	default:
    293 		return (EINVAL);
    294 	}
    295 	ap->type = type;
    296 	return (0);
    297 }
    298 
    299 /*
    300  * UNIX98
    301  * pthread_mutexattr_gettype: gets the type attribute.
    302  */
    303 int
    304 pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *typep)
    305 {
    306 	mattr_t	*ap;
    307 	int type;
    308 
    309 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
    310 	    typep == NULL)
    311 		return (EINVAL);
    312 	switch (ap->type) {
    313 	case LOCK_NORMAL:
    314 		type = PTHREAD_MUTEX_NORMAL;
    315 		break;
    316 	case LOCK_ERRORCHECK:
    317 		type = PTHREAD_MUTEX_ERRORCHECK;
    318 		break;
    319 	case LOCK_RECURSIVE | LOCK_ERRORCHECK:
    320 		type = PTHREAD_MUTEX_RECURSIVE;
    321 		break;
    322 	default:
    323 		return (EINVAL);
    324 	}
    325 	*typep = type;
    326 	return (0);
    327 }
    328