[NTOSKRNL:KE] Implemented ThreadAware Spinlock
Implemented ThreadAware SpinLock: -> Mechanism to Initialize -> Priority Boost Mechanism -> Lock Acquisition and Removal Mechanism To do: Implement a Algorithm to prevent Priority Inversion in Future,
This commit is contained in:
parent
52f5bb6bd2
commit
3d6aa09be1
144
NTOSKRNL/KE/threadawarespin.cpp
Normal file
144
NTOSKRNL/KE/threadawarespin.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* PROJECT: Alcyone System Kernel
|
||||
* LICENSE: BSD Clause 3
|
||||
* PURPOSE: Thread Aware Spin Lock
|
||||
* NT KERNEL: 5.11.9360
|
||||
* COPYRIGHT: 2023-2029 Dibymartanda Samanta <>
|
||||
*/
|
||||
|
||||
/*
|
||||
Thread Aware Spinlock, designed keeping following things in mind:
|
||||
*
|
||||
*Uses a ticket system (Ticket and Serving counters) to ensure first-come, first-served order
|
||||
*Tracks the current owner of the lock (OwnerThread), ensuring easier debugging of deadlock
|
||||
*Reentrant capability: A thread can "acquire" the lock multiple times if it already owns it, preventing self deadlocking
|
||||
*DeadLock Prevention: Detects and prevents attempts by a thread to re-acquire a lock it already holds, prevent non owning thread from releasing a lock.
|
||||
*
|
||||
*/
|
||||
|
||||
class KeThreadAwareSpinLockImpl
|
||||
{
|
||||
public:
|
||||
volatile LONG Ticket;
|
||||
volatile LONG Serving;
|
||||
PKTHREAD OwnerThread;
|
||||
KPRIORITY OriginalPriority;
|
||||
BOOLEAN IsBoosted;
|
||||
|
||||
KeThreadAwareSpinLockImpl()
|
||||
: Ticket(0), Serving(0), OwnerThread(nullptr),
|
||||
OriginalPriority(0), IsBoosted(FALSE) {}
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
Ticket = 0;
|
||||
Serving = 0;
|
||||
OwnerThread = nullptr;
|
||||
OriginalPriority = 0;
|
||||
IsBoosted = FALSE;
|
||||
}
|
||||
|
||||
void Acquire()
|
||||
{
|
||||
LONG CurrentTicket = {0};
|
||||
PKTHREAD CurrentThread = KeGetCurrentThread();
|
||||
|
||||
if (OwnerThread == CurrentThread)
|
||||
{
|
||||
/* Already owned return the thread */
|
||||
return;
|
||||
}
|
||||
|
||||
CurrentTicket = InterlockedIncrement(&Ticket) - 1;
|
||||
|
||||
while (CurrentTicket != Serving)
|
||||
{
|
||||
YieldProcessor();
|
||||
}
|
||||
|
||||
OwnerThread = CurrentThread;
|
||||
BoostPriority();
|
||||
}
|
||||
|
||||
void Release()
|
||||
{
|
||||
PKTHREAD CurrentThread = KeGetCurrentThread();
|
||||
|
||||
if (OwnerThread != CurrentThread)
|
||||
{
|
||||
ASSERT(FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
RestorePriority();
|
||||
OwnerThread = nullptr;
|
||||
InterlockedIncrement(&Serving);
|
||||
}
|
||||
|
||||
private:
|
||||
void BoostPriority()
|
||||
{
|
||||
if (!IsBoosted)
|
||||
{
|
||||
OriginalPriority = KeGetPriorityThread(OwnerThread);
|
||||
|
||||
/*Boost to the highest priority below real-time range*/
|
||||
KPRIORITY BoostPriority = HIGH_PRIORITY;
|
||||
|
||||
/* Ensure we don't lower the priority if it's already higher*/
|
||||
if (OriginalPriority < BoostPriority)
|
||||
{
|
||||
KeSetPriorityThread(OwnerThread, BoostPriority);
|
||||
IsBoosted = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void RestorePriority()
|
||||
{
|
||||
if (IsBoosted)
|
||||
{
|
||||
KeSetPriorityThread(OwnerThread, OriginalPriority);
|
||||
IsBoosted = FALSE;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef KeThreadAwareSpinLockImpl* PKETHREADAWARESPINLOCK;
|
||||
|
||||
/* Exported Function */
|
||||
VOID
|
||||
NTAPI
|
||||
KeThreadAwareSpinLockInitialize(
|
||||
_Out_ PKETHREADAWARESPINLOCK SpinLock)
|
||||
{
|
||||
if (SpinLock)
|
||||
{
|
||||
SpinLock->Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeThreadAwareSpinLockAcquire(
|
||||
_Inout_ PKETHREADAWARESPINLOCK SpinLock)
|
||||
{
|
||||
if (SpinLock)
|
||||
{
|
||||
SpinLock->Acquire();
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
KeThreadAwareSpinLockRelease(
|
||||
_Inout_ PKETHREADAWARESPINLOCK SpinLock)
|
||||
{
|
||||
if (SpinLock)
|
||||
{
|
||||
SpinLock->Release();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user