alcyone/NTOSKRNL/KE/threadawarespin.cpp
Dibyamartanda Samanta 3d6aa09be1 [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,
2024-07-20 18:15:15 +02:00

145 lines
3.1 KiB
C++

/*
* 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();
}
}