|
|
/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
synch.c
Abstract:
This module contains routines for shared reader/writer locks for Session Directory. These reader/writer locks can starve writers, so the assumption is that there is not a lot of constant reading activity.
Author:
Trevor Foucher (trevorfo) 01-Feb-2001
Environment: User mode.
Revision History:
01-Feb-2001 trevorfo Created
--*/
#include "synch.h"
#if DBG
NTSYSAPI VOID NTAPI RtlAssert( PVOID FailedAssertion, PVOID FileName, ULONG LineNumber, PCHAR Message );
#define ASSERT( exp ) \
((!(exp)) ? \ (RtlAssert( #exp, __FILE__, __LINE__, NULL ),FALSE) : \ TRUE) #else
#define ASSERT( exp ) ((void) 0)
#endif
BOOL InitializeSharedResource( IN OUT PSHAREDRESOURCE psr )
/*++
Routine Description:
This routine initializes a shared resource object. Call FreeSharedResource to free.
Arguments:
psr - Pointer to SHAREDRESOURCE to initialize. Must point to a valid block of memory, and the psr->Valid field must be FALSE.
Return Value:
TRUE if the function succeeds, FALSE if it fails.
--*/ { BOOL brr = FALSE; BOOL retval = FALSE; HANDLE hSemaphore = NULL;
ASSERT(!IsBadReadPtr(psr, sizeof(psr))); ASSERT(psr->Valid == FALSE); // Initialize Reader Mutex, Writer Mutex.
__try {
// Initialize the critical section to preallocate the event
// and spin 4096 times on each try (since we don't spend very
// long in our critical section).
brr = InitializeCriticalSectionAndSpinCount(&psr->ReaderMutex, 0x80001000); // Create a semaphore with maximum count as 1, which means
// that only one thread can own it
hSemaphore = psr->WriterSemaphore = CreateSemaphore(NULL, 1, 1, NULL);
} __finally {
if (brr && hSemaphore) { retval = TRUE; psr->Valid = TRUE; } else { if (brr) DeleteCriticalSection(&psr->ReaderMutex); if (hSemaphore) CloseHandle(psr->WriterSemaphore);
psr->Valid = FALSE; } }
// Initialize Readers
psr->Readers = 0;
return retval; }
VOID AcquireResourceShared( IN PSHAREDRESOURCE psr ) /*++
Routine Description:
This routine acquires a resource for shared access. Arguments:
psr - Pointer to SHAREDRESOURCE which has been initialized.
Return Value:
None.
--*/ { ASSERT(psr->Valid); EnterCriticalSection(&psr->ReaderMutex);
psr->Readers += 1;
if (psr->Readers == 1) WaitForSingleObject(psr->WriterSemaphore, INFINITE);
LeaveCriticalSection(&psr->ReaderMutex); }
VOID ReleaseResourceShared( IN PSHAREDRESOURCE psr ) /*++
Routine Description:
This routine releases a resource's shared access. Arguments:
psr - Pointer to SHAREDRESOURCE which has been initialized and which has shared (read) access.
Return Value:
None.
--*/ { ASSERT(psr->Valid);
EnterCriticalSection(&psr->ReaderMutex);
ASSERT(psr->Readers != 0);
psr->Readers -= 1;
if (psr->Readers == 0) ReleaseSemaphore(psr->WriterSemaphore, 1, NULL);
LeaveCriticalSection(&psr->ReaderMutex); }
VOID AcquireResourceExclusive( IN PSHAREDRESOURCE psr ) /*++
Routine Description: This routine acquires a resource for exclusive (write) access.
Arguments:
psr - Pointer to SHAREDRESOURCE which has been initialized.
Return Value:
None.
--*/ { ASSERT(psr->Valid);
WaitForSingleObject(psr->WriterSemaphore, INFINITE); }
VOID ReleaseResourceExclusive( IN PSHAREDRESOURCE psr ) /*++
Routine Description: This routine releases a resource for which we have exclusive (write) access.
Arguments:
psr - Pointer to SHAREDRESOURCE which has been initialized and which has write access.
Return Value:
None.
--*/ { ASSERT(psr->Valid);
ReleaseSemaphore(psr->WriterSemaphore, 1, NULL); }
VOID FreeSharedResource( IN OUT PSHAREDRESOURCE psr ) /*++
Routine Description:
This routine frees resources taken up by a shared resource object allocated by InitializeSharedResource. It does not free the memory. Arguments:
psr - Pointer to SHAREDRESOURCE whose resources should be freed.
Return Value:
None.
--*/ { ASSERT(psr->Valid); ASSERT(psr->Readers == 0);
DeleteCriticalSection(&psr->ReaderMutex); CloseHandle(psr->WriterSemaphore); psr->Readers = 0; psr->Valid = FALSE; }
BOOL VerifyNoSharedAccess( IN PSHAREDRESOURCE psr ) /*++
Routine Description:
This routine verifies that the critical section does not currently have any shared accessors.
Arugments:
psr - Pointer to SHAREDRESOURCE to verify.
Return Value:
TRUE - if there are no shared accessors. FALSE - if there are shared accessors.
--*/ { ASSERT(psr->Valid); return (psr->Readers == 0); }
|