// Copyright 2024-2026, Amlal El Mahrouss (amlal@nekernel.org) // Licensed under the Apache License, Version 2.0 (see LICENSE file) // Official repository: https://github.com/ne-foss-org/nekernel #ifndef KERNELKIT_COREPROCESSSCHEDULER_H #define KERNELKIT_COREPROCESSSCHEDULER_H #include #include /// @file CoreProcessScheduler.h /// @brief Core Process Scheduler header file. /// @author Amlal El Mahrouss (amlal@nekernel.org) #define kSchedMinMicroTime (AffinityKind::kStandard) #define kSchedInvalidPID (-1) #define kSchedProcessLimitPerTeam (32U) #define kSchedTeamCount (256U) #define kSchedMaxMemoryLimit (gib_cast(128)) /* max physical memory limit */ #define kSchedMaxStackSz (kib_cast(8)) /* maximum stack size */ #define kSchedNameLen (128U) EXTERN_C void sched_idle_task(void); namespace Kernel { class UserProcess; class KernelTask; class KernelTaskScheduler; class UserProcessScheduler; class UserProcessTeam; template struct ProcessHeapTree; template struct ProcessSpecialTree; template struct ProcessFileTree; enum struct TreeKind : UInt32 { kInvalidTreeKind = 0U, kRedTreeKind = 100U, kBlackTreeKind = 101U, kTreeKindCount = 3U, }; template struct ProcessHeapTree final { static constexpr auto kHeap = true; static constexpr auto kFile = false; static constexpr auto kSpecial = false; T Entry{nullptr}; SizeT EntrySize{0UL}; SizeT EntryPad{0UL}; TreeKind Color{TreeKind::kBlackTreeKind}; struct ProcessHeapTree* Parent{nullptr}; struct ProcessHeapTree* Child{nullptr}; struct ProcessHeapTree* Prev{nullptr}; struct ProcessHeapTree* Next{nullptr}; }; template struct ProcessFileTree final { static constexpr auto kHeap = false; static constexpr auto kFile = true; static constexpr auto kSpecial = false; T Entry{nullptr}; SizeT EntrySize{0UL}; SizeT EntryPad{0UL}; TreeKind Color{TreeKind::kBlackTreeKind}; struct ProcessFileTree* Parent{nullptr}; struct ProcessFileTree* Child{nullptr}; struct ProcessFileTree* Prev{nullptr}; struct ProcessFileTree* Next{nullptr}; }; template struct ProcessSpecialTree final { static constexpr auto kHeap = false; static constexpr auto kFile = false; static constexpr auto kSpecial = true; T Entry{nullptr}; SizeT EntrySize{0UL}; SizeT EntryPad{0UL}; /// @brief a context is where the resource comes from. using ProcessCtx = UInt32; /// \note could be a socket, printer, device... ProcessCtx EntryContext{0UL}; TreeKind Color{TreeKind::kBlackTreeKind}; struct ProcessSpecialTree* Parent{nullptr}; struct ProcessSpecialTree* Child{nullptr}; struct ProcessSpecialTree* Prev{nullptr}; struct ProcessSpecialTree* Next{nullptr}; }; /***********************************************************************************/ /// @brief Subsystem enum type. /***********************************************************************************/ enum struct ProcessSubsystem : Int32 { kProcessSubsystemSecurity = 100, kProcessSubsystemUser, kProcessSubsystemService, kProcessSubsystemDriver, kProcessSubsystemKernel, kProcessSubsystemCount = kProcessSubsystemKernel - kProcessSubsystemSecurity + 1, kProcessSubsystemInvalid = 0xFFFFFFF, }; /***********************************************************************************/ //! @brief Local Process status enum. /***********************************************************************************/ enum struct ProcessStatusKind : Int32 { kInvalid = 0, kStarting = 100, kRunning, kKilled, kFrozen, kFinished, kCount = kFinished - kStarting + 1, }; /***********************************************************************************/ //! @brief Affinity is the amount of nano-seconds this process is going to run. /***********************************************************************************/ enum struct AffinityKind : Int32 { kInvalid = 0, kRealTime = 100, kVeryHigh = 150, kHigh = 200, kStandard = 1000, kLowUsage = 1500, kVeryLowUsage = 2000, }; /***********************************************************************************/ //! Operators for AffinityKind /***********************************************************************************/ inline bool operator<(AffinityKind lhs, AffinityKind rhs) { Int32 lhs_int = static_cast(lhs); Int32 rhs_int = static_cast(rhs); return lhs_int < rhs_int; } inline bool operator>(AffinityKind lhs, AffinityKind rhs) { Int32 lhs_int = static_cast(lhs); Int32 rhs_int = static_cast(rhs); return lhs_int > rhs_int; } inline bool operator<=(AffinityKind lhs, AffinityKind rhs) { Int32 lhs_int = static_cast(lhs); Int32 rhs_int = static_cast(rhs); return lhs_int <= rhs_int; } inline bool operator>=(AffinityKind lhs, AffinityKind rhs) { Int32 lhs_int = static_cast(lhs); Int32 rhs_int = static_cast(rhs); return lhs_int >= rhs_int; } using PTime = UInt64; using ProcessTime = PTime; /***********************************************************************************/ //! @brief Local Process Identifier type. /***********************************************************************************/ using ProcessID = Int64; /***********************************************************************************/ /// @note For User manager, tells where we run the code. /***********************************************************************************/ enum struct ProcessLevelRing : Int32 { kRingStdUser = 1, kRingSuperUser = 2, kRingGuestUser = 5, kRingCount = 3, }; /***********************************************************************************/ /// @brief Helper type to describe a code image. /***********************************************************************************/ using ImagePtr = VoidPtr; /***********************************************************************************/ /// @brief Helper class to contain a process's image and blob. /***********************************************************************************/ struct ProcessImage final { explicit ProcessImage() = default; private: friend UserProcess; friend KernelTask; friend UserProcessScheduler; friend KernelTaskScheduler; ImagePtr fCode{}; ImagePtr fBlob{}; public: Bool HasCode() const { return this->fCode != nullptr; } Bool HasImage() const { return this->fBlob != nullptr; } ErrorOr LeakImage() { if (this->fCode) { return ErrorOr{this->fCode}; } return ErrorOr{kErrorInvalidData}; } ErrorOr LeakBlob() { if (this->fBlob) { return ErrorOr{this->fBlob}; } return ErrorOr{kErrorInvalidData}; } }; } // namespace Kernel #endif