diff --git a/xtoskrnl/includes/mm.hh b/xtoskrnl/includes/mm.hh index 01ead47..1e3e841 100644 --- a/xtoskrnl/includes/mm.hh +++ b/xtoskrnl/includes/mm.hh @@ -17,6 +17,7 @@ #include #include +#include #include #include #include diff --git a/xtoskrnl/includes/mm/guard.hh b/xtoskrnl/includes/mm/guard.hh new file mode 100644 index 0000000..fce49a1 --- /dev/null +++ b/xtoskrnl/includes/mm/guard.hh @@ -0,0 +1,88 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/includes/mm/guard.hh + * DESCRIPTION: Memory Manager synchronization guard + * DEVELOPERS: Aiken Harris + */ + +#ifndef __XTOSKRNL_MM_GUARD_HH +#define __XTOSKRNL_MM_GUARD_HH + +#include +#include +#include + + +/* Memory Manager */ +namespace MM +{ + class PoolLockGuard + { + private: + BOOLEAN Locked; + MMPOOL_TYPE LockPoolType; + KRUNLEVEL PreviousRunLevel; + + public: + PoolLockGuard(IN MMPOOL_TYPE PoolType) + { + LockPoolType = PoolType; + + /* Determine the appropriate synchronization mechanism based on the requested pool type */ + if(LockPoolType == NonPagedPool) + { + /* Elevate the runlevel to DISPATCH_LEVEL */ + PreviousRunLevel = KE::RunLevel::RaiseRunLevel(DISPATCH_LEVEL); + + /* Acquire the global queued spinlock protecting the non-paged pool */ + KE::SpinLock::AcquireQueuedSpinLock(NonPagedPoolLock); + } + else + { + /* Paged pool requires a mutex, currently unimplemented */ + UNIMPLEMENTED; + } + + /* Mark the guard as actively holding the lock */ + Locked = TRUE; + } + + ~PoolLockGuard(VOID) + { + /* Automatically release the held lock upon going out of scope */ + Release(); + } + + PoolLockGuard(const PoolLockGuard&) = delete; + PoolLockGuard& operator=(const PoolLockGuard&) = delete; + + VOID Release(VOID) + { + /* Check if the guard is currently holding a lock */ + if(!Locked) + { + /* Return, to prevent a double-free */ + return; + } + + /* Determine the appropriate synchronization mechanism based on the requested pool type */ + if(LockPoolType == NonPagedPool) + { + /* Release the non-paged pool spinlock and subsequently restore the original runlevel */ + KE::SpinLock::ReleaseQueuedSpinLock(NonPagedPoolLock); + KE::RunLevel::LowerRunLevel(PreviousRunLevel); + } + else + { + /* Paged pool requires a mutex, currently unimplemented */ + UNIMPLEMENTED; + } + + /* Update the internal state, indicating that the lock is no longer held */ + Locked = FALSE; + } + }; +} + +#endif /* __XTOSKRNL_MM_GUARD_HH */