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.
115 lines
3.0 KiB
115 lines
3.0 KiB
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
win32simplelock.c
|
|
|
|
Abstract:
|
|
|
|
works downlevel to Win95/NT3.
|
|
The only dependencies are InterlocedIncrement, IncrementDecrement, Sleep.
|
|
The old Interlocked semantics are good enough.
|
|
can be statically initialized, but not with all zeros.
|
|
never runs out of memory
|
|
does not wait or boost-upon-exit efficiently.
|
|
must be held for only short periods of time.
|
|
should perhaps be called spinlock
|
|
can be taken recursively.
|
|
can only be taken exclusively, NOT reader/writer.
|
|
acquire has a "SleepCount" parameter:
|
|
0 is like TryEnterCriticalSection
|
|
INFINITE is like EnterCriticalSection
|
|
SHOULD have a spincount to scale hot locks on multiprocs
|
|
|
|
Author:
|
|
|
|
Jay Krell (JayKrell) August 2001
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "windows.h"
|
|
#include "win32simplelock.h"
|
|
|
|
DWORD
|
|
Win32AcquireSimpleLock(PWIN32_SIMPLE_LOCK Lock, DWORD SleepCount)
|
|
{
|
|
DWORD Result = 0;
|
|
BOOL IncrementedWaiters = FALSE;
|
|
// ASSERT(Lock->Size != 0);
|
|
Retry:
|
|
if (InterlockedIncrement(&Lock->Lock) == 0)
|
|
{
|
|
//
|
|
// I got it.
|
|
//
|
|
Lock->OwnerThreadId = GetCurrentThreadId();
|
|
if (Lock->EntryCount == 0)
|
|
{
|
|
Result |= WIN32_ACQUIRE_SIMPLE_LOCK_WAS_FIRST_ACQUIRE;
|
|
}
|
|
if (Lock->EntryCount+1 != 0) /* avoid rollover */
|
|
Lock->EntryCount += 1;
|
|
if (IncrementedWaiters)
|
|
InterlockedDecrement(&Lock->Waiters);
|
|
Result |= WIN32_ACQUIRE_SIMPLE_LOCK_WAS_NOT_RECURSIVE_ACQUIRE;
|
|
return Result;
|
|
}
|
|
else if (Lock->OwnerThreadId == GetCurrentThreadId())
|
|
{
|
|
//
|
|
// I got it recursively.
|
|
//
|
|
Result |= WIN32_ACQUIRE_SIMPLE_LOCK_WAS_RECURSIVE_ACQUIRE;
|
|
return Result;
|
|
}
|
|
InterlockedDecrement(&Lock->Lock);
|
|
if (SleepCount == 0)
|
|
return 0;
|
|
//
|
|
// Someone else has it, wait for them to finish.
|
|
//
|
|
if (!IncrementedWaiters)
|
|
{
|
|
InterlockedIncrement(&Lock->Waiters);
|
|
IncrementedWaiters = TRUE;
|
|
}
|
|
if (SleepCount == INFINITE)
|
|
{
|
|
while (Lock->OwnerThreadId != 0)
|
|
Sleep(0);
|
|
}
|
|
else
|
|
{
|
|
while (Lock->OwnerThreadId != 0 && SleepCount--)
|
|
Sleep(0);
|
|
}
|
|
goto Retry;
|
|
}
|
|
|
|
DWORD
|
|
Win32ReleaseSimpleLock(PWIN32_SIMPLE_LOCK Lock)
|
|
{
|
|
// ASSERT(Lock->Size != 0);
|
|
DWORD Result = 0;
|
|
if (InterlockedDecrement(&Lock->Lock) < 0)
|
|
{
|
|
// I'm done with it (recursively).
|
|
Lock->OwnerThreadId = 0;
|
|
|
|
// Give any waiters a slightly better chance than me.
|
|
// This is "racy", but that's ok.
|
|
if (Lock->Waiters != 0)
|
|
Sleep(0);
|
|
|
|
Result |= WIN32_RELEASE_SIMPLE_LOCK_WAS_NOT_RECURSIVE_RELEASE;
|
|
}
|
|
else
|
|
{
|
|
Result |= WIN32_RELEASE_SIMPLE_LOCK_WAS_RECURSIVE_RELEASE;
|
|
}
|
|
return Result;
|
|
}
|