Print this page
5910 libnisdb won't build with modern GCC
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/libnisdb/nisdb_rw.c
+++ new/usr/src/lib/libnisdb/nisdb_rw.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, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /*
23 + * Copyright 2015 Gary Mills
23 24 * Copyright (c) 2001 by Sun Microsystems, Inc.
24 25 * All rights reserved.
25 26 */
26 27
27 -#pragma ident "%Z%%M% %I% %E% SMI"
28 -
29 28 #include <stdio.h>
30 29 #include <rpc/types.h>
31 30 #include <rpc/xdr.h>
32 31 #include "db_dictionary_c.h"
33 32 #include "nisdb_rw.h"
34 33 #include "nisdb_ldap.h"
35 34
36 35 /*
37 36 * Nesting-safe RW locking functions. Return 0 when successful, an
38 37 * error number from the E-series when not.
39 38 */
40 39
41 40 int
42 41 __nisdb_rwinit(__nisdb_rwlock_t *rw) {
43 42
44 43 int ret;
45 44
46 45 if (rw == 0) {
47 46 #ifdef NISDB_MT_DEBUG
48 47 abort();
49 48 #endif /* NISDB_MT_DEBUG */
50 49 return (EFAULT);
51 50 }
52 51
53 52 if ((ret = mutex_init(&rw->mutex, USYNC_THREAD, 0)) != 0)
54 53 return (ret);
55 54 if ((ret = cond_init(&rw->cv, USYNC_THREAD, 0)) != 0)
56 55 return (ret);
57 56 rw->destroyed = 0;
58 57
59 58 /*
60 59 * If we allow read-to-write lock migration, there's a potential
61 60 * race condition if two or more threads want to upgrade at the
62 61 * same time. The simple and safe (but crude and possibly costly)
63 62 * method to fix this is to always use exclusive locks, and so
64 63 * that has to be the default.
65 64 *
66 65 * There are two conditions under which it is safe to set
67 66 * 'force_write' to zero for a certain lock structure:
68 67 *
69 68 * (1) The lock will never be subject to migration, or
70 69 *
71 70 * (2) It's OK if the data protected by the lock has changed
72 71 * (a) Every time the lock (read or write) has been
73 72 * acquired (even if the lock already was held by
74 73 * the thread), and
75 74 * (b) After every call to a function that might have
76 75 * acquired the lock.
77 76 */
78 77 rw->force_write = NISDB_FORCE_WRITE;
79 78
80 79 rw->writer_count = rw->reader_count = rw->reader_blocked = 0;
81 80 rw->writer.id = rw->reader.id = INV_PTHREAD_ID;
82 81 rw->writer.count = rw->reader.count = 0;
83 82 rw->writer.next = rw->reader.next = 0;
84 83
85 84 return (0);
86 85 }
87 86
88 87
89 88 static __nisdb_rl_t *
90 89 find_reader(pthread_t id, __nisdb_rwlock_t *rw) {
91 90
92 91 __nisdb_rl_t *rr;
93 92
94 93 for (rr = &rw->reader; rr != 0; rr = rr->next) {
95 94 if (rr->id == INV_PTHREAD_ID) {
96 95 rr = 0;
97 96 break;
98 97 }
99 98 if (rr->id == id)
↓ open down ↓ |
61 lines elided |
↑ open up ↑ |
100 99 break;
101 100 }
102 101
103 102 return (rr);
104 103 }
105 104
106 105
107 106 int
108 107 __nisdb_rw_readlock_ok(__nisdb_rwlock_t *rw) {
109 108 int ret;
110 - pthread_t myself = pthread_self();
111 - __nisdb_rl_t *rr;
112 109
113 110 if (rw == 0)
114 111 return (EFAULT);
115 112
116 113 if (rw->destroyed != 0)
117 114 return (ESHUTDOWN);
118 115
119 116 if ((ret = mutex_lock(&rw->mutex)) != 0)
120 117 return (ret);
121 118
122 119 /*
123 120 * Only allow changing 'force_write' when it's really safe; i.e.,
124 121 * the lock hasn't been destroyed, and there are no readers.
125 122 */
126 123 if (rw->destroyed == 0 && rw->reader_count == 0) {
127 124 rw->force_write = 0;
128 125 ret = 0;
129 126 } else {
130 127 ret = EBUSY;
131 128 }
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
132 129
133 130 (void) mutex_unlock(&rw->mutex);
134 131
135 132 return (ret);
136 133 }
137 134
138 135
139 136 int
140 137 __nisdb_rw_force_writelock(__nisdb_rwlock_t *rw) {
141 138 int ret;
142 - pthread_t myself = pthread_self();
143 - __nisdb_rl_t *rr;
144 139
145 140 if (rw == 0 || rw->destroyed != 0)
146 141 return (ESHUTDOWN);
147 142
148 143 if ((ret = mutex_lock(&rw->mutex)) != 0)
149 144 return (ret);
150 145
151 146 /*
152 147 * Only allow changing 'force_write' when it's really safe; i.e.,
153 148 * the lock hasn't been destroyed, and there are no readers.
154 149 */
155 150 if (rw->destroyed == 0 && rw->reader_count == 0) {
156 151 rw->force_write = 1;
157 152 ret = 0;
158 153 } else {
159 154 ret = EBUSY;
160 155 }
161 156
162 157 (void) mutex_unlock(&rw->mutex);
163 158
164 159 return (ret);
165 160 }
166 161
167 162
168 163 int
169 164 __nisdb_wlock_trylock(__nisdb_rwlock_t *rw, int trylock) {
170 165
171 166 int ret;
172 167 pthread_t myself = pthread_self();
173 168 int all_readers_blocked = 0;
174 169 __nisdb_rl_t *rr = 0;
175 170
176 171 if (rw == 0) {
177 172 #ifdef NISDB_MT_DEBUG
178 173 /* This shouldn't happen */
179 174 abort();
180 175 #endif /* NISDB_MT_DEBUG */
181 176 return (EFAULT);
182 177 }
183 178
184 179 if (rw->destroyed != 0)
185 180 return (ESHUTDOWN);
186 181
187 182 if ((ret = mutex_lock(&rw->mutex)) != 0)
188 183 return (ret);
189 184
190 185 if (rw->destroyed != 0) {
191 186 (void) mutex_unlock(&rw->mutex);
192 187 return (ESHUTDOWN);
193 188 }
194 189
195 190 /* Simplest (and probably most common) case: no readers or writers */
196 191 if (rw->reader_count == 0 && rw->writer_count == 0) {
197 192 rw->writer_count = 1;
198 193 rw->writer.id = myself;
↓ open down ↓ |
45 lines elided |
↑ open up ↑ |
199 194 rw->writer.count = 1;
200 195 return (mutex_unlock(&rw->mutex));
201 196 }
202 197
203 198 /*
204 199 * Need to know if we're holding a read lock already, and if
205 200 * all other readers are blocked waiting for the mutex.
206 201 */
207 202 if (rw->reader_count > 0) {
208 203 if ((rr = find_reader(myself, rw)) != 0) {
209 - if (rr->count)
204 + if (rr->count) {
210 205 /*
211 206 * We're already holding a read lock, so
212 207 * if the number of readers equals the number
213 208 * of blocked readers plus one, all other
214 209 * readers are blocked.
215 210 */
216 211 if (rw->reader_count ==
217 212 (rw->reader_blocked + 1))
218 213 all_readers_blocked = 1;
219 - else
214 + } else {
220 215 /*
221 216 * We're not holding a read lock, so the
222 217 * number of readers should equal the number
223 218 * of blocked readers if all readers are
224 219 * blocked.
225 220 */
226 221 if (rw->reader_count == rw->reader_blocked)
227 222 all_readers_blocked = 1;
223 + }
228 224 }
229 225 }
230 226
231 227 /* Wait for reader(s) or writer to finish */
232 228 while (1) {
233 229 /*
234 230 * We can stop looping if one of the following holds:
235 231 * - No readers, no writers
236 232 * - No writers (or writer is myself), and one of:
237 233 * - No readers
238 234 * - One reader, and it's us
239 235 * - N readers, but all blocked on the mutex
240 236 */
241 237 if (
242 - (rw->writer_count == 0 && rw->reader_count == 0) ||
243 - ((rw->writer_count == 0 || rw->writer.id == myself) &&
244 - (rw->reader_count == 0) ||
245 - (rw->reader_count == 1 &&
246 - rw->reader.id == myself))) {
238 + (rw->writer_count == 0 && rw->reader_count == 0) ||
239 + (((rw->writer_count == 0 || rw->writer.id == myself) &&
240 + (rw->reader_count == 0)) ||
241 + (rw->reader_count == 1 &&
242 + rw->reader.id == myself))) {
247 243 break;
248 244 }
249 245 /*
250 246 * Provided that all readers are blocked on the mutex
251 247 * we break a potential dead-lock by acquiring the
252 248 * write lock.
253 249 */
254 250 if (all_readers_blocked) {
255 251 if (rw->writer_count == 0 || rw->writer.id == myself) {
256 252 break;
257 253 }
258 254 }
259 255
260 256 /*
261 257 * If 'trylock' is set, tell the caller that we'd have to
262 258 * block to obtain the lock.
263 259 */
264 260 if (trylock) {
265 261 (void) mutex_unlock(&rw->mutex);
266 262 return (EBUSY);
267 263 }
268 264
269 265 /* If we're also a reader, indicate that we're blocking */
270 266 if (rr != 0) {
271 267 rr->wait = 1;
272 268 rw->reader_blocked++;
273 269 }
274 270 if ((ret = cond_wait(&rw->cv, &rw->mutex)) != 0) {
275 271 if (rr != 0) {
276 272 rr->wait = 0;
277 273 if (rw->reader_blocked > 0)
278 274 rw->reader_blocked--;
279 275 #ifdef NISDB_MT_DEBUG
280 276 else
281 277 abort();
282 278 #endif /* NISDB_MT_DEBUG */
283 279 }
284 280 (void) mutex_unlock(&rw->mutex);
285 281 return (ret);
286 282 }
287 283 if (rr != 0) {
288 284 rr->wait = 0;
289 285 if (rw->reader_blocked > 0)
290 286 rw->reader_blocked--;
291 287 #ifdef NISDB_MT_DEBUG
292 288 else
293 289 abort();
294 290 #endif /* NISDB_MT_DEBUG */
295 291 }
296 292 }
297 293
298 294 /* OK to grab the write lock */
299 295 rw->writer.id = myself;
300 296 /* Increment lock depth */
301 297 rw->writer.count++;
302 298 /* Set number of writers (doesn't increase with lock depth) */
303 299 if (rw->writer_count == 0)
304 300 rw->writer_count = 1;
305 301
306 302 return (mutex_unlock(&rw->mutex));
307 303 }
308 304
309 305 int
310 306 __nisdb_wlock(__nisdb_rwlock_t *rw) {
311 307 return (__nisdb_wlock_trylock(rw, 0));
312 308 }
313 309
314 310
315 311 static __nisdb_rl_t *
316 312 increment_reader(pthread_t id, __nisdb_rwlock_t *rw) {
317 313
318 314 __nisdb_rl_t *rr;
319 315
320 316 for (rr = &rw->reader; rr != 0; rr = rr->next) {
321 317 if (rr->id == id || rr->id == INV_PTHREAD_ID)
322 318 break;
323 319 }
324 320 if (rw->reader_count == 0 && rr == &rw->reader) {
325 321 /* No previous reader */
326 322 rr->id = id;
327 323 rw->reader_count = 1;
328 324 } else if (rr == 0) {
329 325 if ((rr = malloc(sizeof (__nisdb_rl_t))) == 0)
330 326 return (0);
331 327 rr->id = id;
332 328 rr->count = 0;
333 329 /*
334 330 * For insertion simplicity, make it the second item
335 331 * on the list.
336 332 */
337 333 rr->next = rw->reader.next;
338 334 rw->reader.next = rr;
339 335 rw->reader_count++;
340 336 }
341 337 rr->count++;
342 338
343 339 return (rr);
344 340 }
345 341
346 342
347 343 int
348 344 __nisdb_rlock(__nisdb_rwlock_t *rw) {
349 345
350 346 int ret;
351 347 pthread_t myself = pthread_self();
352 348 __nisdb_rl_t *rr;
353 349
354 350 if (rw == 0) {
355 351 #ifdef NISDB_MT_DEBUG
356 352 /* This shouldn't happen */
357 353 abort();
358 354 #endif /* NISDB_MT_DEBUG */
359 355 return (EFAULT);
360 356 }
361 357
362 358 if (rw->destroyed != 0)
363 359 return (ESHUTDOWN);
364 360
365 361 if (rw->force_write)
366 362 return (__nisdb_wlock(rw));
367 363
368 364 if ((ret = mutex_lock(&rw->mutex)) != 0)
369 365 return (ret);
370 366
371 367 if (rw->destroyed != 0) {
372 368 (void) mutex_unlock(&rw->mutex);
373 369 return (ESHUTDOWN);
374 370 }
375 371
376 372 rr = find_reader(myself, rw);
377 373
378 374 /* Wait for writer to complete; writer == myself also OK */
379 375 while (rw->writer_count > 0 && rw->writer.id != myself) {
380 376 if (rr != 0) {
381 377 rr->wait = 1;
382 378 rw->reader_blocked++;
383 379 }
384 380 if ((ret = cond_wait(&rw->cv, &rw->mutex)) != 0) {
385 381 if (rr != 0) {
386 382 rr->wait = 0;
387 383 if (rw->reader_blocked > 0)
388 384 rw->reader_blocked--;
389 385 #ifdef NISDB_MT_DEBUG
390 386 else
391 387 abort();
392 388 #endif /* NISDB_MT_DEBUG */
393 389 }
394 390 (void) mutex_unlock(&rw->mutex);
395 391 return (ret);
396 392 }
397 393 if (rr != 0) {
398 394 rr->wait = 0;
399 395 if (rw->reader_blocked > 0)
400 396 rw->reader_blocked--;
401 397 #ifdef NISDB_MT_DEBUG
402 398 else
403 399 abort();
404 400 #endif /* NISDB_MT_DEBUG */
405 401 }
406 402 }
407 403
408 404 rr = increment_reader(myself, rw);
409 405 ret = mutex_unlock(&rw->mutex);
410 406 return ((rr == 0) ? ENOMEM : ret);
411 407 }
412 408
413 409
414 410 int
415 411 __nisdb_wulock(__nisdb_rwlock_t *rw) {
416 412
417 413 int ret;
418 414 pthread_t myself = pthread_self();
419 415
420 416 if (rw == 0) {
421 417 #ifdef NISDB_MT_DEBUG
422 418 /* This shouldn't happen */
423 419 abort();
424 420 #endif /* NISDB_MT_DEBUG */
425 421 return (EFAULT);
426 422 }
427 423
428 424 if (rw->destroyed != 0)
429 425 return (ESHUTDOWN);
430 426
431 427 if ((ret = mutex_lock(&rw->mutex)) != 0)
432 428 return (ret);
433 429
434 430 if (rw->destroyed != 0) {
435 431 (void) mutex_unlock(&rw->mutex);
436 432 return (ESHUTDOWN);
437 433 }
438 434
439 435 /* Sanity check */
440 436 if (rw->writer_count == 0 ||
441 437 rw->writer.id != myself || rw->writer.count == 0) {
442 438 #ifdef NISDB_MT_DEBUG
443 439 abort();
444 440 #endif /* NISDB_MT_DEBUG */
445 441 (void) mutex_unlock(&rw->mutex);
446 442 return (ENOLCK);
447 443 }
448 444
449 445 rw->writer.count--;
450 446 if (rw->writer.count == 0) {
451 447 rw->writer.id = INV_PTHREAD_ID;
452 448 rw->writer_count = 0;
453 449 if ((ret = cond_broadcast(&rw->cv)) != 0) {
454 450 (void) mutex_unlock(&rw->mutex);
455 451 return (ret);
456 452 }
457 453 }
458 454
459 455 return (mutex_unlock(&rw->mutex));
460 456 }
461 457
462 458
463 459 int
464 460 __nisdb_rulock(__nisdb_rwlock_t *rw) {
465 461
466 462 int ret;
467 463 pthread_t myself = pthread_self();
468 464 __nisdb_rl_t *rr, *prev;
469 465
470 466 if (rw == 0) {
471 467 #ifdef NISDB_MT_DEBUG
472 468 abort();
473 469 #endif /* NISDB_MT_DEBUG */
474 470 return (EFAULT);
475 471 }
476 472
477 473 if (rw->destroyed != 0)
478 474 return (ESHUTDOWN);
479 475
480 476 if (rw->force_write)
481 477 return (__nisdb_wulock(rw));
482 478
483 479 if ((ret = mutex_lock(&rw->mutex)) != 0)
484 480 return (ret);
485 481
486 482 if (rw->destroyed != 0) {
487 483 (void) mutex_unlock(&rw->mutex);
488 484 return (ESHUTDOWN);
489 485 }
490 486
491 487 /* Sanity check */
492 488 if (rw->reader_count == 0 ||
493 489 (rw->writer_count > 0 && rw->writer.id != myself)) {
494 490 #ifdef NISDB_MT_DEBUG
495 491 abort();
496 492 #endif /* NISDB_MT_DEBUG */
497 493 (void) mutex_unlock(&rw->mutex);
498 494 return (ENOLCK);
499 495 }
500 496
501 497 /* Find the reader record */
502 498 for (rr = &rw->reader, prev = 0; rr != 0; prev = rr, rr = rr->next) {
503 499 if (rr->id == myself)
504 500 break;
505 501 }
506 502
507 503 if (rr == 0 || rr->count == 0) {
508 504 #ifdef NISDB_MT_DEBUG
509 505 abort();
510 506 #endif /* NISDB_MT_DEBUG */
511 507 (void) mutex_unlock(&rw->mutex);
512 508 return (ENOLCK);
513 509 }
514 510
515 511 rr->count--;
516 512 if (rr->count == 0) {
517 513 if (rr != &rw->reader) {
518 514 /* Remove item from list and free it */
519 515 prev->next = rr->next;
520 516 free(rr);
521 517 } else {
522 518 /*
523 519 * First record: copy second to first, and free second
524 520 * record.
525 521 */
526 522 if (rr->next != 0) {
527 523 rr = rr->next;
528 524 rw->reader.id = rr->id;
529 525 rw->reader.count = rr->count;
530 526 rw->reader.next = rr->next;
531 527 free(rr);
532 528 } else {
533 529 /* Decomission the first record */
534 530 rr->id = INV_PTHREAD_ID;
535 531 }
536 532 }
537 533 rw->reader_count--;
538 534 }
539 535
540 536 /* If there are no readers, wake up any waiting writer */
541 537 if (rw->reader_count == 0) {
542 538 if ((ret = cond_broadcast(&rw->cv)) != 0) {
543 539 (void) mutex_unlock(&rw->mutex);
544 540 return (ret);
545 541 }
546 542 }
547 543
548 544 return (mutex_unlock(&rw->mutex));
549 545 }
550 546
551 547
552 548 /* Return zero if write lock held by this thread, non-zero otherwise */
553 549 int
554 550 __nisdb_assert_wheld(__nisdb_rwlock_t *rw) {
555 551
556 552 int ret;
557 553
558 554
559 555 if (rw == 0) {
560 556 #ifdef NISDB_MT_DEBUG
561 557 abort();
562 558 #endif /* NISDB_MT_DEBUG */
563 559 return (EFAULT);
564 560 }
565 561
566 562 if (rw->destroyed != 0)
567 563 return (ESHUTDOWN);
568 564
569 565 if ((ret = mutex_lock(&rw->mutex)) != 0)
570 566 return (ret);
571 567
572 568 if (rw->destroyed != 0) {
573 569 (void) mutex_unlock(&rw->mutex);
574 570 return (ESHUTDOWN);
575 571 }
576 572
577 573 if (rw->writer_count == 0 || rw->writer.id != pthread_self()) {
578 574 ret = mutex_unlock(&rw->mutex);
579 575 return ((ret == 0) ? -1 : ret);
580 576 }
581 577
582 578 /*
583 579 * We're holding the lock, so we should return zero. Since
584 580 * that's what mutex_unlock() does if it succeeds, we just
585 581 * return the value of mutex_unlock().
586 582 */
587 583 return (mutex_unlock(&rw->mutex));
588 584 }
589 585
590 586
591 587 /* Return zero if read lock held by this thread, non-zero otherwise */
592 588 int
593 589 __nisdb_assert_rheld(__nisdb_rwlock_t *rw) {
594 590
595 591 int ret;
596 592 pthread_t myself = pthread_self();
597 593 __nisdb_rl_t *rr;
598 594
599 595
600 596 if (rw == 0) {
601 597 #ifdef NISDB_MT_DEBUG
602 598 abort();
603 599 #endif /* NISDB_MT_DEBUG */
604 600 return (EFAULT);
605 601 }
606 602
607 603 if (rw->destroyed != 0)
608 604 return (ESHUTDOWN);
609 605
610 606 if (rw->force_write)
611 607 return (__nisdb_assert_wheld(rw));
612 608
613 609 if ((ret = mutex_lock(&rw->mutex)) != 0)
614 610 return (ret);
615 611
616 612 if (rw->destroyed != 0) {
617 613 (void) mutex_unlock(&rw->mutex);
618 614 return (ESHUTDOWN);
619 615 }
620 616
621 617 /* Write lock also OK */
622 618 if (rw->writer_count > 0 && rw->writer.id == myself) {
623 619 (void) mutex_unlock(&rw->mutex);
624 620 return (0);
625 621 }
626 622
627 623 if (rw->reader_count == 0) {
628 624 (void) mutex_unlock(&rw->mutex);
629 625 return (EBUSY);
630 626 }
631 627
632 628 rr = &rw->reader;
633 629 do {
634 630 if (rr->id == myself) {
635 631 (void) mutex_unlock(&rw->mutex);
636 632 return (0);
637 633 }
638 634 rr = rr->next;
639 635 } while (rr != 0);
640 636
↓ open down ↓ |
384 lines elided |
↑ open up ↑ |
641 637 ret = mutex_unlock(&rw->mutex);
642 638 return ((ret == 0) ? EBUSY : ret);
643 639 }
644 640
645 641
646 642 int
647 643 __nisdb_destroy_lock(__nisdb_rwlock_t *rw) {
648 644
649 645 int ret;
650 646 pthread_t myself = pthread_self();
651 - __nisdb_rl_t *rr;
652 647
653 648
654 649 if (rw == 0) {
655 650 #ifdef NISDB_MT_DEBUG
656 651 abort();
657 652 #endif /* NISDB_MT_DEBUG */
658 653 return (EFAULT);
659 654 }
660 655
661 656 if (rw->destroyed != 0)
662 657 return (ESHUTDOWN);
663 658
664 659 if ((ret = mutex_lock(&rw->mutex)) != 0)
665 660 return (ret);
666 661
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
667 662 if (rw->destroyed != 0) {
668 663 (void) mutex_unlock(&rw->mutex);
669 664 return (ESHUTDOWN);
670 665 }
671 666
672 667 /*
673 668 * Only proceed if if there are neither readers nor writers
674 669 * other than this thread. Also, no nested locks may be in
675 670 * effect.
676 671 */
677 - if ((rw->writer_count > 0 &&
678 - (rw->writer.id != myself || rw->writer.count != 1) ||
679 - (rw->reader_count > 0 &&
680 - !(rw->reader_count == 1 && rw->reader.id == myself &&
681 - rw->reader.count == 1))) ||
682 - (rw->writer_count > 0 && rw->reader_count > 0)) {
672 + if (((rw->writer_count > 0 &&
673 + (rw->writer.id != myself || rw->writer.count != 1)) ||
674 + (rw->reader_count > 0 &&
675 + !(rw->reader_count == 1 && rw->reader.id == myself &&
676 + rw->reader.count == 1))) ||
677 + (rw->writer_count > 0 && rw->reader_count > 0)) {
683 678 #ifdef NISDB_MT_DEBUG
684 679 abort();
685 680 #endif /* NISDB_MT_DEBUG */
686 681 (void) mutex_unlock(&rw->mutex);
687 682 return (ENOLCK);
688 683 }
689 684
690 685 /*
691 686 * Mark lock destroyed, so that any thread waiting on the mutex
692 687 * will know what's what. Of course, this is a bit iffy, since
693 688 * we're probably being called from a destructor, and the structure
694 689 * where we live will soon cease to exist (i.e., be freed and
695 690 * perhaps re-used). Still, we can only do our best, and give
696 691 * those other threads the best chance possible.
697 692 */
698 693 rw->destroyed++;
699 694
700 695 return (mutex_unlock(&rw->mutex));
701 696 }
702 697
703 698 void
704 699 __nisdb_lock_report(__nisdb_rwlock_t *rw) {
705 700 char *myself = "__nisdb_lock_report";
706 701
707 702 if (rw == 0) {
708 703 printf("%s: NULL argument\n", myself);
709 704 return;
710 705 }
711 706
712 707 if (rw->destroyed)
713 708 printf("0x%x: DESTROYED\n", rw);
714 709
715 710 printf("0x%x: Read locking %s\n",
716 711 rw, rw->force_write ? "disallowed" : "allowed");
717 712
718 713 if (rw->writer_count == 0)
719 714 printf("0x%x: No writer\n", rw);
720 715 else if (rw->writer_count == 1) {
721 716 printf("0x%x: Write locked by %d, depth = %d\n",
722 717 rw, rw->writer.id, rw->writer.count);
723 718 if (rw->writer.wait)
724 719 printf("0x%x:\tWriter blocked\n", rw);
725 720 } else
726 721 printf("0x%x: Invalid writer count = %d\n",
727 722 rw, rw->writer_count);
728 723
729 724 if (rw->reader_count == 0)
730 725 printf("0x%x: No readers\n", rw);
731 726 else {
732 727 __nisdb_rl_t *r;
733 728
734 729 printf("0x%x: %d readers, %d blocked\n",
735 730 rw, rw->reader_count, rw->reader_blocked);
736 731 for (r = &rw->reader; r != 0; r = r->next) {
737 732 printf("0x%x:\tthread %d, depth = %d%s\n",
738 733 rw, r->id, r->count,
739 734 (r->wait ? " (blocked)" : ""));
740 735 }
741 736 }
742 737 }
↓ open down ↓ |
50 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX