/* * PROJECT: Alcyone System Kernel * LICENSE: BSD Clause 3 * PURPOSE: Mutexes * NT KERNEL: 5.11.9360 * COPYRIGHT: 2023-2029 Dibymartanda Samanta <> */ #include #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; }