You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
298 lines
5.3 KiB
298 lines
5.3 KiB
/*++
|
|
|
|
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);
|
|
}
|
|
|