00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <stddef.h>
00025
00026 #include <isc/atomic.h>
00027 #include <isc/magic.h>
00028 #include <isc/msgs.h>
00029 #include <isc/platform.h>
00030 #include <isc/rwlock.h>
00031 #include <isc/util.h>
00032
00033 #define RWLOCK_MAGIC ISC_MAGIC('R', 'W', 'L', 'k')
00034 #define VALID_RWLOCK(rwl) ISC_MAGIC_VALID(rwl, RWLOCK_MAGIC)
00035
00036 #ifdef ISC_PLATFORM_USETHREADS
00037
00038 #ifndef RWLOCK_DEFAULT_READ_QUOTA
00039 #define RWLOCK_DEFAULT_READ_QUOTA 4
00040 #endif
00041
00042 #ifndef RWLOCK_DEFAULT_WRITE_QUOTA
00043 #define RWLOCK_DEFAULT_WRITE_QUOTA 4
00044 #endif
00045
00046 #ifdef ISC_RWLOCK_TRACE
00047 #include <stdio.h>
00048 #include <isc/thread.h>
00049
00050 static void
00051 print_lock(const char *operation, isc_rwlock_t *rwl, isc_rwlocktype_t type) {
00052 fprintf(stderr,
00053 isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
00054 ISC_MSG_PRINTLOCK,
00055 "rwlock %p thread %lu %s(%s): %s, %u active, "
00056 "%u granted, %u rwaiting, %u wwaiting\n"),
00057 rwl, isc_thread_self(), operation,
00058 (type == isc_rwlocktype_read ?
00059 isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
00060 ISC_MSG_READ, "read") :
00061 isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
00062 ISC_MSG_WRITE, "write")),
00063 (rwl->type == isc_rwlocktype_read ?
00064 isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
00065 ISC_MSG_READING, "reading") :
00066 isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
00067 ISC_MSG_WRITING, "writing")),
00068 rwl->active, rwl->granted, rwl->readers_waiting,
00069 rwl->writers_waiting);
00070 }
00071 #endif
00072
00073 isc_result_t
00074 isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
00075 unsigned int write_quota)
00076 {
00077 isc_result_t result;
00078
00079 REQUIRE(rwl != NULL);
00080
00081
00082
00083
00084
00085 rwl->magic = 0;
00086
00087 #if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG)
00088 rwl->write_requests = 0;
00089 rwl->write_completions = 0;
00090 rwl->cnt_and_flag = 0;
00091 rwl->readers_waiting = 0;
00092 rwl->write_granted = 0;
00093 if (read_quota != 0) {
00094 UNEXPECTED_ERROR(__FILE__, __LINE__,
00095 "read quota is not supported");
00096 }
00097 if (write_quota == 0)
00098 write_quota = RWLOCK_DEFAULT_WRITE_QUOTA;
00099 rwl->write_quota = write_quota;
00100 #else
00101 rwl->type = isc_rwlocktype_read;
00102 rwl->original = isc_rwlocktype_none;
00103 rwl->active = 0;
00104 rwl->granted = 0;
00105 rwl->readers_waiting = 0;
00106 rwl->writers_waiting = 0;
00107 if (read_quota == 0)
00108 read_quota = RWLOCK_DEFAULT_READ_QUOTA;
00109 rwl->read_quota = read_quota;
00110 if (write_quota == 0)
00111 write_quota = RWLOCK_DEFAULT_WRITE_QUOTA;
00112 rwl->write_quota = write_quota;
00113 #endif
00114
00115 result = isc_mutex_init(&rwl->lock);
00116 if (result != ISC_R_SUCCESS)
00117 return (result);
00118
00119 result = isc_condition_init(&rwl->readable);
00120 if (result != ISC_R_SUCCESS) {
00121 UNEXPECTED_ERROR(__FILE__, __LINE__,
00122 "isc_condition_init(readable) %s: %s",
00123 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
00124 ISC_MSG_FAILED, "failed"),
00125 isc_result_totext(result));
00126 result = ISC_R_UNEXPECTED;
00127 goto destroy_lock;
00128 }
00129 result = isc_condition_init(&rwl->writeable);
00130 if (result != ISC_R_SUCCESS) {
00131 UNEXPECTED_ERROR(__FILE__, __LINE__,
00132 "isc_condition_init(writeable) %s: %s",
00133 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
00134 ISC_MSG_FAILED, "failed"),
00135 isc_result_totext(result));
00136 result = ISC_R_UNEXPECTED;
00137 goto destroy_rcond;
00138 }
00139
00140 rwl->magic = RWLOCK_MAGIC;
00141
00142 return (ISC_R_SUCCESS);
00143
00144 destroy_rcond:
00145 (void)isc_condition_destroy(&rwl->readable);
00146 destroy_lock:
00147 DESTROYLOCK(&rwl->lock);
00148
00149 return (result);
00150 }
00151
00152 void
00153 isc_rwlock_destroy(isc_rwlock_t *rwl) {
00154 REQUIRE(VALID_RWLOCK(rwl));
00155
00156 #if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG)
00157 REQUIRE(rwl->write_requests == rwl->write_completions &&
00158 rwl->cnt_and_flag == 0 && rwl->readers_waiting == 0);
00159 #else
00160 LOCK(&rwl->lock);
00161 REQUIRE(rwl->active == 0 &&
00162 rwl->readers_waiting == 0 &&
00163 rwl->writers_waiting == 0);
00164 UNLOCK(&rwl->lock);
00165 #endif
00166
00167 rwl->magic = 0;
00168 (void)isc_condition_destroy(&rwl->readable);
00169 (void)isc_condition_destroy(&rwl->writeable);
00170 DESTROYLOCK(&rwl->lock);
00171 }
00172
00173 #if defined(ISC_PLATFORM_HAVEXADD) && defined(ISC_PLATFORM_HAVECMPXCHG)
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 #define WRITER_ACTIVE 0x1
00238 #define READER_INCR 0x2
00239
00240 isc_result_t
00241 isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
00242 isc_int32_t cntflag;
00243
00244 REQUIRE(VALID_RWLOCK(rwl));
00245
00246 #ifdef ISC_RWLOCK_TRACE
00247 print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
00248 ISC_MSG_PRELOCK, "prelock"), rwl, type);
00249 #endif
00250
00251 if (type == isc_rwlocktype_read) {
00252 if (rwl->write_requests != rwl->write_completions) {
00253
00254 LOCK(&rwl->lock);
00255 if (rwl->write_requests != rwl->write_completions) {
00256 rwl->readers_waiting++;
00257 WAIT(&rwl->readable, &rwl->lock);
00258 rwl->readers_waiting--;
00259 }
00260 UNLOCK(&rwl->lock);
00261 }
00262
00263 cntflag = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
00264 POST(cntflag);
00265 while (1) {
00266 if ((rwl->cnt_and_flag & WRITER_ACTIVE) == 0)
00267 break;
00268
00269
00270 LOCK(&rwl->lock);
00271 rwl->readers_waiting++;
00272 if ((rwl->cnt_and_flag & WRITER_ACTIVE) != 0)
00273 WAIT(&rwl->readable, &rwl->lock);
00274 rwl->readers_waiting--;
00275 UNLOCK(&rwl->lock);
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301 }
00302
00303
00304
00305
00306
00307
00308 rwl->write_granted = 0;
00309 } else {
00310 isc_int32_t prev_writer;
00311
00312
00313 prev_writer = isc_atomic_xadd(&rwl->write_requests, 1);
00314 while (rwl->write_completions != prev_writer) {
00315 LOCK(&rwl->lock);
00316 if (rwl->write_completions != prev_writer) {
00317 WAIT(&rwl->writeable, &rwl->lock);
00318 UNLOCK(&rwl->lock);
00319 continue;
00320 }
00321 UNLOCK(&rwl->lock);
00322 break;
00323 }
00324
00325 while (1) {
00326 cntflag = isc_atomic_cmpxchg(&rwl->cnt_and_flag, 0,
00327 WRITER_ACTIVE);
00328 if (cntflag == 0)
00329 break;
00330
00331
00332 LOCK(&rwl->lock);
00333 if (rwl->cnt_and_flag != 0)
00334 WAIT(&rwl->writeable, &rwl->lock);
00335 UNLOCK(&rwl->lock);
00336 }
00337
00338 INSIST((rwl->cnt_and_flag & WRITER_ACTIVE) != 0);
00339 rwl->write_granted++;
00340 }
00341
00342 #ifdef ISC_RWLOCK_TRACE
00343 print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
00344 ISC_MSG_POSTLOCK, "postlock"), rwl, type);
00345 #endif
00346
00347 return (ISC_R_SUCCESS);
00348 }
00349
00350 isc_result_t
00351 isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
00352 isc_int32_t cntflag;
00353
00354 REQUIRE(VALID_RWLOCK(rwl));
00355
00356 #ifdef ISC_RWLOCK_TRACE
00357 print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
00358 ISC_MSG_PRELOCK, "prelock"), rwl, type);
00359 #endif
00360
00361 if (type == isc_rwlocktype_read) {
00362
00363 if (rwl->write_requests != rwl->write_completions)
00364 return (ISC_R_LOCKBUSY);
00365
00366
00367 cntflag = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
00368 if ((cntflag & WRITER_ACTIVE) != 0) {
00369
00370
00371
00372
00373 cntflag = isc_atomic_xadd(&rwl->cnt_and_flag,
00374 -READER_INCR);
00375
00376
00377
00378
00379 if (cntflag == READER_INCR &&
00380 rwl->write_completions != rwl->write_requests) {
00381 LOCK(&rwl->lock);
00382 BROADCAST(&rwl->writeable);
00383 UNLOCK(&rwl->lock);
00384 }
00385
00386 return (ISC_R_LOCKBUSY);
00387 }
00388 } else {
00389
00390 cntflag = isc_atomic_cmpxchg(&rwl->cnt_and_flag, 0,
00391 WRITER_ACTIVE);
00392 if (cntflag != 0)
00393 return (ISC_R_LOCKBUSY);
00394
00395
00396
00397
00398
00399 (void)isc_atomic_xadd(&rwl->write_completions, -1);
00400
00401 rwl->write_granted++;
00402 }
00403
00404 #ifdef ISC_RWLOCK_TRACE
00405 print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
00406 ISC_MSG_POSTLOCK, "postlock"), rwl, type);
00407 #endif
00408
00409 return (ISC_R_SUCCESS);
00410 }
00411
00412 isc_result_t
00413 isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
00414 isc_int32_t prevcnt;
00415
00416 REQUIRE(VALID_RWLOCK(rwl));
00417
00418
00419 prevcnt = isc_atomic_cmpxchg(&rwl->cnt_and_flag,
00420 READER_INCR, WRITER_ACTIVE);
00421
00422
00423
00424
00425 INSIST((prevcnt & WRITER_ACTIVE) == 0 &&
00426 (prevcnt & ~WRITER_ACTIVE) != 0);
00427
00428 if (prevcnt == READER_INCR) {
00429
00430
00431
00432
00433 (void)isc_atomic_xadd(&rwl->write_completions, -1);
00434 } else
00435 return (ISC_R_LOCKBUSY);
00436
00437 return (ISC_R_SUCCESS);
00438
00439 }
00440
00441 void
00442 isc_rwlock_downgrade(isc_rwlock_t *rwl) {
00443 isc_int32_t prev_readers;
00444
00445 REQUIRE(VALID_RWLOCK(rwl));
00446
00447
00448 prev_readers = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR);
00449
00450 INSIST((prev_readers & WRITER_ACTIVE) != 0);
00451
00452
00453 (void)isc_atomic_xadd(&rwl->cnt_and_flag, -WRITER_ACTIVE);
00454 (void)isc_atomic_xadd(&rwl->write_completions, 1);
00455
00456
00457 LOCK(&rwl->lock);
00458 if (rwl->readers_waiting > 0)
00459 BROADCAST(&rwl->readable);
00460 UNLOCK(&rwl->lock);
00461 }
00462
00463 isc_result_t
00464 isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
00465 isc_int32_t prev_cnt;
00466
00467 REQUIRE(VALID_RWLOCK(rwl));
00468
00469 #ifdef ISC_RWLOCK_TRACE
00470 print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
00471 ISC_MSG_PREUNLOCK, "preunlock"), rwl, type);
00472 #endif
00473
00474 if (type == isc_rwlocktype_read) {
00475 prev_cnt = isc_atomic_xadd(&rwl->cnt_and_flag, -READER_INCR);
00476
00477
00478
00479
00480
00481
00482 if (prev_cnt == READER_INCR &&
00483 rwl->write_completions != rwl->write_requests) {
00484 LOCK(&rwl->lock);
00485 BROADCAST(&rwl->writeable);
00486 UNLOCK(&rwl->lock);
00487 }
00488 } else {
00489 isc_boolean_t wakeup_writers = ISC_TRUE;
00490
00491
00492
00493
00494
00495 (void)isc_atomic_xadd(&rwl->cnt_and_flag, -WRITER_ACTIVE);
00496 (void)isc_atomic_xadd(&rwl->write_completions, 1);
00497
00498 if (rwl->write_granted >= rwl->write_quota ||
00499 rwl->write_requests == rwl->write_completions ||
00500 (rwl->cnt_and_flag & ~WRITER_ACTIVE) != 0) {
00501
00502
00503
00504
00505
00506
00507
00508
00509 LOCK(&rwl->lock);
00510 if (rwl->readers_waiting > 0) {
00511 wakeup_writers = ISC_FALSE;
00512 BROADCAST(&rwl->readable);
00513 }
00514 UNLOCK(&rwl->lock);
00515 }
00516
00517 if (rwl->write_requests != rwl->write_completions &&
00518 wakeup_writers) {
00519 LOCK(&rwl->lock);
00520 BROADCAST(&rwl->writeable);
00521 UNLOCK(&rwl->lock);
00522 }
00523 }
00524
00525 #ifdef ISC_RWLOCK_TRACE
00526 print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
00527 ISC_MSG_POSTUNLOCK, "postunlock"),
00528 rwl, type);
00529 #endif
00530
00531 return (ISC_R_SUCCESS);
00532 }
00533
00534 #else
00535
00536 static isc_result_t
00537 doit(isc_rwlock_t *rwl, isc_rwlocktype_t type, isc_boolean_t nonblock) {
00538 isc_boolean_t skip = ISC_FALSE;
00539 isc_boolean_t done = ISC_FALSE;
00540 isc_result_t result = ISC_R_SUCCESS;
00541
00542 REQUIRE(VALID_RWLOCK(rwl));
00543
00544 LOCK(&rwl->lock);
00545
00546 #ifdef ISC_RWLOCK_TRACE
00547 print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
00548 ISC_MSG_PRELOCK, "prelock"), rwl, type);
00549 #endif
00550
00551 if (type == isc_rwlocktype_read) {
00552 if (rwl->readers_waiting != 0)
00553 skip = ISC_TRUE;
00554 while (!done) {
00555 if (!skip &&
00556 ((rwl->active == 0 ||
00557 (rwl->type == isc_rwlocktype_read &&
00558 (rwl->writers_waiting == 0 ||
00559 rwl->granted < rwl->read_quota)))))
00560 {
00561 rwl->type = isc_rwlocktype_read;
00562 rwl->active++;
00563 rwl->granted++;
00564 done = ISC_TRUE;
00565 } else if (nonblock) {
00566 result = ISC_R_LOCKBUSY;
00567 done = ISC_TRUE;
00568 } else {
00569 skip = ISC_FALSE;
00570 rwl->readers_waiting++;
00571 WAIT(&rwl->readable, &rwl->lock);
00572 rwl->readers_waiting--;
00573 }
00574 }
00575 } else {
00576 if (rwl->writers_waiting != 0)
00577 skip = ISC_TRUE;
00578 while (!done) {
00579 if (!skip && rwl->active == 0) {
00580 rwl->type = isc_rwlocktype_write;
00581 rwl->active = 1;
00582 rwl->granted++;
00583 done = ISC_TRUE;
00584 } else if (nonblock) {
00585 result = ISC_R_LOCKBUSY;
00586 done = ISC_TRUE;
00587 } else {
00588 skip = ISC_FALSE;
00589 rwl->writers_waiting++;
00590 WAIT(&rwl->writeable, &rwl->lock);
00591 rwl->writers_waiting--;
00592 }
00593 }
00594 }
00595
00596 #ifdef ISC_RWLOCK_TRACE
00597 print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
00598 ISC_MSG_POSTLOCK, "postlock"), rwl, type);
00599 #endif
00600
00601 UNLOCK(&rwl->lock);
00602
00603 return (result);
00604 }
00605
00606 isc_result_t
00607 isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
00608 return (doit(rwl, type, ISC_FALSE));
00609 }
00610
00611 isc_result_t
00612 isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
00613 return (doit(rwl, type, ISC_TRUE));
00614 }
00615
00616 isc_result_t
00617 isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
00618 isc_result_t result = ISC_R_SUCCESS;
00619
00620 REQUIRE(VALID_RWLOCK(rwl));
00621 LOCK(&rwl->lock);
00622 REQUIRE(rwl->type == isc_rwlocktype_read);
00623 REQUIRE(rwl->active != 0);
00624
00625
00626 if (rwl->active == 1) {
00627 rwl->original = (rwl->original == isc_rwlocktype_none) ?
00628 isc_rwlocktype_read : isc_rwlocktype_none;
00629 rwl->type = isc_rwlocktype_write;
00630 } else
00631 result = ISC_R_LOCKBUSY;
00632
00633 UNLOCK(&rwl->lock);
00634 return (result);
00635 }
00636
00637 void
00638 isc_rwlock_downgrade(isc_rwlock_t *rwl) {
00639
00640 REQUIRE(VALID_RWLOCK(rwl));
00641 LOCK(&rwl->lock);
00642 REQUIRE(rwl->type == isc_rwlocktype_write);
00643 REQUIRE(rwl->active == 1);
00644
00645 rwl->type = isc_rwlocktype_read;
00646 rwl->original = (rwl->original == isc_rwlocktype_none) ?
00647 isc_rwlocktype_write : isc_rwlocktype_none;
00648
00649
00650
00651
00652 if (rwl->original == isc_rwlocktype_none &&
00653 (rwl->writers_waiting == 0 || rwl->granted < rwl->read_quota) &&
00654 rwl->readers_waiting > 0)
00655 BROADCAST(&rwl->readable);
00656
00657 UNLOCK(&rwl->lock);
00658 }
00659
00660 isc_result_t
00661 isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
00662
00663 REQUIRE(VALID_RWLOCK(rwl));
00664 LOCK(&rwl->lock);
00665 REQUIRE(rwl->type == type);
00666
00667 UNUSED(type);
00668
00669 #ifdef ISC_RWLOCK_TRACE
00670 print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
00671 ISC_MSG_PREUNLOCK, "preunlock"), rwl, type);
00672 #endif
00673
00674 INSIST(rwl->active > 0);
00675 rwl->active--;
00676 if (rwl->active == 0) {
00677 if (rwl->original != isc_rwlocktype_none) {
00678 rwl->type = rwl->original;
00679 rwl->original = isc_rwlocktype_none;
00680 }
00681 if (rwl->type == isc_rwlocktype_read) {
00682 rwl->granted = 0;
00683 if (rwl->writers_waiting > 0) {
00684 rwl->type = isc_rwlocktype_write;
00685 SIGNAL(&rwl->writeable);
00686 } else if (rwl->readers_waiting > 0) {
00687
00688 BROADCAST(&rwl->readable);
00689 }
00690 } else {
00691 if (rwl->readers_waiting > 0) {
00692 if (rwl->writers_waiting > 0 &&
00693 rwl->granted < rwl->write_quota) {
00694 SIGNAL(&rwl->writeable);
00695 } else {
00696 rwl->granted = 0;
00697 rwl->type = isc_rwlocktype_read;
00698 BROADCAST(&rwl->readable);
00699 }
00700 } else if (rwl->writers_waiting > 0) {
00701 rwl->granted = 0;
00702 SIGNAL(&rwl->writeable);
00703 } else {
00704 rwl->granted = 0;
00705 }
00706 }
00707 }
00708 INSIST(rwl->original == isc_rwlocktype_none);
00709
00710 #ifdef ISC_RWLOCK_TRACE
00711 print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK,
00712 ISC_MSG_POSTUNLOCK, "postunlock"),
00713 rwl, type);
00714 #endif
00715
00716 UNLOCK(&rwl->lock);
00717
00718 return (ISC_R_SUCCESS);
00719 }
00720
00721 #endif
00722 #else
00723
00724 isc_result_t
00725 isc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota,
00726 unsigned int write_quota)
00727 {
00728 REQUIRE(rwl != NULL);
00729
00730 UNUSED(read_quota);
00731 UNUSED(write_quota);
00732
00733 rwl->type = isc_rwlocktype_read;
00734 rwl->active = 0;
00735 rwl->magic = RWLOCK_MAGIC;
00736
00737 return (ISC_R_SUCCESS);
00738 }
00739
00740 isc_result_t
00741 isc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
00742 REQUIRE(VALID_RWLOCK(rwl));
00743
00744 if (type == isc_rwlocktype_read) {
00745 if (rwl->type != isc_rwlocktype_read && rwl->active != 0)
00746 return (ISC_R_LOCKBUSY);
00747 rwl->type = isc_rwlocktype_read;
00748 rwl->active++;
00749 } else {
00750 if (rwl->active != 0)
00751 return (ISC_R_LOCKBUSY);
00752 rwl->type = isc_rwlocktype_write;
00753 rwl->active = 1;
00754 }
00755 return (ISC_R_SUCCESS);
00756 }
00757
00758 isc_result_t
00759 isc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
00760 return (isc_rwlock_lock(rwl, type));
00761 }
00762
00763 isc_result_t
00764 isc_rwlock_tryupgrade(isc_rwlock_t *rwl) {
00765 isc_result_t result = ISC_R_SUCCESS;
00766
00767 REQUIRE(VALID_RWLOCK(rwl));
00768 REQUIRE(rwl->type == isc_rwlocktype_read);
00769 REQUIRE(rwl->active != 0);
00770
00771
00772 if (rwl->active == 1)
00773 rwl->type = isc_rwlocktype_write;
00774 else
00775 result = ISC_R_LOCKBUSY;
00776 return (result);
00777 }
00778
00779 void
00780 isc_rwlock_downgrade(isc_rwlock_t *rwl) {
00781
00782 REQUIRE(VALID_RWLOCK(rwl));
00783 REQUIRE(rwl->type == isc_rwlocktype_write);
00784 REQUIRE(rwl->active == 1);
00785
00786 rwl->type = isc_rwlocktype_read;
00787 }
00788
00789 isc_result_t
00790 isc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) {
00791 REQUIRE(VALID_RWLOCK(rwl));
00792 REQUIRE(rwl->type == type);
00793
00794 UNUSED(type);
00795
00796 INSIST(rwl->active > 0);
00797 rwl->active--;
00798
00799 return (ISC_R_SUCCESS);
00800 }
00801
00802 void
00803 isc_rwlock_destroy(isc_rwlock_t *rwl) {
00804 REQUIRE(rwl != NULL);
00805 REQUIRE(rwl->active == 0);
00806 rwl->magic = 0;
00807 }
00808
00809 #endif