From aa548ba47347a67ff64a38dc842f9d0d5d6bf364 Mon Sep 17 00:00:00 2001 From: zer0condition Date: Sun, 22 Mar 2026 19:56:35 +0530 Subject: [KernelKit] scheduler sleep tracking + mutex priority inheritance - add STime field to UserProcess for tracking sleep/blocked time - boost PTime proportionally when process wakes from sleep (interactive boost) - implement priority inheritance in BinaryMutex to prevent priority inversion - fix broken Unlock() that was spinning waiting for process status change - fix LockAndWait() that was locking then immediately unlocking Co-Authored-By: Claude Opus 4.6 --- src/kernel/KernelKit/BinaryMutex.h | 3 ++ src/kernel/KernelKit/UserProcessScheduler.h | 5 ++-- src/kernel/src/BinaryMutex.cpp | 45 +++++++++++++++++------------ src/kernel/src/UserProcessScheduler.cpp | 15 ++++++++++ 4 files changed, 47 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/kernel/KernelKit/BinaryMutex.h b/src/kernel/KernelKit/BinaryMutex.h index 2fb390d3..d97ab854 100644 --- a/src/kernel/KernelKit/BinaryMutex.h +++ b/src/kernel/KernelKit/BinaryMutex.h @@ -8,12 +8,14 @@ #include #include +#include #include namespace Kernel { class UserProcess; /// @brief Access control class, which locks a task until one is done. +/// Implements priority inheritance to prevent priority inversion. class BinaryMutex final { public: using LockedPtr = UserProcess*; @@ -37,6 +39,7 @@ class BinaryMutex final { private: LockedPtr fLockingProcess{nullptr}; + AffinityKind fOwnerOriginalAffinity{AffinityKind::kInvalid}; // for priority inheritance }; } // namespace Kernel diff --git a/src/kernel/KernelKit/UserProcessScheduler.h b/src/kernel/KernelKit/UserProcessScheduler.h index 5018f1f6..8c7a4afa 100644 --- a/src/kernel/KernelKit/UserProcessScheduler.h +++ b/src/kernel/KernelKit/UserProcessScheduler.h @@ -83,9 +83,10 @@ class UserProcess final { kExecutableKindCount, }; - ProcessTime PTime{0}; //! @brief Process allocated tine. + ProcessTime PTime{0}; //! @brief Process allocated time. ProcessTime RTime{0}; //! @brief Process run time. - ProcessTime UTime{0}; //! #brief Process used time. + ProcessTime UTime{0}; //! @brief Process used time. + ProcessTime STime{0}; //! @brief Process sleep time (for dynamic priority boost). ProcessID ProcessId{kCPSInvalidPID}; ExecutableKind Kind{ExecutableKind::kExecutableKind}; diff --git a/src/kernel/src/BinaryMutex.cpp b/src/kernel/src/BinaryMutex.cpp index c5fd6a50..a83f031a 100644 --- a/src/kernel/src/BinaryMutex.cpp +++ b/src/kernel/src/BinaryMutex.cpp @@ -7,23 +7,15 @@ #include namespace Kernel { -/***********************************************************************************/ -/// @brief Unlocks the binary mutex. -/***********************************************************************************/ - -#ifndef __NE_TIMEOUT_CONFIG__ -#define __NE_TIMEOUT_CONFIG__ 10000 -#endif Bool BinaryMutex::Unlock() { - auto timeout = 0UL; - constexpr auto kTimoutLimit = __NE_TIMEOUT_CONFIG__; + if (!fLockingProcess) + return No; - while (fLockingProcess->Status == ProcessStatusKind::kRunning) { - ++timeout; - - if (timeout > kTimoutLimit) - return No; + // restore original priority if we boosted the owner + if (fOwnerOriginalAffinity != AffinityKind::kInvalid) { + fLockingProcess->Affinity = fOwnerOriginalAffinity; + fOwnerOriginalAffinity = AffinityKind::kInvalid; } fLockingProcess = nullptr; @@ -35,9 +27,20 @@ Bool BinaryMutex::Unlock() { /***********************************************************************************/ Bool BinaryMutex::Lock(BinaryMutex::LockedPtr process) { - if (!process || this->IsLocked()) return No; + if (!process) return No; + + // if already locked, implement priority inheritance + if (this->IsLocked() && fLockingProcess) { + // boost owner to waiter's priority if waiter is higher priority (lower value = higher priority) + if (process->Affinity < fLockingProcess->Affinity) { + fOwnerOriginalAffinity = fLockingProcess->Affinity; + fLockingProcess->Affinity = process->Affinity; + } + return No; // lock not acquired, but owner boosted + } this->fLockingProcess = process; + fOwnerOriginalAffinity = AffinityKind::kInvalid; return Yes; } @@ -51,15 +54,19 @@ Bool BinaryMutex::IsLocked() const { } /***********************************************************************************/ -/// @brief Try lock or wait. +/// @brief Try lock, waiting until timeout if already locked. /***********************************************************************************/ Bool BinaryMutex::LockAndWait(BinaryMutex::LockedPtr process, ITimer* timer) { - if (timer == nullptr) return No; + if (timer == nullptr || !process) return No; + + // try to acquire lock immediately + if (this->Lock(process)) + return Yes; + // wait and retry timer->Wait(); - this->Lock(process); - return this->Unlock(); + return this->Lock(process); } /***********************************************************************************/ diff --git a/src/kernel/src/UserProcessScheduler.cpp b/src/kernel/src/UserProcessScheduler.cpp index 8c048f07..a4b328ac 100644 --- a/src/kernel/src/UserProcessScheduler.cpp +++ b/src/kernel/src/UserProcessScheduler.cpp @@ -406,6 +406,7 @@ ProcessID UserProcessScheduler::Spawn(const Char* name, VoidPtr code, VoidPtr im process.PTime = 0; process.UTime = 0; process.RTime = 0; + process.STime = 0; if (!process.FileTree) { process.FileTree = new ProcessFileTree(); @@ -501,6 +502,16 @@ SizeT UserProcessScheduler::Run() { ++process.UTime; } + //! boost priority for processes that slept (interactive boost) + if (process.STime > 0) { + // the longer it slept, the bigger the boost (capped at kVeryHigh level) + ProcessTime boost = process.STime / 10; + if (boost > (Int32)AffinityKind::kHigh) + boost = (Int32)AffinityKind::kHigh; + process.PTime += boost; + process.STime = 0; // reset sleep counter after boost + } + this->TheCurrentProcess() = process; if (UserProcessHelper::Switch(process.StackFrame, process.ProcessId)) { @@ -520,6 +531,10 @@ SizeT UserProcessScheduler::Run() { } } } else { + //! track sleep time for processes that are blocked/waiting + if (process.Status == ProcessStatusKind::kFrozen) { + ++process.STime; + } ++process.RTime; --process.PTime; } -- cgit v1.2.3