windows-nt/Source/XPSP1/NT/net/rras/ip/rip/sync.c

334 lines
7.5 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
//============================================================================
// Copyright (c) 1996, Microsoft Corporation
//
// File: sync.c
//
// History:
// Abolade Gbadegesin Jan-12-1996 Created.
//
// Synchronization routines used by IPRIP.
//============================================================================
#include "pchrip.h"
//----------------------------------------------------------------------------
// Function: QueueRipWorker
//
// This function is called to queue a RIP function in a safe fashion;
// if cleanup is in progress or if RIP has stopped, this function
// discards the work-item.
//----------------------------------------------------------------------------
DWORD
QueueRipWorker(
WORKERFUNCTION pFunction,
PVOID pContext
) {
DWORD dwErr = NO_ERROR;
EnterCriticalSection(&ig.IG_CS);
if (ig.IG_Status != IPRIP_STATUS_RUNNING) {
//
// cannot queue a work function when RIP has quit or is quitting
//
dwErr = ERROR_CAN_NOT_COMPLETE;
}
else {
BOOL bSuccess;
++ig.IG_ActivityCount;
bSuccess = QueueUserWorkItem(
(LPTHREAD_START_ROUTINE)pFunction,
pContext, 0
);
if (!bSuccess) {
dwErr = GetLastError();
--ig.IG_ActivityCount;
}
}
LeaveCriticalSection(&ig.IG_CS);
return dwErr;
}
//----------------------------------------------------------------------------
// Function: EnterRipAPI
//
// This function is called to when entering a RIP api, as well as
// when entering the input thread and timer thread.
// It checks to see if RIP has stopped, and if so it quits; otherwise
// it increments the count of active threads.
//----------------------------------------------------------------------------
BOOL
EnterRipAPI(
) {
BOOL bEntered;
EnterCriticalSection(&ig.IG_CS);
if (ig.IG_Status == IPRIP_STATUS_RUNNING) {
//
// RIP is running, so the API may continue
//
++ig.IG_ActivityCount;
bEntered = TRUE;
}
else {
//
// RIP is not running, so the API exits quietly
//
bEntered = FALSE;
}
LeaveCriticalSection(&ig.IG_CS);
return bEntered;
}
//----------------------------------------------------------------------------
// Function: EnterRipWorker
//
// This function is called when entering a RIP worker-function.
// Since there is a lapse between the time a worker-function is queued
// and the time the function is actually invoked by a worker thread,
// this function must check to see if RIP has stopped or is stopping;
// if this is the case, then it decrements the activity count,
// releases the activity semaphore, and quits.
//----------------------------------------------------------------------------
BOOL
EnterRipWorker(
) {
BOOL bEntered;
EnterCriticalSection(&ig.IG_CS);
if (ig.IG_Status == IPRIP_STATUS_RUNNING) {
//
// RIP is running, so the function may continue
//
bEntered = TRUE;
}
else
if (ig.IG_Status == IPRIP_STATUS_STOPPING) {
//
// RIP is not running, but it was, so the function must stop.
//
--ig.IG_ActivityCount;
ReleaseSemaphore(ig.IG_ActivitySemaphore, 1, NULL);
bEntered = FALSE;
}
else {
//
// RIP probably never started. quit quietly
//
bEntered = FALSE;
}
LeaveCriticalSection(&ig.IG_CS);
return bEntered;
}
//----------------------------------------------------------------------------
// Function: LeaveRipWorker
//
// This function is called when leaving a RIP API or worker function.
// It decrements the activity count, and if it detects that RIP has stopped
// or is stopping, it releases the activity semaphore.
//----------------------------------------------------------------------------
VOID
LeaveRipWorker(
) {
EnterCriticalSection(&ig.IG_CS);
--ig.IG_ActivityCount;
if (ig.IG_Status == IPRIP_STATUS_STOPPING) {
ReleaseSemaphore(ig.IG_ActivitySemaphore, 1, NULL);
}
LeaveCriticalSection(&ig.IG_CS);
}
//----------------------------------------------------------------------------
// Function: CreateReadWriteLock
//
// Initializes a multiple-reader/single-writer lock object
//----------------------------------------------------------------------------
DWORD
CreateReadWriteLock(
PREAD_WRITE_LOCK pRWL
) {
pRWL->RWL_ReaderCount = 0;
try {
InitializeCriticalSection(&(pRWL)->RWL_ReadWriteBlock);
}
except (EXCEPTION_EXECUTE_HANDLER) {
return GetLastError();
}
pRWL->RWL_ReaderDoneEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
if (pRWL->RWL_ReaderDoneEvent != NULL) {
return GetLastError();
}
return NO_ERROR;
}
//----------------------------------------------------------------------------
// Function: DeleteReadWriteLock
//
// Frees resources used by a multiple-reader/single-writer lock object
//----------------------------------------------------------------------------
VOID
DeleteReadWriteLock(
PREAD_WRITE_LOCK pRWL
) {
CloseHandle(pRWL->RWL_ReaderDoneEvent);
pRWL->RWL_ReaderDoneEvent = NULL;
DeleteCriticalSection(&pRWL->RWL_ReadWriteBlock);
pRWL->RWL_ReaderCount = 0;
}
//----------------------------------------------------------------------------
// Function: AcquireReadLock
//
// Secures shared ownership of the lock object for the caller.
//
// readers enter the read-write critical section, increment the count,
// and leave the critical section
//----------------------------------------------------------------------------
VOID
AcquireReadLock(
PREAD_WRITE_LOCK pRWL
) {
EnterCriticalSection(&pRWL->RWL_ReadWriteBlock);
InterlockedIncrement(&pRWL->RWL_ReaderCount);
LeaveCriticalSection(&pRWL->RWL_ReadWriteBlock);
}
//----------------------------------------------------------------------------
// Function: ReleaseReadLock
//
// Relinquishes shared ownership of the lock object.
//
// the last reader sets the event to wake any waiting writers
//----------------------------------------------------------------------------
VOID
ReleaseReadLock(
PREAD_WRITE_LOCK pRWL
) {
if (InterlockedDecrement(&pRWL->RWL_ReaderCount) < 0) {
SetEvent(pRWL->RWL_ReaderDoneEvent);
}
}
//----------------------------------------------------------------------------
// Function: AcquireWriteLock
//
// Secures exclusive ownership of the lock object.
//
// the writer blocks other threads by entering the ReadWriteBlock section,
// and then waits for any thread(s) owning the lock to finish
//----------------------------------------------------------------------------
VOID
AcquireWriteLock(
PREAD_WRITE_LOCK pRWL
) {
EnterCriticalSection(&pRWL->RWL_ReadWriteBlock);
if (InterlockedDecrement(&pRWL->RWL_ReaderCount) >= 0) {
WaitForSingleObject(pRWL->RWL_ReaderDoneEvent, INFINITE);
}
}
//----------------------------------------------------------------------------
// Function: ReleaseWriteLock
//
// Relinquishes exclusive ownership of the lock object.
//
// the writer releases the lock by setting the count to zero
// and then leaving the ReadWriteBlock critical section
//----------------------------------------------------------------------------
VOID
ReleaseWriteLock(
PREAD_WRITE_LOCK pRWL
) {
pRWL->RWL_ReaderCount = 0;
LeaveCriticalSection(&(pRWL)->RWL_ReadWriteBlock);
}