xref: /onnv-gate/usr/src/lib/libc/port/threads/pthr_mutex.c (revision 8036:1a2f63babdcc)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
54574Sraf  * Common Development and Distribution License (the "License").
64574Sraf  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
214574Sraf 
220Sstevel@tonic-gate /*
236247Sraf  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #include "lint.h"
280Sstevel@tonic-gate #include "thr_uberdata.h"
290Sstevel@tonic-gate #include <pthread.h>
300Sstevel@tonic-gate 
310Sstevel@tonic-gate /*
320Sstevel@tonic-gate  * pthread_mutexattr_init: allocates the mutex attribute object and
330Sstevel@tonic-gate  * initializes it with the default values.
340Sstevel@tonic-gate  */
356812Sraf #pragma weak _pthread_mutexattr_init = pthread_mutexattr_init
360Sstevel@tonic-gate int
pthread_mutexattr_init(pthread_mutexattr_t * attr)376812Sraf pthread_mutexattr_init(pthread_mutexattr_t *attr)
380Sstevel@tonic-gate {
390Sstevel@tonic-gate 	mattr_t	*ap;
400Sstevel@tonic-gate 
410Sstevel@tonic-gate 	if ((ap = lmalloc(sizeof (mattr_t))) == NULL)
420Sstevel@tonic-gate 		return (ENOMEM);
430Sstevel@tonic-gate 	ap->pshared = DEFAULT_TYPE;
440Sstevel@tonic-gate 	ap->type = PTHREAD_MUTEX_DEFAULT;
450Sstevel@tonic-gate 	ap->protocol = PTHREAD_PRIO_NONE;
46*8036SRoger.Faulkner@Sun.COM 	ap->robustness = PTHREAD_MUTEX_STALLED;
470Sstevel@tonic-gate 	attr->__pthread_mutexattrp = ap;
480Sstevel@tonic-gate 	return (0);
490Sstevel@tonic-gate }
500Sstevel@tonic-gate 
510Sstevel@tonic-gate /*
520Sstevel@tonic-gate  * pthread_mutexattr_destroy: frees the mutex attribute object and
530Sstevel@tonic-gate  * invalidates it with NULL value.
540Sstevel@tonic-gate  */
550Sstevel@tonic-gate int
pthread_mutexattr_destroy(pthread_mutexattr_t * attr)566812Sraf pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
570Sstevel@tonic-gate {
580Sstevel@tonic-gate 	if (attr == NULL || attr->__pthread_mutexattrp == NULL)
590Sstevel@tonic-gate 		return (EINVAL);
600Sstevel@tonic-gate 	lfree(attr->__pthread_mutexattrp, sizeof (mattr_t));
610Sstevel@tonic-gate 	attr->__pthread_mutexattrp = NULL;
620Sstevel@tonic-gate 	return (0);
630Sstevel@tonic-gate }
640Sstevel@tonic-gate 
650Sstevel@tonic-gate /*
664574Sraf  * pthread_mutexattr_setpshared: sets the shared attribute
674574Sraf  * to PTHREAD_PROCESS_PRIVATE or PTHREAD_PROCESS_SHARED.
684574Sraf  * This is equivalent to setting the USYNC_THREAD/USYNC_PROCESS
694574Sraf  * flag in mutex_init().
700Sstevel@tonic-gate  */
710Sstevel@tonic-gate int
pthread_mutexattr_setpshared(pthread_mutexattr_t * attr,int pshared)726812Sraf pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared)
730Sstevel@tonic-gate {
740Sstevel@tonic-gate 	mattr_t	*ap;
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
770Sstevel@tonic-gate 	    (pshared != PTHREAD_PROCESS_PRIVATE &&
780Sstevel@tonic-gate 	    pshared != PTHREAD_PROCESS_SHARED))
790Sstevel@tonic-gate 		return (EINVAL);
800Sstevel@tonic-gate 	ap->pshared = pshared;
810Sstevel@tonic-gate 	return (0);
820Sstevel@tonic-gate }
830Sstevel@tonic-gate 
840Sstevel@tonic-gate /*
854574Sraf  * pthread_mutexattr_getpshared: gets the shared attribute.
860Sstevel@tonic-gate  */
876812Sraf #pragma weak _pthread_mutexattr_getpshared = pthread_mutexattr_getpshared
880Sstevel@tonic-gate int
pthread_mutexattr_getpshared(const pthread_mutexattr_t * attr,int * pshared)896812Sraf pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared)
900Sstevel@tonic-gate {
910Sstevel@tonic-gate 	mattr_t	*ap;
920Sstevel@tonic-gate 
930Sstevel@tonic-gate 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
940Sstevel@tonic-gate 	    pshared == NULL)
950Sstevel@tonic-gate 		return (EINVAL);
960Sstevel@tonic-gate 	*pshared = ap->pshared;
970Sstevel@tonic-gate 	return (0);
980Sstevel@tonic-gate }
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate /*
1014574Sraf  * pthread_mutexattr_setprioceiling: sets the prioceiling attribute.
1020Sstevel@tonic-gate  */
1030Sstevel@tonic-gate int
pthread_mutexattr_setprioceiling(pthread_mutexattr_t * attr,int prioceiling)1046812Sraf pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling)
1050Sstevel@tonic-gate {
1066247Sraf 	const pcclass_t *pccp = get_info_by_policy(SCHED_FIFO);
1070Sstevel@tonic-gate 	mattr_t	*ap;
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
1106247Sraf 	    prioceiling < pccp->pcc_primin || prioceiling > pccp->pcc_primax)
1110Sstevel@tonic-gate 		return (EINVAL);
1120Sstevel@tonic-gate 	ap->prioceiling = prioceiling;
1130Sstevel@tonic-gate 	return (0);
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate /*
1174574Sraf  * pthread_mutexattr_getprioceiling: gets the prioceiling attribute.
1180Sstevel@tonic-gate  */
1196812Sraf #pragma weak _pthread_mutexattr_getprioceiling = \
1206812Sraf 			pthread_mutexattr_getprioceiling
1210Sstevel@tonic-gate int
pthread_mutexattr_getprioceiling(const pthread_mutexattr_t * attr,int * ceiling)1226812Sraf pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *ceiling)
1230Sstevel@tonic-gate {
1240Sstevel@tonic-gate 	mattr_t	*ap;
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
1270Sstevel@tonic-gate 	    ceiling == NULL)
1280Sstevel@tonic-gate 		return (EINVAL);
1290Sstevel@tonic-gate 	*ceiling = ap->prioceiling;
1300Sstevel@tonic-gate 	return (0);
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate /*
1340Sstevel@tonic-gate  * pthread_mutexattr_setprotocol: sets the protocol attribute.
1350Sstevel@tonic-gate  */
1360Sstevel@tonic-gate int
pthread_mutexattr_setprotocol(pthread_mutexattr_t * attr,int protocol)1376812Sraf pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol)
1380Sstevel@tonic-gate {
1390Sstevel@tonic-gate 	mattr_t	*ap;
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL)
1420Sstevel@tonic-gate 		return (EINVAL);
1430Sstevel@tonic-gate 	if (protocol != PTHREAD_PRIO_NONE &&
1440Sstevel@tonic-gate 	    protocol != PTHREAD_PRIO_INHERIT &&
1450Sstevel@tonic-gate 	    protocol != PTHREAD_PRIO_PROTECT)
1460Sstevel@tonic-gate 		return (ENOTSUP);
1470Sstevel@tonic-gate 	ap->protocol = protocol;
1480Sstevel@tonic-gate 	return (0);
1490Sstevel@tonic-gate }
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate /*
1520Sstevel@tonic-gate  * pthread_mutexattr_getprotocol: gets the protocol attribute.
1530Sstevel@tonic-gate  */
1546812Sraf #pragma weak _pthread_mutexattr_getprotocol = pthread_mutexattr_getprotocol
1550Sstevel@tonic-gate int
pthread_mutexattr_getprotocol(const pthread_mutexattr_t * attr,int * protocol)1566812Sraf pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol)
1570Sstevel@tonic-gate {
1580Sstevel@tonic-gate 	mattr_t	*ap;
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
1610Sstevel@tonic-gate 	    protocol == NULL)
1620Sstevel@tonic-gate 		return (EINVAL);
1630Sstevel@tonic-gate 	*protocol = ap->protocol;
1640Sstevel@tonic-gate 	return (0);
1650Sstevel@tonic-gate }
1660Sstevel@tonic-gate 
1670Sstevel@tonic-gate /*
168*8036SRoger.Faulkner@Sun.COM  * pthread_mutexattr_setrobust: set the mutex robust attribute.
169*8036SRoger.Faulkner@Sun.COM  * pthread_mutexattr_setrobust_np: the historical name.
1700Sstevel@tonic-gate  */
171*8036SRoger.Faulkner@Sun.COM #pragma weak pthread_mutexattr_setrobust_np = pthread_mutexattr_setrobust
1720Sstevel@tonic-gate int
pthread_mutexattr_setrobust(pthread_mutexattr_t * attr,int robust)173*8036SRoger.Faulkner@Sun.COM pthread_mutexattr_setrobust(pthread_mutexattr_t *attr, int robust)
1740Sstevel@tonic-gate {
1750Sstevel@tonic-gate 	mattr_t	*ap;
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
178*8036SRoger.Faulkner@Sun.COM 	    (robust != PTHREAD_MUTEX_ROBUST && robust != PTHREAD_MUTEX_STALLED))
1790Sstevel@tonic-gate 		return (EINVAL);
1800Sstevel@tonic-gate 	ap->robustness = robust;
1810Sstevel@tonic-gate 	return (0);
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate /*
185*8036SRoger.Faulkner@Sun.COM  * pthread_mutexattr_getrobust: get the mutex robust attribute.
186*8036SRoger.Faulkner@Sun.COM  * pthread_mutexattr_getrobust_np: the historical name.
1870Sstevel@tonic-gate  */
188*8036SRoger.Faulkner@Sun.COM #pragma weak pthread_mutexattr_getrobust_np = pthread_mutexattr_getrobust
1890Sstevel@tonic-gate int
pthread_mutexattr_getrobust(const pthread_mutexattr_t * attr,int * robust)190*8036SRoger.Faulkner@Sun.COM pthread_mutexattr_getrobust(const pthread_mutexattr_t *attr, int *robust)
1910Sstevel@tonic-gate {
1920Sstevel@tonic-gate 	mattr_t	*ap;
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
1950Sstevel@tonic-gate 	    robust == NULL)
1960Sstevel@tonic-gate 		return (EINVAL);
1970Sstevel@tonic-gate 	*robust = ap->robustness;
1980Sstevel@tonic-gate 	return (0);
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate /*
2024574Sraf  * pthread_mutex_init: Initializes the mutex object.  It copies the
2034574Sraf  * various attributes into one type argument and calls mutex_init().
2040Sstevel@tonic-gate  */
2056812Sraf #pragma weak _pthread_mutex_init = pthread_mutex_init
2060Sstevel@tonic-gate int
pthread_mutex_init(pthread_mutex_t * _RESTRICT_KYWD mutex,const pthread_mutexattr_t * _RESTRICT_KYWD attr)2076812Sraf pthread_mutex_init(pthread_mutex_t *_RESTRICT_KYWD mutex,
2086812Sraf     const pthread_mutexattr_t *_RESTRICT_KYWD attr)
2090Sstevel@tonic-gate {
2104574Sraf 	mattr_t *ap;
2110Sstevel@tonic-gate 	int	type;
2120Sstevel@tonic-gate 	int	prioceiling = 0;
2130Sstevel@tonic-gate 
2144574Sraf 	/*
2154574Sraf 	 * All of the pshared, type, protocol, robust attributes
2164574Sraf 	 * translate to bits in the mutex_type field.
2174574Sraf 	 */
2180Sstevel@tonic-gate 	if (attr != NULL) {
2190Sstevel@tonic-gate 		if ((ap = attr->__pthread_mutexattrp) == NULL)
2200Sstevel@tonic-gate 			return (EINVAL);
2214574Sraf 		type = ap->pshared | ap->type | ap->protocol | ap->robustness;
2224574Sraf 		if (ap->protocol == PTHREAD_PRIO_PROTECT)
2230Sstevel@tonic-gate 			prioceiling = ap->prioceiling;
2240Sstevel@tonic-gate 	} else {
2254574Sraf 		type = DEFAULT_TYPE | PTHREAD_MUTEX_DEFAULT |
226*8036SRoger.Faulkner@Sun.COM 		    PTHREAD_PRIO_NONE | PTHREAD_MUTEX_STALLED;
2270Sstevel@tonic-gate 	}
2280Sstevel@tonic-gate 
2296515Sraf 	return (mutex_init((mutex_t *)mutex, type, &prioceiling));
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate /*
2330Sstevel@tonic-gate  * pthread_mutex_setprioceiling: sets the prioceiling.
2346247Sraf  * From the SUSv3 (POSIX) specification for pthread_mutex_setprioceiling():
2356247Sraf  *	The process of locking the mutex need not
2366247Sraf  *	adhere to the priority protect protocol.
2376247Sraf  * We pass the MUTEX_NOCEIL flag to mutex_lock_internal() so that
2386247Sraf  * a non-realtime thread can successfully execute this operation.
2390Sstevel@tonic-gate  */
2400Sstevel@tonic-gate int
pthread_mutex_setprioceiling(pthread_mutex_t * mutex,int ceil,int * oceil)2416812Sraf pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int ceil, int *oceil)
2420Sstevel@tonic-gate {
2430Sstevel@tonic-gate 	mutex_t *mp = (mutex_t *)mutex;
2446247Sraf 	const pcclass_t *pccp = get_info_by_policy(SCHED_FIFO);
2450Sstevel@tonic-gate 	int error;
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	if (!(mp->mutex_type & PTHREAD_PRIO_PROTECT) ||
2486247Sraf 	    ceil < pccp->pcc_primin || ceil > pccp->pcc_primax)
2490Sstevel@tonic-gate 		return (EINVAL);
2506247Sraf 	error = mutex_lock_internal(mp, NULL, MUTEX_LOCK | MUTEX_NOCEIL);
251*8036SRoger.Faulkner@Sun.COM 	if (error == 0 || error == EOWNERDEAD || error == ELOCKUNMAPPED) {
2520Sstevel@tonic-gate 		if (oceil)
2530Sstevel@tonic-gate 			*oceil = mp->mutex_ceiling;
2546247Sraf 		mp->mutex_ceiling = ceil;
255*8036SRoger.Faulkner@Sun.COM 		error = mutex_unlock_internal(mp, 1);
2560Sstevel@tonic-gate 	}
2570Sstevel@tonic-gate 	return (error);
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate /*
2610Sstevel@tonic-gate  * pthread_mutex_getprioceiling: gets the prioceiling.
2620Sstevel@tonic-gate  */
2636812Sraf #pragma weak _pthread_mutex_getprioceiling = pthread_mutex_getprioceiling
2640Sstevel@tonic-gate int
pthread_mutex_getprioceiling(const pthread_mutex_t * mp,int * ceiling)2656812Sraf pthread_mutex_getprioceiling(const pthread_mutex_t *mp, int *ceiling)
2660Sstevel@tonic-gate {
2670Sstevel@tonic-gate 	*ceiling = ((mutex_t *)mp)->mutex_ceiling;
2680Sstevel@tonic-gate 	return (0);
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate /*
2720Sstevel@tonic-gate  * UNIX98
2730Sstevel@tonic-gate  * pthread_mutexattr_settype: sets the type attribute
2740Sstevel@tonic-gate  */
2750Sstevel@tonic-gate int
pthread_mutexattr_settype(pthread_mutexattr_t * attr,int type)2766812Sraf pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
2770Sstevel@tonic-gate {
2780Sstevel@tonic-gate 	mattr_t	*ap;
2790Sstevel@tonic-gate 
2800Sstevel@tonic-gate 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL)
2810Sstevel@tonic-gate 		return (EINVAL);
2820Sstevel@tonic-gate 	switch (type) {
2830Sstevel@tonic-gate 	case PTHREAD_MUTEX_NORMAL:
2840Sstevel@tonic-gate 		type = LOCK_NORMAL;
2850Sstevel@tonic-gate 		break;
2860Sstevel@tonic-gate 	case PTHREAD_MUTEX_ERRORCHECK:
2870Sstevel@tonic-gate 		type = LOCK_ERRORCHECK;
2880Sstevel@tonic-gate 		break;
2890Sstevel@tonic-gate 	case PTHREAD_MUTEX_RECURSIVE:
2904574Sraf 		type = LOCK_RECURSIVE | LOCK_ERRORCHECK;
2910Sstevel@tonic-gate 		break;
2920Sstevel@tonic-gate 	default:
2930Sstevel@tonic-gate 		return (EINVAL);
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 	ap->type = type;
2960Sstevel@tonic-gate 	return (0);
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate /*
3000Sstevel@tonic-gate  * UNIX98
3014574Sraf  * pthread_mutexattr_gettype: gets the type attribute.
3020Sstevel@tonic-gate  */
3030Sstevel@tonic-gate int
pthread_mutexattr_gettype(const pthread_mutexattr_t * attr,int * typep)3046812Sraf pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *typep)
3050Sstevel@tonic-gate {
3060Sstevel@tonic-gate 	mattr_t	*ap;
3070Sstevel@tonic-gate 	int type;
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
3100Sstevel@tonic-gate 	    typep == NULL)
3110Sstevel@tonic-gate 		return (EINVAL);
3120Sstevel@tonic-gate 	switch (ap->type) {
3130Sstevel@tonic-gate 	case LOCK_NORMAL:
3140Sstevel@tonic-gate 		type = PTHREAD_MUTEX_NORMAL;
3150Sstevel@tonic-gate 		break;
3160Sstevel@tonic-gate 	case LOCK_ERRORCHECK:
3170Sstevel@tonic-gate 		type = PTHREAD_MUTEX_ERRORCHECK;
3180Sstevel@tonic-gate 		break;
3194574Sraf 	case LOCK_RECURSIVE | LOCK_ERRORCHECK:
3200Sstevel@tonic-gate 		type = PTHREAD_MUTEX_RECURSIVE;
3210Sstevel@tonic-gate 		break;
3220Sstevel@tonic-gate 	default:
3230Sstevel@tonic-gate 		return (EINVAL);
3240Sstevel@tonic-gate 	}
3250Sstevel@tonic-gate 	*typep = type;
3260Sstevel@tonic-gate 	return (0);
3270Sstevel@tonic-gate }
328