1.fastlock 在没有竞争且是独占类型时,比临界区大约快7%,却比临界区占用内存更小
2.fastlock 是通过原子操作,计算标志位,实现独占、共享或者等待的
3.利用自旋锁实现快速同步。(不推荐)
4.利用信号量实现等待同步。
源码如下,注释在源码中。
// FastLock is a port of FastResourceLock from PH 1.x.
//
// The code contains no comments because it is a direct port. Please see FastResourceLock.cs in PH
// 1.x for details.
// The fast lock is around 7% faster than the critical section when there is no contention, when
// used solely for mutual exclusion. It is also much smaller than the critical section.
#define PH_LOCK_OWNED 0x1 //拥有锁标志位
#define PH_LOCK_EXCLUSIVE_WAKING 0x2 //独占正在唤醒标志位
#define PH_LOCK_SHARED_OWNERS_SHIFT 2 //共享标志位
#define PH_LOCK_SHARED_OWNERS_MASK 0x3ff //共享最大拥有数
#define PH_LOCK_SHARED_OWNERS_INC 0x4 //共享每次加的数值
#define PH_LOCK_SHARED_WAITERS_SHIFT 12 //共享等待
#define PH_LOCK_SHARED_WAITERS_MASK 0x3ff //共享最大拥有数
#define PH_LOCK_SHARED_WAITERS_INC 0x1000 //共享每次加的数值
#define PH_LOCK_EXCLUSIVE_WAITERS_SHIFT 22
#define PH_LOCK_EXCLUSIVE_WAITERS_MASK 0x3ff
#define PH_LOCK_EXCLUSIVE_WAITERS_INC 0x400000
//FFC0 0002
#define PH_LOCK_EXCLUSIVE_MASK \
(PH_LOCK_EXCLUSIVE_WAKING | \
(PH_LOCK_EXCLUSIVE_WAITERS_MASK << PH_LOCK_EXCLUSIVE_WAITERS_SHIFT))
VOID NTAPI PhInitializeFastLock(
_Out_ PPH_FAST_LOCK FastLock
)
{
FastLock->Value = 0;
FastLock->ExclusiveWakeEvent = NULL;
FastLock->SharedWakeEvent = NULL;
}
VOID NTAPI PhDeleteFastLock(
_Inout_ PPH_FAST_LOCK FastLock
)
{
if (FastLock->ExclusiveWakeEvent)
{
NtClose(FastLock->ExclusiveWakeEvent);
FastLock->ExclusiveWakeEvent = NULL;
}
if (FastLock->SharedWakeEvent)
{
NtClose(FastLock->SharedWakeEvent);
FastLock->SharedWakeEvent = NULL;
}
}
FORCEINLINE VOID PhpEnsureEventCreated(
_Inout_ PHANDLE Handle
)
{
HANDLE handle;
if (*Handle != NULL)
return;
//创建等待信号量
NtCreateSemaphore(&handle, SEMAPHORE_ALL_ACCESS, NULL, 0, MAXLONG);
if (_InterlockedCompareExchangePointer(
Handle,
handle,
NULL
) != NULL)
{
NtClose(handle);
}
}
FORCEINLINE ULONG PhpGetSpinCount(
VOID
)
{
//NumberOfProcessors 表示CPU的数量,可主动获取
ULONG NumberOfProcessors = 8;
if ((ULONG)NumberOfProcessors > 1)
return 4000;
else
return 0;
}
_May_raise_
_Acquires_exclusive_lock_(*FastLock)
VOID FASTCALL PhfAcquireFastLockExclusive(
_Inout_ PPH_FAST_LOCK FastLock
)
{
ULONG value;
ULONG i = 0;
ULONG spinCount;
spinCount = PhpGetSpinCount();
while (TRUE)
{
value = FastLock->Value;
if (!(value & (PH_LOCK_OWNED | PH_LOCK_EXCLUSIVE_WAKING)))
{//锁没有被占有,且不是独占唤醒等待,则直接获取该锁
if (_InterlockedCompareExchange(
&FastLock->Value,
value + PH_LOCK_OWNED,
value
) == value)
break;
}
else if (i >= spinCount)
{//大于自旋次数后,创建信号量等待
PhpEnsureEventCreated(&FastLock->ExclusiveWakeEvent);
//独占锁被占有,将锁FastLock->Value 赋值为PH_LOCK_EXCLUSIVE_WAITERS_INC(独占等待标志位)
if (_InterlockedCompareExchange(
&FastLock->Value,
value + PH_LOCK_EXCLUSIVE_WAITERS_INC,
value
) == value)
{//直到等到PhReleaseFastLockExclusive 释放
if (NtWaitForSingleObject(
FastLock->ExclusiveWakeEvent,
FALSE,
NULL
) != STATUS_WAIT_0)
PhRaiseStatus(STATUS_UNSUCCESSFUL);
//获得信号量后,将FastLock->Value 去除PH_LOCK_EXCLUSIVE_WAKING(独占唤醒标志位),并加上PH_LOCK_OWNED,表示占有该锁
do
{
value = FastLock->Value;
} while (_InterlockedCompareExchange(
&FastLock->Value,
value + PH_LOCK_OWNED - PH_LOCK_EXCLUSIVE_WAKING,
value
) != value);
break;
}
}
i++;
YieldProcessor(); //直接自旋
}
}
_May_raise_
_Acquires_shared_lock_(*FastLock)
VOID FASTCALL PhfAcquireFastLockShared(
_Inout_ PPH_FAST_LOCK FastLock
)
{
ULONG value;
ULONG i = 0;
ULONG spinCount;
spinCount = PhpGetSpinCount();
while (TRUE)
{
value = FastLock->Value;
if (!(value & (
PH_LOCK_OWNED |
(PH_LOCK_SHARED_OWNERS_MASK << PH_LOCK_SHARED_OWNERS_SHIFT) |
PH_LOCK_EXCLUSIVE_MASK
)))
{//锁没有被占者,没有达到最大值,且不是独占类型,
//则直接将FastLock->Value 赋值 PH_LOCK_OWNED,表示占有该锁,并将共享值+PH_LOCK_SHARED_OWNERS_INC(一个共享者)
if (_InterlockedCompareExchange(
&FastLock->Value,
value + PH_LOCK_OWNED + PH_LOCK_SHARED_OWNERS_INC,
value
) == value)
break;
}
else if (
(value & PH_LOCK_OWNED) &&
((value >> PH_LOCK_SHARED_OWNERS_SHIFT) & PH_LOCK_SHARED_OWNERS_MASK) > 0 &&
!(value & PH_LOCK_EXCLUSIVE_MASK)
)
{//如果锁被占用且共享没有达到最大值,且非独占锁,则直接加 PH_LOCK_SHARED_OWNERS_INC(加一个共享者)
if (_InterlockedCompareExchange(
&FastLock->Value,
value + PH_LOCK_SHARED_OWNERS_INC,
value
) == value)
break;
}
else if (i >= spinCount)
{
//创建共享信号量等待
PhpEnsureEventCreated(&FastLock->SharedWakeEvent);
//将FastLock->Value 标志位设置为共享等待(+PH_LOCK_SHARED_WAITERS_INC)
if (_InterlockedCompareExchange(
&FastLock->Value,
value + PH_LOCK_SHARED_WAITERS_INC,
value
) == value)
{
if (NtWaitForSingleObject(
FastLock->SharedWakeEvent,
FALSE,
NULL
) != STATUS_WAIT_0)
PhRaiseStatus(STATUS_UNSUCCESSFUL);
continue;
}
}
i++;
YieldProcessor();
}
}
_Releases_exclusive_lock_(*FastLock)
VOID FASTCALL PhfReleaseFastLockExclusive(
_Inout_ PPH_FAST_LOCK FastLock
)
{
ULONG value;
while (TRUE)
{
value = FastLock->Value;
//判断是否独占且等待状态
//PhAcquireFastLockExclusive 将value 加上了 PH_LOCK_EXCLUSIVE_WAITERS_INC值,表示独占等待
//所以需要value >>PH_LOCK_EXCLUSIVE_WAITERS_SHIFT在与PH_LOCK_EXCLUSIVE_WAITERS_MASK
if ((value >> PH_LOCK_EXCLUSIVE_WAITERS_SHIFT) & PH_LOCK_EXCLUSIVE_WAITERS_MASK)
{//独占等待,则将FastLock->Value-PH_LOCK_EXCLUSIVE_WAITERS_INC-PH_LOCK_OWNED,表示去除等待状态释放该锁,
//并将赋值PH_LOCK_EXCLUSIVE_WAKING 等待唤醒状态
if (_InterlockedCompareExchange(
&FastLock->Value,
value - PH_LOCK_OWNED + PH_LOCK_EXCLUSIVE_WAKING - PH_LOCK_EXCLUSIVE_WAITERS_INC,
value
) == value)
{
NtReleaseSemaphore(FastLock->ExclusiveWakeEvent, 1, NULL);
break;
}
}
else
{
ULONG sharedWaiters;
//如果是共享等待,计算有多少等待者
sharedWaiters = (value >> PH_LOCK_SHARED_WAITERS_SHIFT) & PH_LOCK_SHARED_WAITERS_MASK;
//去除共享等待标志,并释放该锁标志(PH_LOCK_OWNED)
if (_InterlockedCompareExchange(
&FastLock->Value,
value & ~(PH_LOCK_OWNED | (PH_LOCK_SHARED_WAITERS_MASK << PH_LOCK_SHARED_WAITERS_SHIFT)),
value
) == value)
{
//释放拥有者数据
if (sharedWaiters)
NtReleaseSemaphore(FastLock->SharedWakeEvent, sharedWaiters, 0);
break;
}
}
YieldProcessor();
}
}
_Releases_shared_lock_(*FastLock)
VOID FASTCALL PhfReleaseFastLockShared(
_Inout_ PPH_FAST_LOCK FastLock
)
{
ULONG value;
while (TRUE)
{
value = FastLock->Value;
if (((value >> PH_LOCK_SHARED_OWNERS_SHIFT) & PH_LOCK_SHARED_OWNERS_MASK) > 1)
{//没有达到最大值,锁被占用,直接减一个共享者(value - PH_LOCK_SHARED_OWNERS_INC)
if (_InterlockedCompareExchange(
&FastLock->Value,
value - PH_LOCK_SHARED_OWNERS_INC,
value
) == value)
break;
}
else if ((value >> PH_LOCK_EXCLUSIVE_WAITERS_SHIFT) & PH_LOCK_EXCLUSIVE_WAITERS_MASK)
{//独占等待类型
if (_InterlockedCompareExchange(
&FastLock->Value,
value - PH_LOCK_OWNED + PH_LOCK_EXCLUSIVE_WAKING -
PH_LOCK_SHARED_OWNERS_INC - PH_LOCK_EXCLUSIVE_WAITERS_INC,
value
) == value)
{
NtReleaseSemaphore(FastLock->ExclusiveWakeEvent, 1, NULL);
break;
}
}
else
{//最后一个占有者,去除占有标志,减一个共享者
if (_InterlockedCompareExchange(
&FastLock->Value,
value - PH_LOCK_OWNED - PH_LOCK_SHARED_OWNERS_INC,
value
) == value)
break;
}
YieldProcessor();
}
}
_When_(return != 0, _Acquires_exclusive_lock_(*FastLock))
BOOLEAN FASTCALL PhfTryAcquireFastLockExclusive(
_Inout_ PPH_FAST_LOCK FastLock
)
{
ULONG value;
value = FastLock->Value;
if (value & (PH_LOCK_OWNED | PH_LOCK_EXCLUSIVE_WAKING))
return FALSE;
return _InterlockedCompareExchange(
&FastLock->Value,
value + PH_LOCK_OWNED,
value
) == value;
}
_When_(return != 0, _Acquires_shared_lock_(*FastLock))
BOOLEAN FASTCALL PhfTryAcquireFastLockShared(
_Inout_ PPH_FAST_LOCK FastLock
)
{
ULONG value;
value = FastLock->Value;
if (value & PH_LOCK_EXCLUSIVE_MASK)
return FALSE;
if (!(value & PH_LOCK_OWNED))
{
return _InterlockedCompareExchange(
&FastLock->Value,
value + PH_LOCK_OWNED + PH_LOCK_SHARED_OWNERS_INC,
value
) == value;
}
else if ((value >> PH_LOCK_SHARED_OWNERS_SHIFT) & PH_LOCK_SHARED_OWNERS_MASK)
{
return _InterlockedCompareExchange(
&FastLock->Value,
value + PH_LOCK_SHARED_OWNERS_INC,
value
) == value;
}
else
{
return FALSE;
}
}