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