224 lines
4.9 KiB
C++
224 lines
4.9 KiB
C++
//+-------------------------------------------------------------------------
|
||
//
|
||
// Microsoft Windows
|
||
//
|
||
// Copyright (C) Microsoft Corporation, 1990 - 1999
|
||
//
|
||
// File: mutex.cxx
|
||
//
|
||
//--------------------------------------------------------------------------
|
||
|
||
/* --------------------------------------------------------------------
|
||
|
||
Microsoft OS/2 LAN Manager
|
||
Copyright(c) Microsoft Corp., 1990
|
||
|
||
-------------------------------------------------------------------- */
|
||
/* --------------------------------------------------------------------
|
||
|
||
File: mutex.cxx
|
||
|
||
Description:
|
||
|
||
This file contains the system independent mutex class for NT.
|
||
|
||
History:
|
||
|
||
mikemon ??-??-?? The beginning.
|
||
mikemon 12-31-90 Upgraded the comments.
|
||
|
||
-------------------------------------------------------------------- */
|
||
|
||
#include <precomp.hxx>
|
||
|
||
|
||
void
|
||
MUTEX::CommonConstructor (
|
||
OUT RPC_STATUS PAPI * RpcStatus,
|
||
IN DWORD dwSpinCount
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
We construct a mutex in this routine; the only interesting part is that
|
||
we need to be able to return a success or failure status.
|
||
|
||
Arguments:
|
||
|
||
RpcStatus - Returns either RPC_S_OK or RPC_S_OUT_OF_MEMORY.
|
||
|
||
--*/
|
||
{
|
||
CriticalSection.DebugInfo = 0;
|
||
|
||
if ( *RpcStatus == RPC_S_OK )
|
||
{
|
||
if ( NT_SUCCESS(RtlInitializeCriticalSectionAndSpinCount(&CriticalSection, dwSpinCount)) )
|
||
{
|
||
*RpcStatus = RPC_S_OK;
|
||
}
|
||
else
|
||
{
|
||
*RpcStatus = RPC_S_OUT_OF_MEMORY;
|
||
}
|
||
}
|
||
|
||
#ifdef NO_RECURSIVE_MUTEXES
|
||
RecursionCount = 0;
|
||
#endif // NO_RECURSIVE_MUTEXES
|
||
}
|
||
|
||
|
||
void MUTEX::Free(void)
|
||
{
|
||
NTSTATUS NtStatus;
|
||
|
||
if ( IsSuccessfullyInitialized() )
|
||
{
|
||
NtStatus = RtlDeleteCriticalSection(&CriticalSection);
|
||
ASSERT(NT_SUCCESS(NtStatus));
|
||
}
|
||
}
|
||
|
||
#ifdef DEBUGRPC
|
||
|
||
void
|
||
MUTEX::EnumOwnedCriticalSections()
|
||
{
|
||
CRITICAL_SECTION_DEBUG * DebugInfo;
|
||
|
||
return;
|
||
|
||
HANDLE MyThreadId = ULongToPtr(GetCurrentThreadId());
|
||
DWORD Count = NtCurrentTeb()->CountOfOwnedCriticalSections;
|
||
|
||
// if (!Count)
|
||
// {
|
||
// DbgPrint("thread %x: taking %x\n", &CriticalSection);
|
||
// return;
|
||
// }
|
||
|
||
DbgPrint("thread %x owns the following %d critical section(s):\n",
|
||
MyThreadId, Count
|
||
);
|
||
|
||
DebugInfo = CriticalSection.DebugInfo;
|
||
|
||
BOOL Found = FALSE;
|
||
|
||
for (;;)
|
||
{
|
||
DebugInfo = CONTAINING_RECORD( DebugInfo->ProcessLocksList.Flink,
|
||
RTL_CRITICAL_SECTION_DEBUG,
|
||
ProcessLocksList
|
||
);
|
||
|
||
if (!DebugInfo->ProcessLocksList.Flink)
|
||
{
|
||
// DbgPrint("null forward link\n");
|
||
break;
|
||
}
|
||
|
||
if (DebugInfo->ProcessLocksList.Flink == &CriticalSection.DebugInfo->ProcessLocksList)
|
||
{
|
||
// DbgPrint("circular list complete\n");
|
||
break;
|
||
}
|
||
|
||
// DbgPrint("mutex %x owner %x\n",
|
||
// DebugInfo->CriticalSection,
|
||
// DebugInfo->CriticalSection
|
||
// ? DebugInfo->CriticalSection->OwningThread
|
||
// : 0
|
||
// );
|
||
|
||
if (DebugInfo->CriticalSection &&
|
||
DebugInfo->CriticalSection->OwningThread == MyThreadId)
|
||
{
|
||
DbgPrint(" %x\n", DebugInfo->CriticalSection);
|
||
Found = TRUE;
|
||
}
|
||
}
|
||
|
||
if (Found)
|
||
{
|
||
DbgPrint("and is taking %x\n", &CriticalSection);
|
||
DbgBreakPoint();
|
||
}
|
||
}
|
||
|
||
#endif // DEBUG
|
||
|
||
|
||
void
|
||
MUTEX3::Request()
|
||
{
|
||
if (guard.Increment() > 0)
|
||
{
|
||
if (owner == GetCurrentThreadId())
|
||
{
|
||
guard.Decrement();
|
||
|
||
ASSERT(guard.GetInteger() >= 0);
|
||
|
||
recursion++;
|
||
return;
|
||
}
|
||
|
||
event.Wait();
|
||
|
||
ASSERT(guard.GetInteger() >= 0);
|
||
}
|
||
|
||
ASSERT(owner == 0);
|
||
ASSERT(recursion == 0);
|
||
|
||
owner = GetCurrentThreadId();
|
||
recursion = 1;
|
||
return;
|
||
}
|
||
|
||
|
||
void
|
||
MUTEX3::Clear()
|
||
{
|
||
ASSERT(owner == GetCurrentThreadId());
|
||
ASSERT(recursion > 0);
|
||
|
||
if ( --recursion > 0)
|
||
{
|
||
return;
|
||
}
|
||
|
||
owner = 0;
|
||
|
||
if (guard.Decrement() >= 0)
|
||
{
|
||
event.Raise();
|
||
}
|
||
}
|
||
|
||
BOOL
|
||
MUTEX3::TryRequest()
|
||
{
|
||
if (guard.CompareExchange(0, -1) == -1)
|
||
{
|
||
// Lock wasn't owned, now we own it.
|
||
owner = GetCurrentThreadId();
|
||
recursion = 1;
|
||
return TRUE;
|
||
}
|
||
|
||
if (owner == GetCurrentThreadId())
|
||
{
|
||
// We can aquire it recursivly, just increment the count
|
||
recursion++;
|
||
return TRUE;
|
||
}
|
||
|
||
// Owned by another thread
|
||
|
||
return FALSE;
|
||
}
|