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
pthread_mutexattr_init(pthread_mutexattr_t * attr)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
pthread_mutexattr_destroy(pthread_mutexattr_t * attr)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
pthread_mutexattr_setpshared(pthread_mutexattr_t * attr,int pshared)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
pthread_mutexattr_getpshared(const pthread_mutexattr_t * attr,int * pshared)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
pthread_mutexattr_setprioceiling(pthread_mutexattr_t * attr,int prioceiling)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
pthread_mutexattr_getprioceiling(const pthread_mutexattr_t * attr,int * ceiling)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
pthread_mutexattr_setprotocol(pthread_mutexattr_t * attr,int protocol)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
pthread_mutexattr_getprotocol(const pthread_mutexattr_t * attr,int * protocol)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
pthread_mutexattr_setrobust(pthread_mutexattr_t * attr,int robust)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
pthread_mutexattr_getrobust(const pthread_mutexattr_t * attr,int * robust)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
pthread_mutex_init(pthread_mutex_t * _RESTRICT_KYWD mutex,const pthread_mutexattr_t * _RESTRICT_KYWD attr)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
pthread_mutex_setprioceiling(pthread_mutex_t * mutex,int ceil,int * oceil)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
pthread_mutex_getprioceiling(const pthread_mutex_t * mp,int * ceiling)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
pthread_mutexattr_settype(pthread_mutexattr_t * attr,int type)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
pthread_mutexattr_gettype(const pthread_mutexattr_t * attr,int * typep)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