alcyone/NTOSKRNL/KE/mutex.cpp
Dibyamartanda Samanta 67ee8f85ce
[NTOSKRNL:KE] Implement Mutex
*Initial Structure for  Fast  Mutexes in NT Kernel 
*Implemented some directives
Todo:
* Implement All Fast and Guarded Mutex Functions present in NT10 and Exclusive to Alcyone
2024-07-30 19:33:48 +02:00

134 lines
3.1 KiB
C++

/*
* PROJECT: Alcyone System Kernel
* LICENSE: BSD Clause 3
* PURPOSE: Mutexes
* NT KERNEL: 5.11.9360
* COPYRIGHT: 2023-2029 Dibymartanda Samanta <>
*/
#include <ntoskrnl.h>
#define NTDEBUG
extern "C"
/*Mutex Count :
0 => Can Be aquired,
1 => Is Aquired by a Thread
In Negative Indigates, Number of Threads waiting*/
constexpr ULONG MUTEX_READY_TO_BE_AQUIRED = 0;
/*Internal Function*/
typedef struct _FAST_MUTEX
{
LONG Count; //0x0
VOID* Owner; //0x4
ULONG Contention; //0x8
struct _KEVENT Event; //0xc
ULONG OldIrql; //0x1c
} FAST_MUTEX, *PFAST_MUTEX; //0x20 bytes (sizeof)
/*Internal Functio*/
VOID
FASTCALL
KiAcquireFastMutex(
_Inout_ PFAST_MUTEX Mutex
)
{
LONG AcquireMarker;
LONG AcquireBit;
LONG OldCount;
PAGED_CODE();
/* Increment contention count */
InterlockedIncrement(&Mutex->Contention);
/* Initialize loop variables */
AcquireMarker = 4;
AcquireBit = 1;
AcquireLoop:
while(true)
{
/* Read current count */
OldCount = ReadForWriteAccess(&Mutex->Count);
/* Check if mutex is free */
if ((OldCount & 1) == 0)
{
/* Attempt to acquire by incrementing count */
if (InterlockedCompareExchange(&Mutex->Count, OldCount + AcquireMarker,OldCount) == OldCount)
{
/* Wait for the mutex event */
KeWaitForSingleObject(&Mutex->Event,WrFastMutex,KernelMode,false,0);
AcquireMarker = 2;
AcquireBit = 3;
goto AcquireLoop;
}
}
else
{
/* Attempt to mark mutex as owned */
if (InterlockedCompareExchange(&Mutex->Count, AcquireBit ^ OldCount,OldCount) == OldCount)
{
/* Mutex acquired successfully */
break;
}
}
}
}
/* Exported Function */
VOID
NTAPI
KeInitializeFastMutex(
_Out_ PFAST_MUTEX Mutex
)
{
PAGED_CODE();
/* Initialize the mutex structure */
RtlZeroMemory(Mutex, sizeof(FAST_MUTEX));
/* Set initial values */
Mutex->Owner = nullptr;
Mutex->Contention = 0;
Mutex->Count = 1;
/* Initialize the Mutex Gate */
KeInitializeEvent(&Mutex->Event, SynchronizationEvent, FALSE);
}
BOOLEAN
VECTORCALL
KeTryToAcquireFastMutex(
_Inout_ PFAST_MUTEX Mutex)
{
KIRQL CurrentIrql = KeGetCurrentIrql();
BOOLEAN Result = false;
if(_InterlockedBitTestAndReset(&FastMutex->Count, MUTEX_READY_TO_BE_AQUIRED))
{
FastMutex->Owner = (PVOID)KeGetCurrentThread();
Mutex->OldIrql = KeRaiseIrql(APC_LEVEL);
Result = TRUE;
}
else
{
/* Failed to acquire the mutex */
KeLowerIrql(CurrentIrql);
KeYieldProcessor();
Result = FALSE;
}
return Result;
}