windows-nt/Source/XPSP1/NT/net/layer2svc/monitor/database/mrswlock.c

242 lines
4.9 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
mrswlock.c
Abstract:
This module contains multiple readers / single writer implementation.
Author:
abhisheV 18-October-2001
Environment
User Level: Win32
Revision History:
--*/
#include "precomp.h"
DWORD
InitializeRWLock(
PWZC_RW_LOCK pWZCRWLock
)
{
DWORD dwError = 0;
SECURITY_ATTRIBUTES SecurityAttributes;
memset(pWZCRWLock, 0, sizeof(WZC_RW_LOCK));
__try {
InitializeCriticalSection(&(pWZCRWLock->csExclusive));
pWZCRWLock->bInitExclusive = TRUE;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
dwError = GetExceptionCode();
BAIL_ON_WIN32_ERROR(dwError);
}
__try {
InitializeCriticalSection(&(pWZCRWLock->csShared));
pWZCRWLock->bInitShared = TRUE;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
dwError = GetExceptionCode();
BAIL_ON_WIN32_ERROR(dwError);
}
memset(&SecurityAttributes, 0, sizeof(SECURITY_ATTRIBUTES));
SecurityAttributes.nLength = sizeof(SecurityAttributes);
SecurityAttributes.lpSecurityDescriptor = NULL;
SecurityAttributes.bInheritHandle = TRUE;
pWZCRWLock->hReadDone = CreateEvent(
&SecurityAttributes,
TRUE,
FALSE,
NULL
);
if (!pWZCRWLock->hReadDone) {
dwError = GetLastError();
BAIL_ON_WIN32_ERROR(dwError);
}
SetEvent(pWZCRWLock->hReadDone);
return (dwError);
error:
DestroyRWLock(pWZCRWLock);
return (dwError);
}
VOID
DestroyRWLock(
PWZC_RW_LOCK pWZCRWLock
)
{
if (pWZCRWLock->hReadDone) {
CloseHandle(pWZCRWLock->hReadDone);
}
if (pWZCRWLock->bInitShared == TRUE) {
DeleteCriticalSection(&(pWZCRWLock->csShared));
pWZCRWLock->bInitShared = FALSE;
}
if (pWZCRWLock->bInitExclusive == TRUE) {
DeleteCriticalSection(&(pWZCRWLock->csExclusive));
pWZCRWLock->bInitExclusive = FALSE;
}
memset(pWZCRWLock, 0, sizeof(WZC_RW_LOCK));
return;
}
VOID
AcquireSharedLock(
PWZC_RW_LOCK pWZCRWLock
)
{
//
// Claim the exclusive critical section. This call blocks if there's
// an active writer or if there's a writer waiting for active readers
// to complete.
//
EnterCriticalSection(&(pWZCRWLock->csExclusive));
//
// Claim access to the reader count. If this blocks, it's only for a
// brief moment while other reader threads go through to increment or
// decrement the reader count.
//
EnterCriticalSection(&(pWZCRWLock->csShared));
//
// Increment the reader count. If this is the first reader then reset
// the read done event so that the next writer blocks.
//
if ((pWZCRWLock->lReaders)++ == 0) {
ResetEvent(pWZCRWLock->hReadDone);
}
//
// Release access to the reader count.
//
LeaveCriticalSection(&(pWZCRWLock->csShared));
//
// Release access to the exclusive critical section. This enables
// other readers to come through and the next write to wait for
// active readers to complete which in turn prevents new readers
// from entering.
//
LeaveCriticalSection(&(pWZCRWLock->csExclusive));
return;
}
VOID
AcquireExclusiveLock(
PWZC_RW_LOCK pWZCRWLock
)
{
DWORD dwStatus = 0;
//
// Claim the exclusive critical section. This not only prevents other
// threads from claiming the write lock, but also prevents any new
// threads from claiming the read lock.
//
EnterCriticalSection(&(pWZCRWLock->csExclusive));
pWZCRWLock->dwCurExclusiveOwnerThreadId = GetCurrentThreadId();
//
// Wait for the active readers to release their read locks.
//
dwStatus = WaitForSingleObject(pWZCRWLock->hReadDone, INFINITE);
ASSERT(dwStatus == WAIT_OBJECT_0);
return;
}
VOID
ReleaseSharedLock(
PWZC_RW_LOCK pWZCRWLock
)
{
//
// Claim access to the reader count. If this blocks, it's only for a
// brief moment while other reader threads go through to increment or
// decrement the reader count.
//
EnterCriticalSection(&(pWZCRWLock->csShared));
//
// Decrement the reader count. If this is the last reader, set read
// done event, which allows the first waiting writer to proceed.
//
if (--(pWZCRWLock->lReaders) == 0) {
SetEvent(pWZCRWLock->hReadDone);
}
//
// Release access to the reader count.
//
LeaveCriticalSection(&(pWZCRWLock->csShared));
return;
}
VOID
ReleaseExclusiveLock(
PWZC_RW_LOCK pWZCRWLock
)
{
//
// Make the exclusive critical section available to one other writer
// or to the first reader.
//
pWZCRWLock->dwCurExclusiveOwnerThreadId = 0;
LeaveCriticalSection(&(pWZCRWLock->csExclusive));
return;
}