Print this page
9959 pthread_mutex_init should initialize mutex appropriately for robust mutex_init
Reviewed by: Jason King <jason.king@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libc/port/threads/pthr_mutex.c
+++ new/usr/src/lib/libc/port/threads/pthr_mutex.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 #include "lint.h"
28 28 #include "thr_uberdata.h"
29 29 #include <pthread.h>
30 30
31 31 /*
32 32 * pthread_mutexattr_init: allocates the mutex attribute object and
33 33 * initializes it with the default values.
34 34 */
35 35 #pragma weak _pthread_mutexattr_init = pthread_mutexattr_init
36 36 int
37 37 pthread_mutexattr_init(pthread_mutexattr_t *attr)
38 38 {
39 39 mattr_t *ap;
40 40
41 41 if ((ap = lmalloc(sizeof (mattr_t))) == NULL)
42 42 return (ENOMEM);
43 43 ap->pshared = PTHREAD_PROCESS_PRIVATE;
44 44 ap->type = PTHREAD_MUTEX_DEFAULT;
45 45 ap->protocol = PTHREAD_PRIO_NONE;
46 46 ap->robustness = PTHREAD_MUTEX_STALLED;
47 47 attr->__pthread_mutexattrp = ap;
48 48 return (0);
49 49 }
50 50
51 51 /*
52 52 * pthread_mutexattr_destroy: frees the mutex attribute object and
53 53 * invalidates it with NULL value.
54 54 */
55 55 int
56 56 pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
57 57 {
58 58 if (attr == NULL || attr->__pthread_mutexattrp == NULL)
59 59 return (EINVAL);
60 60 lfree(attr->__pthread_mutexattrp, sizeof (mattr_t));
61 61 attr->__pthread_mutexattrp = NULL;
62 62 return (0);
63 63 }
64 64
65 65 /*
66 66 * pthread_mutexattr_setpshared: sets the shared attribute
67 67 * to PTHREAD_PROCESS_PRIVATE or PTHREAD_PROCESS_SHARED.
68 68 * This is equivalent to setting the USYNC_THREAD/USYNC_PROCESS
69 69 * flag in mutex_init().
70 70 */
71 71 int
72 72 pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared)
73 73 {
74 74 mattr_t *ap;
75 75
76 76 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
77 77 (pshared != PTHREAD_PROCESS_PRIVATE &&
78 78 pshared != PTHREAD_PROCESS_SHARED))
79 79 return (EINVAL);
80 80 ap->pshared = pshared;
81 81 return (0);
82 82 }
83 83
84 84 /*
85 85 * pthread_mutexattr_getpshared: gets the shared attribute.
86 86 */
87 87 #pragma weak _pthread_mutexattr_getpshared = pthread_mutexattr_getpshared
88 88 int
89 89 pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr, int *pshared)
90 90 {
91 91 mattr_t *ap;
92 92
93 93 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
94 94 pshared == NULL)
95 95 return (EINVAL);
96 96 *pshared = ap->pshared;
97 97 return (0);
98 98 }
99 99
100 100 /*
101 101 * pthread_mutexattr_setprioceiling: sets the prioceiling attribute.
102 102 */
103 103 int
104 104 pthread_mutexattr_setprioceiling(pthread_mutexattr_t *attr, int prioceiling)
105 105 {
106 106 const pcclass_t *pccp = get_info_by_policy(SCHED_FIFO);
107 107 mattr_t *ap;
108 108
109 109 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
110 110 prioceiling < pccp->pcc_primin || prioceiling > pccp->pcc_primax)
111 111 return (EINVAL);
112 112 ap->prioceiling = prioceiling;
113 113 return (0);
114 114 }
115 115
116 116 /*
117 117 * pthread_mutexattr_getprioceiling: gets the prioceiling attribute.
118 118 */
119 119 #pragma weak _pthread_mutexattr_getprioceiling = \
120 120 pthread_mutexattr_getprioceiling
121 121 int
122 122 pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *attr, int *ceiling)
123 123 {
124 124 mattr_t *ap;
125 125
126 126 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
127 127 ceiling == NULL)
128 128 return (EINVAL);
129 129 *ceiling = ap->prioceiling;
130 130 return (0);
131 131 }
132 132
133 133 /*
134 134 * pthread_mutexattr_setprotocol: sets the protocol attribute.
135 135 */
136 136 int
137 137 pthread_mutexattr_setprotocol(pthread_mutexattr_t *attr, int protocol)
138 138 {
139 139 mattr_t *ap;
140 140
141 141 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL)
142 142 return (EINVAL);
143 143 if (protocol != PTHREAD_PRIO_NONE &&
144 144 protocol != PTHREAD_PRIO_INHERIT &&
145 145 protocol != PTHREAD_PRIO_PROTECT)
146 146 return (ENOTSUP);
147 147 ap->protocol = protocol;
148 148 return (0);
149 149 }
150 150
151 151 /*
152 152 * pthread_mutexattr_getprotocol: gets the protocol attribute.
153 153 */
154 154 #pragma weak _pthread_mutexattr_getprotocol = pthread_mutexattr_getprotocol
155 155 int
156 156 pthread_mutexattr_getprotocol(const pthread_mutexattr_t *attr, int *protocol)
157 157 {
158 158 mattr_t *ap;
159 159
160 160 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
161 161 protocol == NULL)
162 162 return (EINVAL);
163 163 *protocol = ap->protocol;
164 164 return (0);
165 165 }
166 166
167 167 /*
168 168 * pthread_mutexattr_setrobust: set the mutex robust attribute.
169 169 * pthread_mutexattr_setrobust_np: the historical name.
170 170 */
171 171 #pragma weak pthread_mutexattr_setrobust_np = pthread_mutexattr_setrobust
172 172 int
173 173 pthread_mutexattr_setrobust(pthread_mutexattr_t *attr, int robust)
174 174 {
175 175 mattr_t *ap;
176 176
177 177 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
178 178 (robust != PTHREAD_MUTEX_ROBUST && robust != PTHREAD_MUTEX_STALLED))
179 179 return (EINVAL);
180 180 ap->robustness = robust;
181 181 return (0);
182 182 }
183 183
184 184 /*
185 185 * pthread_mutexattr_getrobust: get the mutex robust attribute.
186 186 * pthread_mutexattr_getrobust_np: the historical name.
187 187 */
188 188 #pragma weak pthread_mutexattr_getrobust_np = pthread_mutexattr_getrobust
189 189 int
190 190 pthread_mutexattr_getrobust(const pthread_mutexattr_t *attr, int *robust)
191 191 {
192 192 mattr_t *ap;
193 193
194 194 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
195 195 robust == NULL)
196 196 return (EINVAL);
197 197 *robust = ap->robustness;
198 198 return (0);
199 199 }
200 200
201 201 /*
202 202 * pthread_mutex_init: Initializes the mutex object. It copies the
203 203 * various attributes into one type argument and calls mutex_init().
204 204 */
205 205 #pragma weak _pthread_mutex_init = pthread_mutex_init
206 206 int
207 207 pthread_mutex_init(pthread_mutex_t *_RESTRICT_KYWD mutex,
208 208 const pthread_mutexattr_t *_RESTRICT_KYWD attr)
209 209 {
210 210 mattr_t *ap;
211 211 int type;
212 212 int prioceiling = 0;
213 213
214 214 /*
215 215 * All of the pshared, type, protocol, robust attributes
216 216 * translate to bits in the mutex_type field.
217 217 */
218 218 if (attr != NULL) {
↓ open down ↓ |
218 lines elided |
↑ open up ↑ |
219 219 if ((ap = attr->__pthread_mutexattrp) == NULL)
220 220 return (EINVAL);
221 221 type = ap->pshared | ap->type | ap->protocol | ap->robustness;
222 222 if (ap->protocol == PTHREAD_PRIO_PROTECT)
223 223 prioceiling = ap->prioceiling;
224 224 } else {
225 225 type = PTHREAD_PROCESS_PRIVATE | PTHREAD_MUTEX_DEFAULT |
226 226 PTHREAD_PRIO_NONE | PTHREAD_MUTEX_STALLED;
227 227 }
228 228
229 + /*
230 + * POSIX mutexes (this interface) make no guarantee about the state of
231 + * the mutex before pthread_mutex_init(3C) is called. Sun mutexes, upon
232 + * which these are built and which mutex_init(3C) below represents
233 + * require that a robust mutex be initialized to all 0s _prior_ to
234 + * mutex_init() being called, and that mutex_init() of an initialized
235 + * mutex return EBUSY.
236 + *
237 + * We respect both these behaviors by zeroing the mutex here in the
238 + * POSIX implementation if and only if the mutex magic is incorrect,
239 + * and the mutex is robust.
240 + */
241 + if (((type & PTHREAD_MUTEX_ROBUST) != 0) &&
242 + (((mutex_t *)mutex)->mutex_magic != MUTEX_MAGIC)) {
243 + (void) memset(mutex, 0, sizeof (*mutex));
244 + }
245 +
229 246 return (mutex_init((mutex_t *)mutex, type, &prioceiling));
230 247 }
231 248
232 249 /*
233 250 * pthread_mutex_setprioceiling: sets the prioceiling.
234 251 * From the SUSv3 (POSIX) specification for pthread_mutex_setprioceiling():
235 252 * The process of locking the mutex need not
236 253 * adhere to the priority protect protocol.
237 254 * We pass the MUTEX_NOCEIL flag to mutex_lock_internal() so that
238 255 * a non-realtime thread can successfully execute this operation.
239 256 */
240 257 int
241 258 pthread_mutex_setprioceiling(pthread_mutex_t *mutex, int ceil, int *oceil)
242 259 {
243 260 mutex_t *mp = (mutex_t *)mutex;
244 261 const pcclass_t *pccp = get_info_by_policy(SCHED_FIFO);
245 262 int error;
246 263
247 264 if (!(mp->mutex_type & PTHREAD_PRIO_PROTECT) ||
248 265 ceil < pccp->pcc_primin || ceil > pccp->pcc_primax)
249 266 return (EINVAL);
250 267 error = mutex_lock_internal(mp, NULL, MUTEX_LOCK | MUTEX_NOCEIL);
251 268 if (error == 0 || error == EOWNERDEAD || error == ELOCKUNMAPPED) {
252 269 if (oceil)
253 270 *oceil = mp->mutex_ceiling;
254 271 mp->mutex_ceiling = ceil;
255 272 error = mutex_unlock_internal(mp, 1);
256 273 }
257 274 return (error);
258 275 }
259 276
260 277 /*
261 278 * pthread_mutex_getprioceiling: gets the prioceiling.
262 279 */
263 280 #pragma weak _pthread_mutex_getprioceiling = pthread_mutex_getprioceiling
264 281 int
265 282 pthread_mutex_getprioceiling(const pthread_mutex_t *mp, int *ceiling)
266 283 {
267 284 *ceiling = ((mutex_t *)mp)->mutex_ceiling;
268 285 return (0);
269 286 }
270 287
271 288 /*
272 289 * UNIX98
273 290 * pthread_mutexattr_settype: sets the type attribute
274 291 */
275 292 int
276 293 pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type)
277 294 {
278 295 mattr_t *ap;
279 296
280 297 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL)
281 298 return (EINVAL);
282 299 switch (type) {
283 300 case PTHREAD_MUTEX_NORMAL:
284 301 type = LOCK_NORMAL;
285 302 break;
286 303 case PTHREAD_MUTEX_ERRORCHECK:
287 304 type = LOCK_ERRORCHECK;
288 305 break;
289 306 case PTHREAD_MUTEX_RECURSIVE:
290 307 type = LOCK_RECURSIVE | LOCK_ERRORCHECK;
291 308 break;
292 309 default:
293 310 return (EINVAL);
294 311 }
295 312 ap->type = type;
296 313 return (0);
297 314 }
298 315
299 316 /*
300 317 * UNIX98
301 318 * pthread_mutexattr_gettype: gets the type attribute.
302 319 */
303 320 int
304 321 pthread_mutexattr_gettype(const pthread_mutexattr_t *attr, int *typep)
305 322 {
306 323 mattr_t *ap;
307 324 int type;
308 325
309 326 if (attr == NULL || (ap = attr->__pthread_mutexattrp) == NULL ||
310 327 typep == NULL)
311 328 return (EINVAL);
312 329 switch (ap->type) {
313 330 case LOCK_NORMAL:
314 331 type = PTHREAD_MUTEX_NORMAL;
315 332 break;
316 333 case LOCK_ERRORCHECK:
317 334 type = PTHREAD_MUTEX_ERRORCHECK;
318 335 break;
319 336 case LOCK_RECURSIVE | LOCK_ERRORCHECK:
320 337 type = PTHREAD_MUTEX_RECURSIVE;
321 338 break;
322 339 default:
323 340 return (EINVAL);
324 341 }
325 342 *typep = type;
326 343 return (0);
327 344 }
↓ open down ↓ |
89 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX