Leaked source code of windows server 2003
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.
|
|
/*++
Copyright (c) 2001-2001 Microsoft Corporation
Module Name:
locks.c
Abstract:
Domain Name System (DNS) Library.
Helpful locking routines. These are not DNS specific.
Author:
Jim Gilroy (jamesg) September 2001
Revision History:
--*/
#include "local.h"
// Note: this modules requires only windows.h.
// local.h is included only to allow precompiled header
#include <windows.h>
//
// Init wait spin interval
//
#define CS_PROTECTED_INIT_INTERLOCK_WAIT (5) // 5ms
//
// In progress flag
//
INT g_CsInitInProgress = FALSE;
VOID InitializeCriticalSectionProtected( OUT PCRITICAL_SECTION pCritSec, IN OUT PINT pInitialized ) /*++
Routine Description:
Protected init of CS.
Purpose here is to do dynamic "on-demand" CS init avoiding need to do these in dll load for CS that are not generally used.
Arguments:
pCs -- ptr to CS to init
pInitialized -- addr of init state flag; this flag must be initialized to zero (by loader or dll startup routine).
Return Value:
None
--*/ { //
// protect CS init with interlock
// - first thread through does CS init
// - any others racing, are not released until init
// completes
//
while ( ! *pInitialized ) { if ( InterlockedIncrement( &g_CsInitInProgress ) == 1 ) { if ( !*pInitialized ) { InitializeCriticalSection( pCritSec ); *pInitialized = TRUE; } InterlockedDecrement( &g_CsInitInProgress ); break; }
InterlockedDecrement( &g_CsInitInProgress ); Sleep( CS_PROTECTED_INIT_INTERLOCK_WAIT ); }
//
// implementation note: "StartLocked" feature
//
// considered having a "StartLocked" feature for callers who
// want to follow the CS init with other initialization;
// however the only service we could provide that is different
// than calling EnterCriticalSection() after this function, is
// to make sure the CS init thread gets the lock first;
// but this only protects changes that outcome when two init
// threads are in an extremely close race AND the issue of
// which thread initialized the CS is irrelevant
//
}
//
// Timed lock functions
//
// This is critical section functionality with a time-limited wait.
//
// DCR: timed lock
//
// non-wait locking
// - have a wait count, for faster locking
// - interlock increment coming in,
// problem is would either have to ResetEvent() -- and
// still racing another thread
// or other threads would have to be able to ResetEvent()
// safely
//
// other alternative is have non-auto-reset event
// (global event for all locks or unique if desired for perf)
// everyone waiting releases, and checks their individual locks
// when leaving lock with waiters threads always SetEvent
//
#if 0
typedef struct _TimedLock { HANDLE hEvent; DWORD ThreadId; LONG RecursionCount; DWORD WaitTime; } TIMED_LOCK, *PTIMED_LOCK;
#define TIMED_LOCK_DEFAULT_WAIT (0xf0000000)
#endif
DWORD TimedLock_Initialize( OUT PTIMED_LOCK pTimedLock, IN DWORD DefaultWait ) /*++
Routine Description:
Init timed lock.
Arguments:
pTimedLock -- ptr to timed lock
Return Value:
ERROR_SUCCESS if successful. Error code on failure.
--*/ { HANDLE hevent;
RtlZeroMemory( pTimedLock, sizeof(*pTimedLock) );
//
// event
// - autoreset (satisfies only one waiting thread when signalled)
// - starts signalled (open)
//
hevent = CreateEvent( NULL, // default security
FALSE, // auto-reset
TRUE, // start signalled
NULL // unnamed
); if ( !hevent ) { return GetLastError(); }
pTimedLock->hEvent = hevent;
//
// default wait
//
pTimedLock->WaitTime = DefaultWait;
return NO_ERROR; }
VOID TimedLock_Cleanup( OUT PTIMED_LOCK pTimedLock ) /*++
Routine Description:
Cleanup timed lock.
Arguments:
pTimedLock -- ptr to timed lock
Return Value:
None
--*/ { // close event
if ( pTimedLock->hEvent ) { CloseHandle( pTimedLock->hEvent ); pTimedLock->hEvent = NULL; } }
BOOL TimedLock_Enter( IN OUT PTIMED_LOCK pTimedLock, IN DWORD WaitTime ) /*++
Routine Description:
Timed lock.
Arguments:
pTimedLock -- ptr to timed lock
WaitTime -- time to wait for lock
Return Value:
None
--*/ { DWORD threadId; DWORD result;
//
// check for recursion
//
threadId = GetCurrentThreadId();
if ( pTimedLock->ThreadId == threadId ) { pTimedLock->RecursionCount++; return TRUE; }
//
// if non-wait -- bail
// - special case just to avoid going into wait
// and yielding timeslice
//
if ( WaitTime == 0 ) { return FALSE; }
//
// wait for event to be signalled (open)
//
result = WaitForSingleObject( pTimedLock->hEvent, ( WaitTime != TIMED_LOCK_DEFAULT_WAIT ) ? WaitTime : pTimedLock->WaitTime );
if ( result == WAIT_OBJECT_0 ) { ASSERT( pTimedLock->RecursionCount == 0 ); ASSERT( pTimedLock->ThreadId == 0 ); pTimedLock->RecursionCount = 1; pTimedLock->ThreadId = threadId; return TRUE; }
ASSERT( result == WAIT_TIMEOUT ); return FALSE; }
VOID TimedLock_Leave( IN OUT PTIMED_LOCK pTimedLock ) /*++
Routine Description:
Leave timed lock
Arguments:
pTimedLock -- ptr to timed lock
Return Value:
None
--*/ { //
// validate thread ID
//
// note that with this check, it's then safe to decrement the count
// unchecked because it can never reach zero without thread ID
// being cleared -- barring non-functional manipulation of structure
//
if ( pTimedLock->ThreadId != GetCurrentThreadId() ) { ASSERT( FALSE ); return; } ASSERT( pTimedLock->RecursionCount > 0 );
if ( --(pTimedLock->RecursionCount) == 0 ) { pTimedLock->ThreadId = 0; SetEvent( pTimedLock->hEvent ); } }
//
// End of locks.c
//
|