summaryrefslogtreecommitdiffhomepage
path: root/src/kernel/KernelKit/UserProcessScheduler.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/KernelKit/UserProcessScheduler.h')
-rw-r--r--src/kernel/KernelKit/UserProcessScheduler.h243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/kernel/KernelKit/UserProcessScheduler.h b/src/kernel/KernelKit/UserProcessScheduler.h
new file mode 100644
index 00000000..b2ab7dc2
--- /dev/null
+++ b/src/kernel/KernelKit/UserProcessScheduler.h
@@ -0,0 +1,243 @@
+/* ========================================
+
+ Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license.
+
+======================================== */
+
+#ifndef INC_PROCESS_SCHEDULER_H
+#define INC_PROCESS_SCHEDULER_H
+
+/// @file UserProcessScheduler.h
+/// @brief User Process Scheduler header file.
+/// @author Amlal El Mahrouss (amlal@nekernel.org)
+
+#include <ArchKit/ArchKit.h>
+#include <KernelKit/CoreProcessScheduler.h>
+#include <KernelKit/LockDelegate.h>
+#include <KernelKit/UserMgr.h>
+#include <NeKit/MutableArray.h>
+
+////////////////////////////////////////////////////
+// Last revision date is: Fri Mar 28 2025 //
+////////////////////////////////////////////////////
+
+namespace Kernel {
+//! @brief Forward declarations.
+
+class IDylibObject;
+class UserProcessScheduler;
+class UserProcessHelper;
+
+/***********************************************************************************/
+/// @name USER_PROCESS
+/// @brief USER_PROCESS class, holds information about the running process/thread.
+/***********************************************************************************/
+class USER_PROCESS final {
+ public:
+ explicit USER_PROCESS();
+ ~USER_PROCESS();
+
+ public:
+ NE_COPY_DEFAULT(USER_PROCESS)
+
+ public:
+ Char Name[kSchedNameLen] = {"USER_PROCESS"};
+ ProcessSubsystem SubSystem{ProcessSubsystem::kProcessSubsystemUser};
+ User* Owner{nullptr};
+ HAL::StackFramePtr StackFrame{nullptr};
+ AffinityKind Affinity{AffinityKind::kStandard};
+ ProcessStatusKind Status{ProcessStatusKind::kKilled};
+ UInt8 StackReserve[kSchedMaxStackSz];
+ ProcessImage Image{};
+ SizeT StackSize{kSchedMaxStackSz};
+ IDylibObject* DylibDelegate{nullptr};
+ SizeT MemoryCursor{0UL};
+ SizeT MemoryLimit{kSchedMaxMemoryLimit};
+ SizeT UsedMemory{0UL};
+
+ struct USER_PROCESS_SIGNAL final {
+ UIntPtr SignalArg{0};
+ ProcessStatusKind Status{ProcessStatusKind::kKilled};
+ UIntPtr SignalID{0};
+ };
+
+ USER_PROCESS_SIGNAL Signal;
+ PROCESS_FILE_TREE<VoidPtr>* FileTree{nullptr};
+ PROCESS_HEAP_TREE<VoidPtr>* HeapTree{nullptr};
+ UserProcessTeam* ParentTeam;
+
+ VoidPtr VMRegister{0UL};
+
+ enum {
+ kInvalidExecutableKind,
+ kExecutableKind,
+ kExecutableDylibKind,
+ kExecutableKindCount,
+ };
+
+ ProcessTime PTime{0}; //! @brief Process allocated tine.
+ ProcessTime RTime{0}; //! @brief Process run time.
+ ProcessTime UTime{0}; //! #brief Process used time.
+
+ ProcessID ProcessId{kSchedInvalidPID};
+ Int32 Kind{kExecutableKind};
+
+ public:
+ /***********************************************************************************/
+ //! @brief boolean operator, check status.
+ /***********************************************************************************/
+ explicit operator bool();
+
+ /***********************************************************************************/
+ ///! @brief Crashes the app, exits with code ~0.
+ /***********************************************************************************/
+ Void Crash();
+
+ /***********************************************************************************/
+ ///! @brief Spawns a dynamic library handle if dylib.
+ /***********************************************************************************/
+ Bool InitDylib();
+
+ /***********************************************************************************/
+ ///! @brief Exits the app.
+ /***********************************************************************************/
+ Void Exit(const Int32& exit_code = 0);
+
+ /***********************************************************************************/
+ ///! @brief TLS allocate.
+ ///! @param sz size of data structure.
+ ///! @param pad_amount amount to add after pointer.
+ ///! @return A wrapped pointer, or error code.
+ /***********************************************************************************/
+ ErrorOr<VoidPtr> New(SizeT sz, SizeT pad_amount = 0);
+
+ /***********************************************************************************/
+ ///! @brief TLS free.
+ ///! @param ptr the pointer to free.
+ ///! @param sz the size of it.
+ /***********************************************************************************/
+ template <typename T>
+ Boolean Delete(ErrorOr<T*> ptr);
+
+ /***********************************************************************************/
+ ///! @brief Wakes up thread.
+ /***********************************************************************************/
+ Void Wake(Bool wakeup = false);
+
+ public:
+ /***********************************************************************************/
+ //! @brief Gets the local exit code.
+ /***********************************************************************************/
+ KPCError& GetExitCode() noexcept;
+
+ /***********************************************************************************/
+ ///! @brief Get the process's name
+ ///! @example 'C Runtime Library'
+ /***********************************************************************************/
+ const Char* GetName() noexcept;
+
+ /***********************************************************************************/
+ //! @brief return local error code of process.
+ //! @return Int32 local error code.
+ /***********************************************************************************/
+ KPCError& GetLocalCode() noexcept;
+
+ const User* GetOwner() noexcept;
+ const ProcessStatusKind& GetStatus() noexcept;
+ const AffinityKind& GetAffinity() noexcept;
+
+ private:
+ KPCError LastExitCode{0};
+ KPCError LocalCode{0};
+
+ friend UserProcessScheduler;
+ friend UserProcessHelper;
+};
+
+typedef Array<USER_PROCESS, kSchedProcessLimitPerTeam> USER_PROCESS_ARRAY;
+typedef Ref<USER_PROCESS> USER_PROCESS_REF;
+
+/// \brief Processs Team (contains multiple processes inside it.)
+/// Equivalent to a process batch
+class UserProcessTeam final {
+ public:
+ explicit UserProcessTeam();
+ ~UserProcessTeam() = default;
+
+ NE_COPY_DEFAULT(UserProcessTeam)
+
+ Array<USER_PROCESS, kSchedProcessLimitPerTeam>& AsArray();
+ Ref<USER_PROCESS>& AsRef();
+ ProcessID& Id() noexcept;
+
+ public:
+ USER_PROCESS_ARRAY mProcessList;
+ USER_PROCESS_REF mCurrentProcess;
+ ProcessID mTeamId{0};
+ ProcessID mProcessCur{0};
+};
+
+/***********************************************************************************/
+/// @brief USER_PROCESS scheduler class.
+/// The main class which you call to schedule user processes.
+/***********************************************************************************/
+class UserProcessScheduler final : public ISchedulable {
+ friend class UserProcessHelper;
+
+ public:
+ explicit UserProcessScheduler() = default;
+ ~UserProcessScheduler() override = default;
+
+ NE_COPY_DELETE(UserProcessScheduler)
+ NE_MOVE_DELETE(UserProcessScheduler)
+
+ public:
+ explicit operator bool();
+ bool operator!();
+
+ public:
+ UserProcessTeam& TheCurrentTeam();
+ BOOL SwitchTeam(UserProcessTeam& team);
+
+ public:
+ ProcessID Spawn(const Char* name, VoidPtr code, VoidPtr image);
+ Void Remove(ProcessID process_id);
+
+ Bool IsUser() override;
+ Bool IsKernel() override;
+ Bool HasMP() override;
+
+ public:
+ USER_PROCESS_REF& TheCurrentProcess();
+ SizeT Run() noexcept;
+
+ public:
+ STATIC UserProcessScheduler& The();
+
+ private:
+ UserProcessTeam mTeam{};
+};
+
+/***********************************************************************************/
+/**
+ * \brief USER_PROCESS helper class, which contains needed utilities for the scheduler.
+ */
+/***********************************************************************************/
+
+class UserProcessHelper final {
+ public:
+ STATIC Bool Switch(HAL::StackFramePtr frame_ptr, ProcessID new_pid);
+ STATIC Bool CanBeScheduled(const USER_PROCESS& process);
+ STATIC ErrorOr<ProcessID> TheCurrentPID();
+ STATIC SizeT StartScheduling();
+};
+} // namespace Kernel
+
+#include <KernelKit/ThreadLocalStorage.h>
+#include <KernelKit/UserProcessScheduler.inl>
+
+////////////////////////////////////////////////////
+// END
+////////////////////////////////////////////////////
+
+#endif /* ifndef INC_PROCESS_SCHEDULER_H */