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.
 
 
 
 
 
 

360 lines
7.7 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
reslock.cxx
Abstract:
Contains methods for RESOURCE_LOCK class
Contents:
RESOURCE_LOCK::Acquire()
RESOURCE_LOCK::Release()
Author:
Richard L Firth (rfirth) 18-Jun-1996
Revision History:
18-Jun-1996 rfirth
Created
--*/
#include <wininetp.h>
//
// class members
//
#ifdef OLD_VERSION
BOOL
RESOURCE_LOCK::Acquire(
IN BOOL bExclusiveMode
)
/*++
Routine Description:
Acquires the resource protected by this lock. Acquires for non-exclusive
(read) or exclusive (write) ownership
Arguments:
bExclusiveMode - TRUE if we are acquiring the resource for exclusive
(write) ownership
Return Value:
BOOL
TRUE - resource is acquired
FALSE - failed to acquire resource (timeout?)
--*/
{
DEBUG_ENTER((DBG_RESLOCK,
Bool,
"RESOURCE_LOCK::Acquire",
"%B",
bExclusiveMode
));
INET_ASSERT(this != NULL);
//INET_ASSERT(IsInitialized());
//INET_ASSERT(IsValid());
if (!IsInitialized()) {
DEBUG_LEAVE(FALSE);
return FALSE;
}
BOOL acquired = TRUE;
//_CritSect.Lock();
if (bExclusiveMode) {
//
// acquired for exclusive ownership (write access). Set the owning
// thread id and wait for the last current reader to release. Note
// that if we're being re-entered, the Lock() has already
// done the work of checking the thread id and updating re-entrancy
// counts, so if its already not zero, we know it must be us
//
++_WriteCount;
if (_ThreadId == 0) {
_ThreadId = GetCurrentThreadId();
#if INET_DEBUG
INET_ASSERT(_ThreadId != _ThreadIdReader);
#endif
acquired = Wait(_hWriteEvent);
_CritSect.Lock();
} else {
INET_ASSERT(_ThreadId == GetCurrentThreadId());
}
} else {
//
// don't allow re-entry if already held for exclusive access
//
INET_ASSERT(_ThreadId == 0);
//
// acquired for non-exclusive ownership (read access). Just increase
// the number of active readers. If this is the first then inhibit the
// writer
//
if (InterlockedIncrement(&_Readers) == 0) {
#if INET_DEBUG
if (_ThreadIdReader == 0) {
_ThreadIdReader = GetCurrentThreadId();
}
#endif
ResetEvent(_hWriteEvent);
}
//
// reader doesn't need to keep hold of critical section
//
//_CritSect.Unlock();
}
DEBUG_LEAVE(acquired);
return acquired;
}
VOID
RESOURCE_LOCK::Release(
VOID
)
/*++
Routine Description:
Releases a resource previously acquired by RESOURCE_LOCK::Acquire()
Arguments:
None.
Return Value:
None.
--*/
{
DEBUG_ENTER((DBG_RESLOCK,
None,
"RESOURCE_LOCK::Release",
NULL
));
INET_ASSERT(this != NULL);
//INET_ASSERT(IsInitialized());
//INET_ASSERT(IsValid());
if (!IsInitialized()) {
DEBUG_LEAVE(0);
return;
}
if ((_ThreadId != 0) && (_ThreadId == GetCurrentThreadId())) {
INET_ASSERT(_WriteCount > 0);
if (--_WriteCount == 0) {
//
// we acquired _hWriteEvent; signal it to allow next writer to continue
//
SetEvent(_hWriteEvent);
//
// this resource no longer owned for exclusive access
//
_ThreadId = 0;
}
_CritSect.Unlock();
} else if (InterlockedDecrement(&_Readers) < 0) {
INET_ASSERT(_Readers >= -1);
//
// we are last currently active reader; allow waiting writer to continue
//
#if INET_DEBUG
if (_ThreadIdReader == GetCurrentThreadId()) {
_ThreadIdReader = 0;
}
#endif
SetEvent(_hWriteEvent);
}
DEBUG_LEAVE(0);
}
#else
BOOL
RESOURCE_LOCK::Acquire(
IN BOOL bExclusiveMode
)
{
DEBUG_ENTER((DBG_RESLOCK,
Bool,
"RESOURCE_LOCK::Acquire",
"%B",
bExclusiveMode
));
BOOL fReturn = TRUE;
if (!IsInitialized()) {
fReturn = FALSE;
goto quit;
}
if (bExclusiveMode) {
do {
DEBUG_PRINT(RESLOCK,
INFO,
("Waiting on WriteEvent\n")
);
if (_ThreadId != GetCurrentThreadId()) {
Wait(_hWriteEvent);
}
if (!_CritSect.Lock())
{
DEBUG_PRINT(RESLOCK,
ERROR,
("Failed to obtain critsec lock after waiting on WriteEvent\n")
);
fReturn = FALSE;
break;
}
INET_ASSERT((_ThreadId == 0) || (_ThreadId == GetCurrentThreadId()));
if ((_Readers == -1)
&& ((_ThreadId == 0) || (_ThreadId == GetCurrentThreadId()))) {
_ThreadId = GetCurrentThreadId();
if (++_WriteCount == 1) {
ResetEvent(_hWriteEvent);
}
break;
}
DEBUG_PRINT(RESLOCK,
INFO,
("trying again\n")
);
_CritSect.Unlock();
} while ( 1 );
} else {
if (_CritSect.Lock()) {
if (++_Readers == 0) {
DEBUG_PRINT(RESLOCK,
INFO,
("Resetting WriteEvent\n")
);
ResetEvent(_hWriteEvent);
}
_CritSect.Unlock();
}
else {
DEBUG_PRINT(RESLOCK,
ERROR,
("Failed to obtain critsec lock after waiting on WriteEvent\n")
);
fReturn = FALSE;
}
}
quit:
DEBUG_LEAVE(fReturn);
return fReturn;
}
VOID
RESOURCE_LOCK::Release(
VOID
)
{
DEBUG_ENTER((DBG_RESLOCK,
None,
"RESOURCE_LOCK::Release",
NULL
));
if (IsInitialized()) {
if (_ThreadId == GetCurrentThreadId()) {
DEBUG_PRINT(RESLOCK,
INFO,
("Clearing writer\n")
);
if (--_WriteCount == 0) {
_ThreadId = 0;
SetEvent(_hWriteEvent);
}
_CritSect.Unlock();
} else {
if (_CritSect.Lock()) {
if (--_Readers == -1) {
DEBUG_PRINT(RESLOCK,
INFO,
("Setting WriteEvent\n")
);
SetEvent(_hWriteEvent);
}
_CritSect.Unlock();
}
else {
DEBUG_PRINT(RESLOCK,
INFO,
("Couldn't set WriteEvent due to not enough memory\n")
);
}
}
}
DEBUG_LEAVE(0);
}
#endif // OLD_VERSION