]>
Commit | Line | Data |
---|---|---|
9385eb3d | 1 | /* |
224c7076 | 2 | * Copyright (c) 2000-2003, 2007 Apple Inc. All rights reserved. |
9385eb3d A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
9385eb3d A |
6 | * This file contains Original Code and/or Modifications of Original Code |
7 | * as defined in and that are subject to the Apple Public Source License | |
8 | * Version 2.0 (the 'License'). You may not use this file except in | |
9 | * compliance with the License. Please obtain a copy of the License at | |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this | |
11 | * file. | |
12 | * | |
13 | * The Original Code and all software distributed under the License are | |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER | |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, | |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. | |
18 | * Please see the License for the specific language governing rights and | |
19 | * limitations under the License. | |
20 | * | |
21 | * @APPLE_LICENSE_HEADER_END@ | |
22 | */ | |
5b2abdfb A |
23 | /*- |
24 | * Copyright (c) 1998 Alex Nash | |
25 | * All rights reserved. | |
26 | * | |
27 | * Redistribution and use in source and binary forms, with or without | |
28 | * modification, are permitted provided that the following conditions | |
29 | * are met: | |
30 | * 1. Redistributions of source code must retain the above copyright | |
31 | * notice, this list of conditions and the following disclaimer. | |
32 | * 2. Redistributions in binary form must reproduce the above copyright | |
33 | * notice, this list of conditions and the following disclaimer in the | |
34 | * documentation and/or other materials provided with the distribution. | |
35 | * | |
36 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
37 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
38 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
39 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
40 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
41 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
42 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
43 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
44 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
45 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
46 | * SUCH DAMAGE. | |
47 | * | |
48 | * $FreeBSD: src/lib/libc_r/uthread/uthread_rwlock.c,v 1.6 2001/04/10 04:19:20 deischen Exp $ | |
49 | */ | |
50 | ||
51 | /* | |
52 | * POSIX Pthread Library | |
53 | * -- Read Write Lock support | |
54 | * 4/24/02: A. Ramesh | |
55 | * Ported from FreeBSD | |
56 | */ | |
57 | ||
58 | #include "pthread_internals.h" | |
224c7076 A |
59 | extern int __unix_conforming; |
60 | ||
61 | #include "plockstat.h" | |
62 | #define READ_LOCK_PLOCKSTAT 0 | |
63 | #define WRITE_LOCK_PLOCKSTAT 1 | |
64 | ||
65 | #define BLOCK_FAIL_PLOCKSTAT 0 | |
66 | #define BLOCK_SUCCESS_PLOCKSTAT 1 | |
5b2abdfb A |
67 | |
68 | /* maximum number of times a read lock may be obtained */ | |
224c7076 A |
69 | #define MAX_READ_LOCKS (INT_MAX - 1) |
70 | ||
71 | ||
72 | #ifndef BUILDING_VARIANT /* [ */ | |
73 | ||
74 | ||
75 | int | |
76 | pthread_rwlockattr_init(pthread_rwlockattr_t *attr) | |
77 | { | |
78 | attr->sig = _PTHREAD_RWLOCK_ATTR_SIG; | |
79 | attr->pshared = _PTHREAD_DEFAULT_PSHARED; | |
80 | return (0); | |
81 | } | |
82 | ||
83 | int | |
84 | pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr) | |
85 | { | |
86 | attr->sig = _PTHREAD_NO_SIG; /* Uninitialized */ | |
87 | attr->pshared = 0; | |
88 | return (0); | |
89 | } | |
90 | ||
91 | int | |
92 | pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *attr, | |
93 | int *pshared) | |
94 | { | |
95 | if (attr->sig == _PTHREAD_RWLOCK_ATTR_SIG) | |
96 | { | |
97 | *pshared = (int)attr->pshared; | |
98 | return (0); | |
99 | } else | |
100 | { | |
101 | return (EINVAL); /* Not an initialized 'attribute' structure */ | |
102 | } | |
103 | } | |
104 | ||
105 | /* Temp: untill pshared is fixed right */ | |
106 | #ifdef PR_5243343 | |
107 | /* 5243343 - temporary hack to detect if we are running the conformance test */ | |
108 | extern int PR_5243343_flag; | |
109 | #endif /* PR_5243343 */ | |
110 | ||
111 | int | |
112 | pthread_rwlockattr_setpshared(pthread_rwlockattr_t * attr, int pshared) | |
113 | { | |
114 | if (attr->sig == _PTHREAD_RWLOCK_ATTR_SIG) | |
115 | { | |
116 | #if __DARWIN_UNIX03 | |
117 | #ifdef PR_5243343 | |
118 | if (( pshared == PTHREAD_PROCESS_PRIVATE) || (pshared == PTHREAD_PROCESS_SHARED && PR_5243343_flag)) | |
119 | #else /* !PR_5243343 */ | |
120 | if (( pshared == PTHREAD_PROCESS_PRIVATE) || (pshared == PTHREAD_PROCESS_SHARED)) | |
121 | #endif /* PR_5243343 */ | |
122 | #else /* __DARWIN_UNIX03 */ | |
123 | if ( pshared == PTHREAD_PROCESS_PRIVATE) | |
124 | #endif /* __DARWIN_UNIX03 */ | |
125 | { | |
126 | attr->pshared = pshared ; | |
127 | return (0); | |
128 | } else | |
129 | { | |
130 | return (EINVAL); /* Invalid parameter */ | |
131 | } | |
132 | } else | |
133 | { | |
134 | return (EINVAL); /* Not an initialized 'attribute' structure */ | |
135 | } | |
136 | ||
137 | } | |
138 | ||
139 | #endif /* !BUILDING_VARIANT ] */ | |
5b2abdfb A |
140 | |
141 | int | |
142 | pthread_rwlock_destroy(pthread_rwlock_t *rwlock) | |
143 | { | |
224c7076 | 144 | int ret; |
5b2abdfb A |
145 | |
146 | if (rwlock->sig != _PTHREAD_RWLOCK_SIG) { | |
147 | return(EINVAL); | |
148 | } else { | |
224c7076 A |
149 | #if __DARWIN_UNIX03 |
150 | /* grab the monitor lock */ | |
151 | if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) | |
152 | return(ret); | |
153 | ||
154 | if (rwlock->state != 0) { | |
155 | pthread_mutex_unlock(&rwlock->lock); | |
156 | return(EBUSY); | |
157 | } | |
158 | pthread_mutex_unlock(&rwlock->lock); | |
159 | #endif /* __DARWIN_UNIX03 */ | |
160 | ||
5b2abdfb A |
161 | pthread_mutex_destroy(&rwlock->lock); |
162 | pthread_cond_destroy(&rwlock->read_signal); | |
163 | pthread_cond_destroy(&rwlock->write_signal); | |
164 | rwlock->sig = _PTHREAD_NO_SIG; | |
224c7076 | 165 | return(0); |
5b2abdfb A |
166 | } |
167 | } | |
168 | ||
169 | int | |
170 | pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) | |
171 | { | |
172 | int ret; | |
224c7076 A |
173 | #if __DARWIN_UNIX03 |
174 | if (attr && (attr->sig != _PTHREAD_RWLOCK_ATTR_SIG)) { | |
175 | return(EINVAL); | |
176 | } | |
177 | /* if already inited check whether it is in use, then return EBUSY */ | |
178 | if ((rwlock->sig == _PTHREAD_RWLOCK_SIG) && (rwlock->state !=0 )) { | |
179 | return(EBUSY); | |
180 | } | |
181 | #endif /* __DARWIN_UNIX03 */ | |
5b2abdfb A |
182 | |
183 | /* initialize the lock */ | |
184 | if ((ret = pthread_mutex_init(&rwlock->lock, NULL)) != 0) | |
185 | return(ret); | |
186 | else { | |
187 | /* initialize the read condition signal */ | |
188 | ret = pthread_cond_init(&rwlock->read_signal, NULL); | |
189 | ||
190 | if (ret != 0) { | |
191 | pthread_mutex_destroy(&rwlock->lock); | |
192 | return(ret); | |
193 | } else { | |
194 | /* initialize the write condition signal */ | |
195 | ret = pthread_cond_init(&rwlock->write_signal, NULL); | |
196 | ||
197 | if (ret != 0) { | |
198 | pthread_cond_destroy(&rwlock->read_signal); | |
199 | pthread_mutex_destroy(&rwlock->lock); | |
200 | return(ret); | |
201 | } else { | |
202 | /* success */ | |
203 | rwlock->state = 0; | |
224c7076 | 204 | rwlock->owner = (pthread_t)0; |
5b2abdfb | 205 | rwlock->blocked_writers = 0; |
224c7076 A |
206 | if (attr) |
207 | rwlock->pshared = attr->pshared; | |
208 | else | |
209 | rwlock->pshared = _PTHREAD_DEFAULT_PSHARED; | |
210 | ||
5b2abdfb | 211 | rwlock->sig = _PTHREAD_RWLOCK_SIG; |
224c7076 | 212 | return(0); |
5b2abdfb A |
213 | } |
214 | } | |
215 | } | |
216 | } | |
217 | ||
218 | int | |
219 | pthread_rwlock_rdlock(pthread_rwlock_t *rwlock) | |
220 | { | |
221 | int ret; | |
224c7076 A |
222 | #if __DARWIN_UNIX03 |
223 | pthread_t self = pthread_self(); | |
224 | #endif | |
5b2abdfb A |
225 | |
226 | if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) { | |
227 | if ((ret = pthread_rwlock_init(rwlock, NULL)) != 0) { | |
224c7076 | 228 | PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret); |
5b2abdfb A |
229 | return(ret); |
230 | } | |
231 | } | |
232 | ||
224c7076 A |
233 | if (rwlock->sig != _PTHREAD_RWLOCK_SIG) { |
234 | PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, EINVAL); | |
5b2abdfb | 235 | return(EINVAL); |
224c7076 | 236 | } |
5b2abdfb | 237 | /* grab the monitor lock */ |
224c7076 A |
238 | if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) { |
239 | PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret); | |
5b2abdfb | 240 | return(ret); |
224c7076 A |
241 | } |
242 | ||
243 | #if __DARWIN_UNIX03 | |
244 | if ((rwlock->state < 0) && (rwlock->owner == self)) { | |
245 | pthread_mutex_unlock(&rwlock->lock); | |
246 | PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, EDEADLK); | |
247 | return(EDEADLK); | |
248 | } | |
249 | #endif /* __DARWIN_UNIX03 */ | |
250 | ||
251 | #if __DARWIN_UNIX03 | |
252 | while (rwlock->blocked_writers || ((rwlock->state < 0) && (rwlock->owner != self))) | |
253 | #else /* __DARWIN_UNIX03 */ | |
254 | while (rwlock->blocked_writers || rwlock->state < 0) | |
5b2abdfb | 255 | |
224c7076 A |
256 | #endif /* __DARWIN_UNIX03 */ |
257 | { | |
5b2abdfb | 258 | /* give writers priority over readers */ |
224c7076 | 259 | PLOCKSTAT_RW_BLOCK(rwlock, READ_LOCK_PLOCKSTAT); |
5b2abdfb A |
260 | ret = pthread_cond_wait(&rwlock->read_signal, &rwlock->lock); |
261 | ||
262 | if (ret != 0) { | |
263 | /* can't do a whole lot if this fails */ | |
264 | pthread_mutex_unlock(&rwlock->lock); | |
224c7076 A |
265 | PLOCKSTAT_RW_BLOCKED(rwlock, READ_LOCK_PLOCKSTAT, BLOCK_FAIL_PLOCKSTAT); |
266 | PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret); | |
5b2abdfb A |
267 | return(ret); |
268 | } | |
224c7076 A |
269 | |
270 | PLOCKSTAT_RW_BLOCKED(rwlock, READ_LOCK_PLOCKSTAT, BLOCK_SUCCESS_PLOCKSTAT); | |
5b2abdfb A |
271 | } |
272 | ||
273 | /* check lock count */ | |
224c7076 | 274 | if (rwlock->state == MAX_READ_LOCKS) { |
5b2abdfb | 275 | ret = EAGAIN; |
224c7076 A |
276 | PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret); |
277 | } | |
278 | else { | |
5b2abdfb | 279 | ++rwlock->state; /* indicate we are locked for reading */ |
224c7076 A |
280 | PLOCKSTAT_RW_ACQUIRE(rwlock, READ_LOCK_PLOCKSTAT); |
281 | } | |
5b2abdfb A |
282 | |
283 | /* | |
284 | * Something is really wrong if this call fails. Returning | |
285 | * error won't do because we've already obtained the read | |
286 | * lock. Decrementing 'state' is no good because we probably | |
287 | * don't have the monitor lock. | |
288 | */ | |
289 | pthread_mutex_unlock(&rwlock->lock); | |
290 | ||
291 | return(ret); | |
292 | } | |
293 | ||
294 | int | |
295 | pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock) | |
296 | { | |
297 | int ret; | |
224c7076 A |
298 | #if __DARWIN_UNIX03 |
299 | pthread_t self = pthread_self(); | |
300 | #endif | |
5b2abdfb A |
301 | |
302 | /* check for static initialization */ | |
303 | if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) { | |
304 | if ((ret = pthread_rwlock_init(rwlock, NULL)) != 0) { | |
224c7076 | 305 | PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret); |
5b2abdfb A |
306 | return(ret); |
307 | } | |
308 | } | |
309 | ||
224c7076 A |
310 | if (rwlock->sig != _PTHREAD_RWLOCK_SIG) { |
311 | PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, EINVAL); | |
5b2abdfb | 312 | return(EINVAL); |
224c7076 | 313 | } |
5b2abdfb | 314 | /* grab the monitor lock */ |
224c7076 A |
315 | if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) { |
316 | PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret); | |
5b2abdfb | 317 | return(ret); |
224c7076 | 318 | } |
5b2abdfb A |
319 | |
320 | /* give writers priority over readers */ | |
224c7076 | 321 | if (rwlock->blocked_writers || rwlock->state < 0) { |
5b2abdfb | 322 | ret = EBUSY; |
224c7076 A |
323 | PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret); |
324 | } | |
325 | else if (rwlock->state == MAX_READ_LOCKS) { | |
5b2abdfb | 326 | ret = EAGAIN; /* too many read locks acquired */ |
224c7076 A |
327 | PLOCKSTAT_RW_ERROR(rwlock, READ_LOCK_PLOCKSTAT, ret); |
328 | } | |
329 | else { | |
5b2abdfb | 330 | ++rwlock->state; /* indicate we are locked for reading */ |
224c7076 A |
331 | PLOCKSTAT_RW_ACQUIRE(rwlock, READ_LOCK_PLOCKSTAT); |
332 | } | |
5b2abdfb A |
333 | |
334 | /* see the comment on this in pthread_rwlock_rdlock */ | |
335 | pthread_mutex_unlock(&rwlock->lock); | |
336 | ||
337 | return(ret); | |
338 | } | |
339 | ||
340 | int | |
341 | pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock) | |
342 | { | |
343 | int ret; | |
224c7076 A |
344 | #if __DARWIN_UNIX03 |
345 | pthread_t self = pthread_self(); | |
346 | #endif /* __DARWIN_UNIX03 */ | |
5b2abdfb A |
347 | |
348 | /* check for static initialization */ | |
349 | if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) { | |
350 | if ((ret = pthread_rwlock_init(rwlock, NULL)) != 0) { | |
224c7076 | 351 | PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret); |
5b2abdfb A |
352 | return(ret); |
353 | } | |
354 | } | |
355 | ||
224c7076 A |
356 | if (rwlock->sig != _PTHREAD_RWLOCK_SIG) { |
357 | PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, EINVAL); | |
5b2abdfb | 358 | return(EINVAL); |
224c7076 | 359 | } |
5b2abdfb | 360 | /* grab the monitor lock */ |
224c7076 A |
361 | if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) { |
362 | PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret); | |
5b2abdfb | 363 | return(ret); |
224c7076 A |
364 | } |
365 | ||
5b2abdfb | 366 | |
224c7076 | 367 | if (rwlock->state != 0) { |
5b2abdfb | 368 | ret = EBUSY; |
224c7076 A |
369 | PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret); |
370 | } | |
371 | else { | |
5b2abdfb A |
372 | /* indicate we are locked for writing */ |
373 | rwlock->state = -1; | |
224c7076 A |
374 | #if __DARWIN_UNIX03 |
375 | rwlock->owner = self; | |
376 | #endif /* __DARWIN_UNIX03 */ | |
377 | PLOCKSTAT_RW_ACQUIRE(rwlock, WRITE_LOCK_PLOCKSTAT); | |
378 | } | |
5b2abdfb A |
379 | |
380 | /* see the comment on this in pthread_rwlock_rdlock */ | |
381 | pthread_mutex_unlock(&rwlock->lock); | |
382 | ||
383 | return(ret); | |
384 | } | |
385 | ||
386 | int | |
387 | pthread_rwlock_unlock(pthread_rwlock_t *rwlock) | |
388 | { | |
389 | int ret; | |
224c7076 A |
390 | int writer = (rwlock < 0) ? 1:0; |
391 | #if __DARWIN_UNIX03 | |
392 | pthread_t self = pthread_self(); | |
393 | #endif /* __DARWIN_UNIX03 */ | |
5b2abdfb | 394 | |
224c7076 A |
395 | if (rwlock->sig != _PTHREAD_RWLOCK_SIG) { |
396 | PLOCKSTAT_RW_ERROR(rwlock, writer, EINVAL); | |
5b2abdfb | 397 | return(EINVAL); |
224c7076 | 398 | } |
5b2abdfb | 399 | /* grab the monitor lock */ |
224c7076 A |
400 | if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) { |
401 | PLOCKSTAT_RW_ERROR(rwlock, writer, ret); | |
5b2abdfb | 402 | return(ret); |
224c7076 | 403 | } |
5b2abdfb A |
404 | |
405 | if (rwlock->state > 0) { | |
406 | if (--rwlock->state == 0 && rwlock->blocked_writers) | |
407 | ret = pthread_cond_signal(&rwlock->write_signal); | |
408 | } else if (rwlock->state < 0) { | |
409 | rwlock->state = 0; | |
224c7076 A |
410 | #if __DARWIN_UNIX03 |
411 | rwlock->owner = (pthread_t)0; | |
412 | #endif /* __DARWIN_UNIX03 */ | |
5b2abdfb A |
413 | |
414 | if (rwlock->blocked_writers) | |
415 | ret = pthread_cond_signal(&rwlock->write_signal); | |
416 | else | |
417 | ret = pthread_cond_broadcast(&rwlock->read_signal); | |
418 | } else | |
419 | ret = EINVAL; | |
420 | ||
224c7076 A |
421 | if (ret == 0) { |
422 | PLOCKSTAT_RW_RELEASE(rwlock, writer); | |
423 | } else { | |
424 | PLOCKSTAT_RW_ERROR(rwlock, writer, ret); | |
425 | } | |
426 | ||
5b2abdfb A |
427 | /* see the comment on this in pthread_rwlock_rdlock */ |
428 | pthread_mutex_unlock(&rwlock->lock); | |
429 | ||
430 | return(ret); | |
431 | } | |
432 | ||
433 | int | |
434 | pthread_rwlock_wrlock(pthread_rwlock_t *rwlock) | |
435 | { | |
436 | int ret; | |
224c7076 A |
437 | #if __DARWIN_UNIX03 |
438 | pthread_t self = pthread_self(); | |
439 | #endif /* __DARWIN_UNIX03 */ | |
5b2abdfb A |
440 | |
441 | /* check for static initialization */ | |
442 | if (rwlock->sig == _PTHREAD_RWLOCK_SIG_init) { | |
443 | if ((ret = pthread_rwlock_init(rwlock, NULL)) != 0) { | |
224c7076 | 444 | PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret); |
5b2abdfb A |
445 | return(ret); |
446 | } | |
447 | } | |
448 | ||
224c7076 A |
449 | if (rwlock->sig != _PTHREAD_RWLOCK_SIG) { |
450 | PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, EINVAL); | |
5b2abdfb | 451 | return(EINVAL); |
224c7076 | 452 | } |
5b2abdfb | 453 | /* grab the monitor lock */ |
224c7076 A |
454 | if ((ret = pthread_mutex_lock(&rwlock->lock)) != 0) { |
455 | PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret); | |
5b2abdfb | 456 | return(ret); |
224c7076 | 457 | } |
5b2abdfb | 458 | |
224c7076 A |
459 | #if __DARWIN_UNIX03 |
460 | if ((rwlock->state < 0) && (rwlock->owner == self)) { | |
461 | pthread_mutex_unlock(&rwlock->lock); | |
462 | PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, EDEADLK); | |
463 | return(EDEADLK); | |
464 | } | |
465 | #endif /* __DARWIN_UNIX03 */ | |
5b2abdfb A |
466 | while (rwlock->state != 0) { |
467 | ++rwlock->blocked_writers; | |
468 | ||
224c7076 | 469 | PLOCKSTAT_RW_BLOCK(rwlock, WRITE_LOCK_PLOCKSTAT); |
5b2abdfb A |
470 | ret = pthread_cond_wait(&rwlock->write_signal, &rwlock->lock); |
471 | ||
472 | if (ret != 0) { | |
473 | --rwlock->blocked_writers; | |
474 | pthread_mutex_unlock(&rwlock->lock); | |
224c7076 A |
475 | PLOCKSTAT_RW_BLOCKED(rwlock, WRITE_LOCK_PLOCKSTAT, BLOCK_FAIL_PLOCKSTAT); |
476 | PLOCKSTAT_RW_ERROR(rwlock, WRITE_LOCK_PLOCKSTAT, ret); | |
5b2abdfb A |
477 | return(ret); |
478 | } | |
479 | ||
224c7076 A |
480 | PLOCKSTAT_RW_BLOCKED(rwlock, WRITE_LOCK_PLOCKSTAT, BLOCK_SUCCESS_PLOCKSTAT); |
481 | ||
5b2abdfb A |
482 | --rwlock->blocked_writers; |
483 | } | |
484 | ||
485 | /* indicate we are locked for writing */ | |
486 | rwlock->state = -1; | |
224c7076 A |
487 | #if __DARWIN_UNIX03 |
488 | rwlock->owner = self; | |
489 | #endif /* __DARWIN_UNIX03 */ | |
490 | PLOCKSTAT_RW_ACQUIRE(rwlock, WRITE_LOCK_PLOCKSTAT); | |
5b2abdfb A |
491 | |
492 | /* see the comment on this in pthread_rwlock_rdlock */ | |
493 | pthread_mutex_unlock(&rwlock->lock); | |
494 | ||
495 | return(ret); | |
496 | } | |
497 | ||
5b2abdfb | 498 |