rwlock.c
来自「非常好的dns解析软件」· C语言 代码 · 共 809 行 · 第 1/2 页
C
809 行
#endif return (ISC_R_SUCCESS);}isc_result_tisc_rwlock_tryupgrade(isc_rwlock_t *rwl) { isc_int32_t prevcnt; REQUIRE(VALID_RWLOCK(rwl)); /* Try to acquire write access. */ prevcnt = isc_atomic_cmpxchg(&rwl->cnt_and_flag, READER_INCR, WRITER_ACTIVE); /* * There must have been no writer, and there must have been at least * one reader. */ INSIST((prevcnt & WRITER_ACTIVE) == 0 && (prevcnt & ~WRITER_ACTIVE) != 0); if (prevcnt == READER_INCR) { /* * We are the only reader and have been upgraded. * Now jump into the head of the writer waiting queue. */ (void)isc_atomic_xadd(&rwl->write_completions, -1); } else return (ISC_R_LOCKBUSY); return (ISC_R_SUCCESS); }voidisc_rwlock_downgrade(isc_rwlock_t *rwl) { isc_int32_t prev_readers; REQUIRE(VALID_RWLOCK(rwl)); /* Become an active reader. */ prev_readers = isc_atomic_xadd(&rwl->cnt_and_flag, READER_INCR); /* We must have been a writer. */ INSIST((prev_readers & WRITER_ACTIVE) != 0); /* Complete write */ (void)isc_atomic_xadd(&rwl->cnt_and_flag, -WRITER_ACTIVE); (void)isc_atomic_xadd(&rwl->write_completions, 1); /* Resume other readers */ LOCK(&rwl->lock); if (rwl->readers_waiting > 0) BROADCAST(&rwl->readable); UNLOCK(&rwl->lock);}isc_result_tisc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { isc_int32_t prev_cnt; REQUIRE(VALID_RWLOCK(rwl));#ifdef ISC_RWLOCK_TRACE print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, ISC_MSG_PREUNLOCK, "preunlock"), rwl, type);#endif if (type == isc_rwlocktype_read) { prev_cnt = isc_atomic_xadd(&rwl->cnt_and_flag, -READER_INCR); /* * If we're the last reader and any writers are waiting, wake * them up. We need to wake up all of them to ensure the * FIFO order. */ if (prev_cnt == READER_INCR && rwl->write_completions != rwl->write_requests) { LOCK(&rwl->lock); BROADCAST(&rwl->writeable); UNLOCK(&rwl->lock); } } else { isc_boolean_t wakeup_writers = ISC_TRUE; /* * Reset the flag, and (implicitly) tell other writers * we are done. */ (void)isc_atomic_xadd(&rwl->cnt_and_flag, -WRITER_ACTIVE); (void)isc_atomic_xadd(&rwl->write_completions, 1); if (rwl->write_granted >= rwl->write_quota || rwl->write_requests == rwl->write_completions || (rwl->cnt_and_flag & ~WRITER_ACTIVE) != 0) { /* * We have passed the write quota, no writer is * waiting, or some readers are almost ready, pending * possible writers. Note that the last case can * happen even if write_requests != write_completions * (which means a new writer in the queue), so we need * to catch the case explicitly. */ LOCK(&rwl->lock); if (rwl->readers_waiting > 0) { wakeup_writers = ISC_FALSE; BROADCAST(&rwl->readable); } UNLOCK(&rwl->lock); } if (rwl->write_requests != rwl->write_completions && wakeup_writers) { LOCK(&rwl->lock); BROADCAST(&rwl->writeable); UNLOCK(&rwl->lock); } }#ifdef ISC_RWLOCK_TRACE print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, ISC_MSG_POSTUNLOCK, "postunlock"), rwl, type);#endif return (ISC_R_SUCCESS);}#else /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */static isc_result_tdoit(isc_rwlock_t *rwl, isc_rwlocktype_t type, isc_boolean_t nonblock) { isc_boolean_t skip = ISC_FALSE; isc_boolean_t done = ISC_FALSE; isc_result_t result = ISC_R_SUCCESS; REQUIRE(VALID_RWLOCK(rwl)); LOCK(&rwl->lock);#ifdef ISC_RWLOCK_TRACE print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, ISC_MSG_PRELOCK, "prelock"), rwl, type);#endif if (type == isc_rwlocktype_read) { if (rwl->readers_waiting != 0) skip = ISC_TRUE; while (!done) { if (!skip && ((rwl->active == 0 || (rwl->type == isc_rwlocktype_read && (rwl->writers_waiting == 0 || rwl->granted < rwl->read_quota))))) { rwl->type = isc_rwlocktype_read; rwl->active++; rwl->granted++; done = ISC_TRUE; } else if (nonblock) { result = ISC_R_LOCKBUSY; done = ISC_TRUE; } else { skip = ISC_FALSE; rwl->readers_waiting++; WAIT(&rwl->readable, &rwl->lock); rwl->readers_waiting--; } } } else { if (rwl->writers_waiting != 0) skip = ISC_TRUE; while (!done) { if (!skip && rwl->active == 0) { rwl->type = isc_rwlocktype_write; rwl->active = 1; rwl->granted++; done = ISC_TRUE; } else if (nonblock) { result = ISC_R_LOCKBUSY; done = ISC_TRUE; } else { skip = ISC_FALSE; rwl->writers_waiting++; WAIT(&rwl->writeable, &rwl->lock); rwl->writers_waiting--; } } }#ifdef ISC_RWLOCK_TRACE print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, ISC_MSG_POSTLOCK, "postlock"), rwl, type);#endif UNLOCK(&rwl->lock); return (result);}isc_result_tisc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { return (doit(rwl, type, ISC_FALSE));}isc_result_tisc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { return (doit(rwl, type, ISC_TRUE));}isc_result_tisc_rwlock_tryupgrade(isc_rwlock_t *rwl) { isc_result_t result = ISC_R_SUCCESS; REQUIRE(VALID_RWLOCK(rwl)); LOCK(&rwl->lock); REQUIRE(rwl->type == isc_rwlocktype_read); REQUIRE(rwl->active != 0); /* If we are the only reader then succeed. */ if (rwl->active == 1) { rwl->original = (rwl->original == isc_rwlocktype_none) ? isc_rwlocktype_read : isc_rwlocktype_none; rwl->type = isc_rwlocktype_write; } else result = ISC_R_LOCKBUSY; UNLOCK(&rwl->lock); return (result);}voidisc_rwlock_downgrade(isc_rwlock_t *rwl) { REQUIRE(VALID_RWLOCK(rwl)); LOCK(&rwl->lock); REQUIRE(rwl->type == isc_rwlocktype_write); REQUIRE(rwl->active == 1); rwl->type = isc_rwlocktype_read; rwl->original = (rwl->original == isc_rwlocktype_none) ? isc_rwlocktype_write : isc_rwlocktype_none; /* * Resume processing any read request that were blocked when * we upgraded. */ if (rwl->original == isc_rwlocktype_none && (rwl->writers_waiting == 0 || rwl->granted < rwl->read_quota) && rwl->readers_waiting > 0) BROADCAST(&rwl->readable); UNLOCK(&rwl->lock);}isc_result_tisc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { REQUIRE(VALID_RWLOCK(rwl)); LOCK(&rwl->lock); REQUIRE(rwl->type == type); UNUSED(type);#ifdef ISC_RWLOCK_TRACE print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, ISC_MSG_PREUNLOCK, "preunlock"), rwl, type);#endif INSIST(rwl->active > 0); rwl->active--; if (rwl->active == 0) { if (rwl->original != isc_rwlocktype_none) { rwl->type = rwl->original; rwl->original = isc_rwlocktype_none; } if (rwl->type == isc_rwlocktype_read) { rwl->granted = 0; if (rwl->writers_waiting > 0) { rwl->type = isc_rwlocktype_write; SIGNAL(&rwl->writeable); } else if (rwl->readers_waiting > 0) { /* Does this case ever happen? */ BROADCAST(&rwl->readable); } } else { if (rwl->readers_waiting > 0) { if (rwl->writers_waiting > 0 && rwl->granted < rwl->write_quota) { SIGNAL(&rwl->writeable); } else { rwl->granted = 0; rwl->type = isc_rwlocktype_read; BROADCAST(&rwl->readable); } } else if (rwl->writers_waiting > 0) { rwl->granted = 0; SIGNAL(&rwl->writeable); } else { rwl->granted = 0; } } } INSIST(rwl->original == isc_rwlocktype_none);#ifdef ISC_RWLOCK_TRACE print_lock(isc_msgcat_get(isc_msgcat, ISC_MSGSET_RWLOCK, ISC_MSG_POSTUNLOCK, "postunlock"), rwl, type);#endif UNLOCK(&rwl->lock); return (ISC_R_SUCCESS);}#endif /* ISC_PLATFORM_HAVEXADD && ISC_PLATFORM_HAVECMPXCHG */#else /* ISC_PLATFORM_USETHREADS */isc_result_tisc_rwlock_init(isc_rwlock_t *rwl, unsigned int read_quota, unsigned int write_quota){ REQUIRE(rwl != NULL); UNUSED(read_quota); UNUSED(write_quota); rwl->type = isc_rwlocktype_read; rwl->active = 0; rwl->magic = RWLOCK_MAGIC; return (ISC_R_SUCCESS);}isc_result_tisc_rwlock_lock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { REQUIRE(VALID_RWLOCK(rwl)); if (type == isc_rwlocktype_read) { if (rwl->type != isc_rwlocktype_read && rwl->active != 0) return (ISC_R_LOCKBUSY); rwl->type = isc_rwlocktype_read; rwl->active++; } else { if (rwl->active != 0) return (ISC_R_LOCKBUSY); rwl->type = isc_rwlocktype_write; rwl->active = 1; } return (ISC_R_SUCCESS);}isc_result_tisc_rwlock_trylock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { return (isc_rwlock_lock(rwl, type));}isc_result_tisc_rwlock_tryupgrade(isc_rwlock_t *rwl) { isc_result_t result = ISC_R_SUCCESS; REQUIRE(VALID_RWLOCK(rwl)); REQUIRE(rwl->type == isc_rwlocktype_read); REQUIRE(rwl->active != 0); /* If we are the only reader then succeed. */ if (rwl->active == 1) rwl->type = isc_rwlocktype_write; else result = ISC_R_LOCKBUSY; return (result);}voidisc_rwlock_downgrade(isc_rwlock_t *rwl) { REQUIRE(VALID_RWLOCK(rwl)); REQUIRE(rwl->type == isc_rwlocktype_write); REQUIRE(rwl->active == 1); rwl->type = isc_rwlocktype_read;}isc_result_tisc_rwlock_unlock(isc_rwlock_t *rwl, isc_rwlocktype_t type) { REQUIRE(VALID_RWLOCK(rwl)); REQUIRE(rwl->type == type); UNUSED(type); INSIST(rwl->active > 0); rwl->active--; return (ISC_R_SUCCESS);}voidisc_rwlock_destroy(isc_rwlock_t *rwl) { REQUIRE(rwl != NULL); REQUIRE(rwl->active == 0); rwl->magic = 0;}#endif /* ISC_PLATFORM_USETHREADS */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?