301 lines
4.9 KiB
C
301 lines
4.9 KiB
C
|
/*++
|
|||
|
|
|||
|
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 bwr = FALSE;
|
|||
|
BOOL retval = FALSE;
|
|||
|
|
|||
|
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);
|
|||
|
bwr = InitializeCriticalSectionAndSpinCount(&psr->WriterMutex,
|
|||
|
0x80001000);
|
|||
|
|
|||
|
}
|
|||
|
__finally {
|
|||
|
|
|||
|
if (brr && bwr) {
|
|||
|
retval = TRUE;
|
|||
|
psr->Valid = TRUE;
|
|||
|
}
|
|||
|
else {
|
|||
|
if (brr)
|
|||
|
DeleteCriticalSection(&psr->ReaderMutex);
|
|||
|
if (bwr)
|
|||
|
DeleteCriticalSection(&psr->WriterMutex);
|
|||
|
|
|||
|
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)
|
|||
|
EnterCriticalSection(&psr->WriterMutex);
|
|||
|
|
|||
|
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)
|
|||
|
LeaveCriticalSection(&psr->WriterMutex);
|
|||
|
|
|||
|
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);
|
|||
|
|
|||
|
EnterCriticalSection(&psr->WriterMutex);
|
|||
|
|
|||
|
ASSERT(psr->Readers == 0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
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);
|
|||
|
ASSERT(psr->Readers == 0);
|
|||
|
|
|||
|
LeaveCriticalSection(&psr->WriterMutex);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
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);
|
|||
|
DeleteCriticalSection(&psr->WriterMutex);
|
|||
|
|
|||
|
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);
|
|||
|
}
|
|||
|
|