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 + -
显示快捷键?