From 2c4b02249ec4355a73b826909ab1889e45871faf Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Sat, 31 Aug 2024 10:47:14 +0200 Subject: Saving progress on User scheduler implementation. + Working on RISC-V, ARM64, POWER64 HALs, to be able to distribute mulitple versions of the product. Signed-off-by: Amlal El Mahrouss --- dev/ZKA/Sources/CodeManager.cxx | 14 +- dev/ZKA/Sources/DLLMain.cxx | 20 +- dev/ZKA/Sources/FS/NewFS.cxx | 2 +- dev/ZKA/Sources/Heap.cxx | 15 +- dev/ZKA/Sources/KernelCheck.cxx | 10 +- dev/ZKA/Sources/MP.cxx | 51 ++-- dev/ZKA/Sources/Network/IPC.cxx | 12 +- dev/ZKA/Sources/PEFCodeManager.cxx | 17 +- dev/ZKA/Sources/PEFDLLInterface.cxx | 6 +- dev/ZKA/Sources/PageAllocator.cxx | 2 +- dev/ZKA/Sources/ProcessScheduler.cxx | 453 ----------------------------- dev/ZKA/Sources/ProcessTeam.cxx | 10 +- dev/ZKA/Sources/Semaphore.cxx | 6 +- dev/ZKA/Sources/ThreadLocalStorage.cxx | 6 +- dev/ZKA/Sources/URL.cxx | 4 +- dev/ZKA/Sources/User.cxx | 6 +- dev/ZKA/Sources/UserProcessScheduler.cxx | 480 +++++++++++++++++++++++++++++++ dev/ZKA/Sources/Utils.cxx | 45 --- 18 files changed, 574 insertions(+), 585 deletions(-) delete mode 100644 dev/ZKA/Sources/ProcessScheduler.cxx create mode 100644 dev/ZKA/Sources/UserProcessScheduler.cxx (limited to 'dev/ZKA/Sources') diff --git a/dev/ZKA/Sources/CodeManager.cxx b/dev/ZKA/Sources/CodeManager.cxx index 3dc08ca6..243e3441 100644 --- a/dev/ZKA/Sources/CodeManager.cxx +++ b/dev/ZKA/Sources/CodeManager.cxx @@ -6,12 +6,12 @@ #include #include -#include +#include namespace Kernel { - /// @brief Executes a new process from a function. kernel code only. - /// @note This sets up a new stack, anything on the main function that calls the kernel will not be accessible. + /// @brief Executes a new process from a function. Kernel code only. + /// @note This sets up a new stack, anything on the main function that calls the Kernel will not be accessible. /// @param main the start of the process. /// @return if the process was started or not. bool execute_from_image(MainKind main, const Char* processName) noexcept @@ -19,10 +19,12 @@ namespace Kernel if (!main) return false; - PROCESS_HEADER_BLOCK proc((VoidPtr)main); - proc.Kind = PROCESS_HEADER_BLOCK::kExeKind; + UserProcess proc((VoidPtr)main); + proc.Kind = UserProcess::kExeKind; + proc.StackSize = mib_cast(1); + rt_copy_memory((VoidPtr)processName, proc.Name, rt_string_len(processName)); - return ProcessScheduler::The().Add(proc) == kErrorSuccess; + return UserProcessScheduler::The().Add(proc) == kErrorSuccess; } } // namespace Kernel diff --git a/dev/ZKA/Sources/DLLMain.cxx b/dev/ZKA/Sources/DLLMain.cxx index 89ca0d3c..15a9079f 100644 --- a/dev/ZKA/Sources/DLLMain.cxx +++ b/dev/ZKA/Sources/DLLMain.cxx @@ -3,7 +3,7 @@ Copyright ZKA Technologies File: Main.cxx - Purpose: Main entrypoint of kernel. + Purpose: Main entrypoint of Kernel. ------------------------------------------- */ @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -28,7 +28,7 @@ #include /***********************************************************************************/ -/* Returns kernel's version. */ +/* Returns Kernel's version. */ /***********************************************************************************/ EXTERN Kernel::Property cKernelVersion; @@ -152,7 +152,7 @@ namespace Kernel::Detail namespace Kernel { - EXTERN ProcessScheduler* cProcessScheduler; + EXTERN UserProcessScheduler* cProcessScheduler; } // namespace Kernel /// @brief Application entrypoint. @@ -173,7 +173,7 @@ EXTERN_C Kernel::Void ke_dll_entrypoint(Kernel::Void) CG::CGDrawWindowList(&cKernelWnd, 1); - /// Now run kernel loop, until no process are running. + /// Now run Kernel loop, until no process are running. Kernel::Detail::FilesystemInstaller(); // automatic filesystem creation. cKernelWnd->w_sub_type = CG::cWndFlagCloseControlSelect; @@ -213,9 +213,13 @@ EXTERN_C Kernel::Void ke_dll_entrypoint(Kernel::Void) CG::CGDrawStringToWnd(cKernelWnd, kSysDrv, 20, 10 + (FONT_SIZE_X * Kernel::rt_string_len("newoskrnl.dll: Missing catalog: ")), RGB(0, 0, 0)); } - Kernel::execute_from_image([]() -> void { - }, - "ZKA Logger"); + auto hey = []() -> void { + auto number_own = 8; + Kernel::kcout << "I have my own stack: " << Kernel::number(number_own); + while (Yes); + }; + + Kernel::execute_from_image(hey, "ZKA Logger"); while (Yes) { diff --git a/dev/ZKA/Sources/FS/NewFS.cxx b/dev/ZKA/Sources/FS/NewFS.cxx index 5406f91c..56707738 100644 --- a/dev/ZKA/Sources/FS/NewFS.cxx +++ b/dev/ZKA/Sources/FS/NewFS.cxx @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include using namespace Kernel; diff --git a/dev/ZKA/Sources/Heap.cxx b/dev/ZKA/Sources/Heap.cxx index de9eaa86..a89ed584 100644 --- a/dev/ZKA/Sources/Heap.cxx +++ b/dev/ZKA/Sources/Heap.cxx @@ -22,6 +22,7 @@ namespace Kernel PageManager kHeapPageManager; Bool kOperationInProgress = No; + /// @brief Contains data structures and algorithms for the heap. namespace Detail { /// @brief Kernel heap information block. @@ -58,6 +59,8 @@ namespace Kernel } } // namespace Detail + Detail::HEAP_INFORMATION_BLOCK_PTR kLatestAllocation = nullptr; + /// @brief Declare a new size for allocatedPtr. /// @param allocatedPtr the pointer. /// @return @@ -102,15 +105,17 @@ namespace Kernel heap_info_ptr->fTargetPtrSize = szFix; heap_info_ptr->fMagic = kKernelHeapMagic; - heap_info_ptr->fCRC32 = 0; // dont fill it for now. - heap_info_ptr->fTargetPtr = wrapper.VirtualAddress(); - heap_info_ptr->fPagePtr = 0; + heap_info_ptr->fCRC32 = 0U; // dont fill it for now. + heap_info_ptr->fTargetPtr = wrapper.VirtualAddress() + sizeof(Detail::HEAP_INFORMATION_BLOCK); + heap_info_ptr->fPagePtr = 0UL; ++kHeapCount; + kLatestAllocation = heap_info_ptr; + Detail::mm_alloc_fini_timeout(); - return reinterpret_cast(wrapper.VirtualAddress() + + return reinterpret_cast(heap_info_ptr + sizeof(Detail::HEAP_INFORMATION_BLOCK)); } @@ -196,7 +201,7 @@ namespace Kernel return -kErrorInternal; } - /// @brief Check if pointer is a valid kernel pointer. + /// @brief Check if pointer is a valid Kernel pointer. /// @param heap_ptr the pointer /// @return if it exists. Boolean mm_is_valid_heap(VoidPtr heap_ptr) diff --git a/dev/ZKA/Sources/KernelCheck.cxx b/dev/ZKA/Sources/KernelCheck.cxx index 85cfe215..8e5f0827 100644 --- a/dev/ZKA/Sources/KernelCheck.cxx +++ b/dev/ZKA/Sources/KernelCheck.cxx @@ -55,7 +55,7 @@ namespace Kernel switch (id) { case RUNTIME_CHECK_PROCESS: { - CGDrawString("0x00000008 Process execution fault, this is a catasrophic failure.", start_y, x, panicTxt); + CGDrawString("0x00000008 UserProcess execution fault, this is a catasrophic failure.", start_y, x, panicTxt); break; } case RUNTIME_CHECK_ACPI: { @@ -89,7 +89,7 @@ namespace Kernel break; } case RUNTIME_CHECK_IPC: { - CGDrawString("0x00000003 Bad kernel IPC error.", start_y, x, panicTxt); + CGDrawString("0x00000003 Bad Kernel IPC error.", start_y, x, panicTxt); RecoveryFactory::Recover(); break; } @@ -98,7 +98,7 @@ namespace Kernel RecoveryFactory::Recover(); break; case RUNTIME_CHECK_UNEXCPECTED: { - CGDrawString("0x0000000B Catasrophic kernel failure.", start_y, x, panicTxt); + CGDrawString("0x0000000B Catasrophic Kernel failure.", start_y, x, panicTxt); break; } case RUNTIME_CHECK_FAILED: { @@ -108,7 +108,7 @@ namespace Kernel } default: { RecoveryFactory::Recover(); - CGDrawString("0xFFFFFFFC Unknown kernel error.", start_y, x, panicTxt); + CGDrawString("0xFFFFFFFC Unknown Kernel error.", start_y, x, panicTxt); break; } } @@ -125,7 +125,7 @@ namespace Kernel HardwareTimer timer(cMaxSeconds); timer.Wait(); - kcout << "newoskrnl: Shutting down...\r"; + kcout << "newoskrnl: Shutting down computer...\r"; PowerFactoryInterface power(nullptr); power.Shutdown(); diff --git a/dev/ZKA/Sources/MP.cxx b/dev/ZKA/Sources/MP.cxx index 89b5f01d..381f266d 100644 --- a/dev/ZKA/Sources/MP.cxx +++ b/dev/ZKA/Sources/MP.cxx @@ -5,19 +5,23 @@ ------------------------------------------- */ #include -#include +#include #include #include ///! BUGS: 0 ///! @file MP.cxx -///! @brief This file handles multi processing in the kernel. +///! @brief This file handles multi processing in the Kernel. ///! @brief Multi processing is needed for multi-tasking operations. namespace Kernel { - STATIC Property cSMPCoreName; + /***********************************************************************************/ + /// @brief MP object container property. + /***********************************************************************************/ + + Property cSMPCoreName; ///! A HardwareThread class takes care of it's owned hardware thread. ///! It has a stack for it's core. @@ -87,29 +91,10 @@ namespace Kernel /// @retval false stack is invalid, previous code is running. Bool HardwareThread::Switch(HAL::StackFramePtr stack) { - /// provide 'nullptr' to free the stack frame. - if (stack == nullptr) - { - delete fStack; - fStack = nullptr; - - return true; - } - - if (!hal_check_stack(stack)) - { - return false; - } - - if (fStack) - { - delete fStack; - fStack = nullptr; - } - fStack = stack; hal_switch_context(fStack); + mp_do_context_switch(fStack); return true; } @@ -120,28 +105,30 @@ namespace Kernel return fWakeup; } - //! @brief Constructor and destructor + ///! @brief Internal Hardware Thread list. + STATIC HardwareThread cThreadList[cMaxHWThreads]; + + ///! @brief Constructor and destructors. ///! @brief Default constructor. HardwareThreadScheduler::HardwareThreadScheduler() { - StringView strCoreName(512); - strCoreName += "\\Class\\Smp\\MPClass"; + kcout << "newoskrnl: initializing HardwareThreadScheduler." << endl; - cSMPCoreName.GetKey() = strCoreName; - cSMPCoreName.GetValue() = (UIntPtr)this; + cSMPCoreName.GetKey() += "Property\\MPClass"; + cSMPCoreName.GetValue() = (PropertyId)this; - kcout << "newoskrnl: initializing " << strCoreName.CData() << endl; + kcout << "newoskrnl: initialized HardwareThreadScheduler." << endl; } ///! @brief Default destructor. HardwareThreadScheduler::~HardwareThreadScheduler() = default; /// @brief Shared singleton function - Ref HardwareThreadScheduler::The() + HardwareThreadScheduler& HardwareThreadScheduler::The() { - static HardwareThreadScheduler manager; - return {manager}; + STATIC HardwareThreadScheduler sched; + return sched; } /// @brief Get Stack Frame of Core diff --git a/dev/ZKA/Sources/Network/IPC.cxx b/dev/ZKA/Sources/Network/IPC.cxx index 92476d9c..e5926c7f 100644 --- a/dev/ZKA/Sources/Network/IPC.cxx +++ b/dev/ZKA/Sources/Network/IPC.cxx @@ -6,7 +6,7 @@ #include #include -#include +#include using namespace Kernel; @@ -63,7 +63,7 @@ namespace Kernel if (!pckt || !ipc_int_sanitize_packet(pckt)) { - ProcessScheduler::The().CurrentProcess().Leak().Crash(); + UserProcessScheduler::The().CurrentProcess().Leak().Crash(); return false; } @@ -82,7 +82,7 @@ namespace Kernel // crash process if the packet pointer of pointer is NULL. if (!pckt_in) { - ProcessScheduler::The().CurrentProcess().Leak().Crash(); + UserProcessScheduler::The().CurrentProcess().Leak().Crash(); return false; } @@ -98,12 +98,12 @@ namespace Kernel (*pckt_in)->IpcEndianess = static_cast(endian); (*pckt_in)->IpcPacketSize = sizeof(IPC_MESSAGE_STRUCT); - (*pckt_in)->IpcFrom.ProcessID = Kernel::ProcessScheduler::The().CurrentProcess().Leak().ProcessId; - (*pckt_in)->IpcFrom.ProcessTeam = Kernel::ProcessScheduler::The().CurrentTeam().mTeamId; + (*pckt_in)->IpcFrom.ProcessID = Kernel::UserProcessScheduler::The().CurrentProcess().Leak().ProcessId; + (*pckt_in)->IpcFrom.ProcessTeam = Kernel::UserProcessScheduler::The().CurrentTeam().mTeamId; return true; } - ProcessScheduler::The().CurrentProcess().Leak().Crash(); + UserProcessScheduler::The().CurrentProcess().Leak().Crash(); return false; } } // namespace Kernel diff --git a/dev/ZKA/Sources/PEFCodeManager.cxx b/dev/ZKA/Sources/PEFCodeManager.cxx index cecc4820..60b55efc 100644 --- a/dev/ZKA/Sources/PEFCodeManager.cxx +++ b/dev/ZKA/Sources/PEFCodeManager.cxx @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #include #include @@ -192,17 +192,24 @@ namespace Kernel namespace Utils { - bool execute_from_image(PEFLoader& exec, const Int32& procKind) noexcept + Bool execute_from_image(PEFLoader& exec, const Int32& procKind) noexcept { auto errOrStart = exec.FindStart(); - if (errOrStart.Error() != 0) + if (errOrStart.Error() != kErrorSuccess) return false; - PROCESS_HEADER_BLOCK proc(errOrStart.Leak().Leak()); + UserProcess proc(errOrStart.Leak().Leak()); + proc.Kind = procKind; + proc.StackSize = *(UIntPtr*)exec.FindSymbol("__STACK_SIZE", kPefData); + + if (!proc.StackSize) + { + proc.StackSize = mib_cast(8); + } - return ProcessScheduler::The().Add(proc); + return UserProcessScheduler::The().Add(proc); } } // namespace Utils diff --git a/dev/ZKA/Sources/PEFDLLInterface.cxx b/dev/ZKA/Sources/PEFDLLInterface.cxx index 0ca6b85e..70c68783 100644 --- a/dev/ZKA/Sources/PEFDLLInterface.cxx +++ b/dev/ZKA/Sources/PEFDLLInterface.cxx @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include @@ -37,7 +37,7 @@ using namespace Kernel; /** @brief Library initializer. */ /***********************************************************************************/ -EXTERN_C DLLInterfacePtr rtl_init_shared_object(PROCESS_HEADER_BLOCK* header) +EXTERN_C DLLInterfacePtr rtl_init_shared_object(UserProcess* header) { DLLInterfacePtr sharedObj = tls_new_class(); @@ -80,7 +80,7 @@ EXTERN_C DLLInterfacePtr rtl_init_shared_object(PROCESS_HEADER_BLOCK* header) /** @param successful Reports if successful or not. */ /***********************************************************************************/ -EXTERN_C Void rtl_fini_shared_object(PROCESS_HEADER_BLOCK* header, DLLInterfacePtr lib, Bool* successful) +EXTERN_C Void rtl_fini_shared_object(UserProcess* header, DLLInterfacePtr lib, Bool* successful) { MUST_PASS(successful); diff --git a/dev/ZKA/Sources/PageAllocator.cxx b/dev/ZKA/Sources/PageAllocator.cxx index 4a07a12d..dec6c470 100644 --- a/dev/ZKA/Sources/PageAllocator.cxx +++ b/dev/ZKA/Sources/PageAllocator.cxx @@ -8,7 +8,7 @@ #include #include -/// @brief Internal namespace, used internally by kernel. +/// @brief Internal namespace, used internally by Kernel. namespace Kernel::Detail { VoidPtr create_page_wrapper(Boolean rw, Boolean user, SizeT pageSz) diff --git a/dev/ZKA/Sources/ProcessScheduler.cxx b/dev/ZKA/Sources/ProcessScheduler.cxx deleted file mode 100644 index 82c1cf57..00000000 --- a/dev/ZKA/Sources/ProcessScheduler.cxx +++ /dev/null @@ -1,453 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies. - -------------------------------------------- */ - -/***********************************************************************************/ -/// @file ProcessScheduler.cxx -/// @brief User Process scheduler. -/***********************************************************************************/ - -#include -#include -#include -#include -#include -#include - -///! BUGS: 0 - -/***********************************************************************************/ -/* TODO: Document more the kernel, sdk and kits. */ -/***********************************************************************************/ - -namespace Kernel -{ - /***********************************************************************************/ - /// @brief Exit Code global variable. - /***********************************************************************************/ - - UInt32 cLastExitCode = 0U; - - /// @brief The main process object. - ProcessScheduler* cProcessScheduler = nullptr; - - /// @brief Gets the last exit code. - /// @note Not thread-safe. - /// @return Int32 the last exit code. - const UInt32& sched_get_exit_code(void) noexcept - { - return cLastExitCode; - } - - /***********************************************************************************/ - /// @brief crash current process. - /***********************************************************************************/ - - void PROCESS_HEADER_BLOCK::Crash() - { - constexpr auto cUnknownProcess = "?"; - - kcout << (*this->Name == 0 ? cUnknownProcess : this->Name) << ": crashed. (id = " << number(kErrorProcessFault); - kcout << ")\r"; - - this->Status = ProcessStatus::kDead; - - this->Exit(kErrorProcessFault); - } - - /// @brief Gets the local last exit code. - /// @note Not thread-safe. - /// @return Int32 the last exit code. - const UInt32& PROCESS_HEADER_BLOCK::GetExitCode() noexcept - { - return this->fLastExitCode; - } - - /***********************************************************************************/ - /// @brief Error code variable getter. - /***********************************************************************************/ - - Int32& PROCESS_HEADER_BLOCK::GetLocalCode() noexcept - { - return fLocalCode; - } - - void PROCESS_HEADER_BLOCK::Wake(const bool should_wakeup) - { - this->Status = - should_wakeup ? ProcessStatus::kRunning : ProcessStatus::kFrozen; - } - - /***********************************************************************************/ - - VoidPtr PROCESS_HEADER_BLOCK::New(const SizeT& sz) - { - if (this->HeapCursor) - { - if (this->FreeMemory < 1) - { - ErrLocal() = kErrorHeapOutOfMemory; - - /* We're going out of memory! crash... */ - this->Crash(); - - return nullptr; - } - - this->HeapCursor = reinterpret_cast((UIntPtr)this->HeapCursor + (sizeof(sz))); - VoidPtr cursor = this->HeapCursor; - - ++this->UsedMemory; - --this->FreeMemory; - - return cursor; - } - - return nullptr; - } - - /***********************************************************************************/ - - /* @brief checks if runtime pointer is in region. */ - bool rt_is_in_pool(VoidPtr pool_ptr, VoidPtr pool, const SizeT& pool_ptr_cur_sz, const SizeT& pool_ptr_used_sz) - { - if (pool == nullptr || - pool_ptr == nullptr) - return false; - - UIntPtr* uint_pool_ptr = (UIntPtr*)pool_ptr; - UIntPtr* uint_pool = (UIntPtr*)pool; - - return (UIntPtr)&uint_pool > (UIntPtr)&uint_pool_ptr && - pool_ptr_cur_sz > pool_ptr_used_sz; - } - - /* @brief free pointer from usage. */ - Boolean PROCESS_HEADER_BLOCK::Delete(VoidPtr ptr, const SizeT& sz) - { - if (sz < 1 || this->HeapCursor == this->HeapPtr) - return false; - - // also check for the amount of allocations we've done so far. - if (this->UsedMemory < 1) - return false; - - if (rt_is_in_pool(ptr, this->HeapCursor, this->UsedMemory, this->FreeMemory)) - { - this->HeapCursor = (VoidPtr)((UIntPtr)this->HeapCursor - (sizeof(sz))); - rt_zero_memory(ptr, sz); - - ++this->FreeMemory; - --this->UsedMemory; - - return true; - } - - return false; - } - - /// @brief process name getter. - const Char* PROCESS_HEADER_BLOCK::GetProcessName() noexcept - { - return this->Name; - } - - /// @brief process selector getter. - const User* PROCESS_HEADER_BLOCK::GetOwner() noexcept - { - return this->AssignedOwner; - } - - /// @brief process status getter. - const ProcessStatus& PROCESS_HEADER_BLOCK::GetStatus() noexcept - { - return this->Status; - } - - /***********************************************************************************/ - - /** - @brief Affinity is the time slot allowed for the process. - */ - const AffinityKind& PROCESS_HEADER_BLOCK::GetAffinity() noexcept - { - return this->Affinity; - } - - /** - @brief Standard exit proc. - */ - void PROCESS_HEADER_BLOCK::Exit(const Int32& exit_code) - { - fLastExitCode = exit_code; - cLastExitCode = exit_code; - - //! Delete image if not done already. - if (this->Image) - mm_delete_ke_heap(this->Image); - - if (this->StackFrame) - mm_delete_ke_heap((VoidPtr)this->StackFrame); - - this->Image = nullptr; - this->StackFrame = nullptr; - - if (this->Kind == kSharedObjectKind) - { - bool success = false; - rtl_fini_shared_object(this, this->DLLPtr, &success); - - if (success) - { - this->DLLPtr = nullptr; - } - } - - cProcessScheduler->Remove(this->ProcessId); - } - - /// @brief Add process to list. - /// @param process the process *Ref* class. - /// @return the process index inside the team. - SizeT ProcessScheduler::Add(PROCESS_HEADER_BLOCK& process) - { - if (!process.Image) - { - return -kErrorInvalidData; - } - - kcout << "ProcessScheduler: Adding process to team...\r"; - - // Create heap according to type of process. - if (process.Kind == PROCESS_HEADER_BLOCK::kExeKind) - { - process.HeapPtr = mm_new_ke_heap(process.SizeMemory, true, true); - } - else if (process.Kind == PROCESS_HEADER_BLOCK::kSharedObjectKind) - { - process.DLLPtr = rtl_init_shared_object(&process); - process.HeapPtr = mm_new_ke_heap(process.SizeMemory, true, true); - } - else - { - // Something went wrong, do not continue, process may be incorrect. - process.Crash(); - return -kErrorProcessFault; - } - - process.StackFrame = reinterpret_cast( - mm_new_ke_heap(sizeof(HAL::StackFrame), Yes, Yes)); - - MUST_PASS(process.StackFrame); - - if (process.Image) - { - process.StackFrame->BP = reinterpret_cast(process.Image); - } - else - { - if (process.Kind != PROCESS_HEADER_BLOCK::kSharedObjectKind) - { - process.Crash(); - return -kErrorProcessFault; - } - } - - if (!process.StackFrame->SP) - process.StackFrame->SP = reinterpret_cast(mm_new_ke_heap(sizeof(UInt8) * 8196, Yes, Yes)); - - process.Status = ProcessStatus::kStarting; - - process.ProcessId = (mTeam.mCurrentProcess); - - ++mTeam.mProcessAmount; - - process.HeapCursor = process.HeapPtr; - - mTeam.AsArray()[process.ProcessId] = process; - - kcout << "ProcessScheduler: Adding process to team [ OK ]...\r"; - - return process.ProcessId; - } - - /***********************************************************************************/ - - ProcessScheduler& ProcessScheduler::The() - { - MUST_PASS(cProcessScheduler); - return *cProcessScheduler; - } - - /***********************************************************************************/ - - /// @brief Remove process from list. - /// @param processSlot process slot inside team. - /// @retval true process was removed. - /// @retval false process doesn't exist in team. - Bool ProcessScheduler::Remove(ProcessID processSlot) - { - // check if process is within range. - if (processSlot > mTeam.AsArray().Count()) - return false; - - // also check if the process isn't a dummy one. - if (mTeam.AsArray()[processSlot].Image == nullptr) - return false; - - kcout << "ProcessScheduler: Removing process...\r"; - - --mTeam.mProcessAmount; - mTeam.AsArray()[processSlot].Status = ProcessStatus::kDead; - return true; - } - - /// @brief Run scheduler. - /// @return - SizeT ProcessScheduler::Run() noexcept - { - SizeT process_index = 0; //! we store this guy to tell the scheduler how many - //! things we have scheduled. - - for (; process_index < mTeam.AsArray().Count(); ++process_index) - { - auto process = mTeam.AsArray()[process_index]; - - //! check if process needs to be scheduled. - if (ProcessHelper::CanBeScheduled(process)) - { - // set the current process. - mTeam.AsRef() = process; - - process.PTime = static_cast(process.Affinity); - - kcout << process.Name << ": will be runned.\r"; - - // tell helper to find a core to schedule on. - ProcessHelper::Switch(process.StackFrame, - process.ProcessId); - } - else - { - // otherwise increment the P-time. - --mTeam.AsRef().Leak().PTime; - } - } - - return process_index; - } - - /// @brief Gets the current scheduled team. - /// @return - ProcessTeam& ProcessScheduler::CurrentTeam() - { - return mTeam; - } - - /// @internal - - /// @brief Gets current running process. - /// @return - Ref& ProcessScheduler::CurrentProcess() - { - return mTeam.AsRef(); - } - - /// @brief Current proccess id getter. - /// @return Process ID integer. - PID& ProcessHelper::TheCurrentPID() - { - kcout << "ProcessHelper::TheCurrentPID: Leaking ProcessId...\r"; - return cProcessScheduler->CurrentProcess().Leak().ProcessId; - } - - /// @brief Check if process can be schedulded. - /// @param process the process reference. - /// @retval true can be schedulded. - /// @retval false cannot be schedulded. - bool ProcessHelper::CanBeScheduled(PROCESS_HEADER_BLOCK& process) - { - if (process.Status == ProcessStatus::kFrozen || - process.Status == ProcessStatus::kDead) - return false; - - if (process.Kind == PROCESS_HEADER_BLOCK::kSharedObjectKind) - { - if (auto start = process.DLLPtr->Load(kPefStart, rt_string_len(kPefStart), kPefCode); - start) - { - process.Image = start; - process.StackFrame->BP = reinterpret_cast(start); - } - } - - return process.PTime < 0; - } - - /** - * @brief Scheduler helper class. - */ - - SizeT ProcessHelper::StartScheduling() - { - if (!cProcessScheduler) - cProcessScheduler = new ProcessScheduler(); - - SizeT ret = cProcessScheduler->Run(); - return ret; - } - - /** - * \brief Does a context switch in a CPU. - * \param the_stack the stackframe of the running app. - * \param new_pid the process's PID. - */ - - bool ProcessHelper::Switch(HAL::StackFrame* the_stack, const PID& new_pid) - { - if (!the_stack || new_pid < 0) - return false; - - for (SizeT index = 0UL; index < HardwareThreadScheduler::The().Leak().Count(); ++index) - { - if (HardwareThreadScheduler::The().Leak()[index].Leak()->Kind() == kInvalidHart) - continue; - - if (HardwareThreadScheduler::The().Leak()[index].Leak()->StackFrame() == the_stack) - { - HardwareThreadScheduler::The().Leak()[index].Leak()->Busy(false); - continue; - } - - if (HardwareThreadScheduler::The().Leak()[index].Leak()->IsBusy()) - continue; - - if (HardwareThreadScheduler::The().Leak()[index].Leak()->Kind() != - ThreadKind::kHartBoot && - HardwareThreadScheduler::The().Leak()[index].Leak()->Kind() != - ThreadKind::kHartSystemReserved) - { - HardwareThreadScheduler::The().Leak()[index].Leak()->Busy(true); - ProcessHelper::TheCurrentPID() = new_pid; - - return HardwareThreadScheduler::The().Leak()[index].Leak()->Switch(the_stack); - } - } - - return false; - } - - /// @brief this checks if any process is on the team. - ProcessScheduler::operator bool() - { - return mTeam.AsArray().Count() > 0; - } - - /// @brief this checks if no process is on the team. - bool ProcessScheduler::operator!() - { - return mTeam.AsArray().Count() == 0; - } -} // namespace Kernel diff --git a/dev/ZKA/Sources/ProcessTeam.cxx b/dev/ZKA/Sources/ProcessTeam.cxx index 58a639f6..f7282faf 100644 --- a/dev/ZKA/Sources/ProcessTeam.cxx +++ b/dev/ZKA/Sources/ProcessTeam.cxx @@ -6,16 +6,16 @@ /***********************************************************************************/ /// @file ProcessTeam.cxx -/// @brief Process teams implementation. +/// @brief UserProcess teams implementation. /***********************************************************************************/ -#include +#include namespace Kernel { - /// @brief Process list array getter. + /// @brief UserProcess list array getter. /// @return The list of process to schedule. - Array& ProcessTeam::AsArray() + Array& ProcessTeam::AsArray() { return mProcessList; } @@ -29,7 +29,7 @@ namespace Kernel /// @brief Current process getter. /// @return The current process header. - Ref& ProcessTeam::AsRef() + Ref& ProcessTeam::AsRef() { return mCurrentProcess; } diff --git a/dev/ZKA/Sources/Semaphore.cxx b/dev/ZKA/Sources/Semaphore.cxx index f9da0703..9181443e 100644 --- a/dev/ZKA/Sources/Semaphore.cxx +++ b/dev/ZKA/Sources/Semaphore.cxx @@ -4,7 +4,7 @@ ------------------------------------------- */ -#include +#include #include namespace Kernel @@ -17,7 +17,7 @@ namespace Kernel return fLockingProcess == nullptr; } - bool Semaphore::Lock(PROCESS_HEADER_BLOCK* process) + bool Semaphore::Lock(UserProcess* process) { if (!process || fLockingProcess) return false; @@ -32,7 +32,7 @@ namespace Kernel return fLockingProcess; } - bool Semaphore::LockOrWait(PROCESS_HEADER_BLOCK* process, TimerInterface* timer) + bool Semaphore::LockOrWait(UserProcess* process, TimerInterface* timer) { if (process == nullptr) return false; diff --git a/dev/ZKA/Sources/ThreadLocalStorage.cxx b/dev/ZKA/Sources/ThreadLocalStorage.cxx index ed12c890..4ee2494e 100644 --- a/dev/ZKA/Sources/ThreadLocalStorage.cxx +++ b/dev/ZKA/Sources/ThreadLocalStorage.cxx @@ -9,21 +9,21 @@ #include #include -#include +#include #include ///! BUGS: 0 /***********************************************************************************/ /// @file ThreadLocalStorage.cxx -/// @brief TLS inside the kernel. +/// @brief TLS inside the Kernel. /***********************************************************************************/ using namespace Kernel; namespace Detail { - /// \brief Process thread information header. + /// \brief UserProcess thread information header. struct THREAD_HEADER_BLOCK final { STATIC constexpr SizeT cMaxLen = 256; diff --git a/dev/ZKA/Sources/URL.cxx b/dev/ZKA/Sources/URL.cxx index 189aba8e..9c76d435 100644 --- a/dev/ZKA/Sources/URL.cxx +++ b/dev/ZKA/Sources/URL.cxx @@ -19,13 +19,13 @@ namespace Kernel URL::~URL() = default; - /// @brief internal and reserved protocols by kernel. + /// @brief internal and reserved protocols by Kernel. constexpr const Char* kURLProtocols[] = { "file", // Filesystem protocol "zup", // ZKA update protocol "oscc", // Open System Configuration Connectivity. "odbc", // ODBC connectivity. - "https", // HTTPS layer driver (HTTPS.sys). + "https", // HTTPS layer driver (HTTPS.sys). }; constexpr const int kUrlOutSz = 1; //! such as: :// diff --git a/dev/ZKA/Sources/User.cxx b/dev/ZKA/Sources/User.cxx index 53cb5e07..b3b62d8b 100644 --- a/dev/ZKA/Sources/User.cxx +++ b/dev/ZKA/Sources/User.cxx @@ -5,7 +5,7 @@ * Copyright ZKA Technologies., all rights reserved. * * File: User.cxx - * Purpose: User concept and management. + * Purpose: User concept class. * * ======================================================== */ @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include @@ -120,6 +120,8 @@ namespace Kernel return this->fUserName; } + /// @brief Returns the user's ring. + /// @return The king of ring the user is attached to. const RingKind& User::Ring() noexcept { return this->fRing; diff --git a/dev/ZKA/Sources/UserProcessScheduler.cxx b/dev/ZKA/Sources/UserProcessScheduler.cxx new file mode 100644 index 00000000..94512913 --- /dev/null +++ b/dev/ZKA/Sources/UserProcessScheduler.cxx @@ -0,0 +1,480 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +/***********************************************************************************/ +/// @file UserProcessScheduler.cxx +/// @brief User UserProcess scheduler. +/***********************************************************************************/ + +#include +#include +#include +#include +#include +#include + +///! BUGS: 0 + +/***********************************************************************************/ +/* TODO: Document more the Kernel, sdk and kits. */ +/***********************************************************************************/ + +namespace Kernel +{ + /***********************************************************************************/ + /// @brief Exit Code global variable. + /***********************************************************************************/ + + UInt32 cLastExitCode = 0U; + + /***********************************************************************************/ + /// @brief UserProcess scheduler instance. + /***********************************************************************************/ + + UserProcessScheduler* cProcessScheduler = nullptr; + + /// @brief Gets the last exit code. + /// @note Not thread-safe. + /// @return Int32 the last exit code. + const UInt32& sched_get_exit_code(void) noexcept + { + return cLastExitCode; + } + + /***********************************************************************************/ + /// @brief crash current process. + /***********************************************************************************/ + + void UserProcess::Crash() + { + constexpr auto cUnknownProcess = "?"; + + kcout << (*this->Name == 0 ? cUnknownProcess : this->Name) << ": crashed. (id = " << number(kErrorProcessFault); + kcout << ")\r"; + + this->Status = ProcessStatus::kDead; + + this->Exit(kErrorProcessFault); + } + + /// @brief Gets the local last exit code. + /// @note Not thread-safe. + /// @return Int32 the last exit code. + const UInt32& UserProcess::GetExitCode() noexcept + { + return this->fLastExitCode; + } + + /***********************************************************************************/ + /// @brief Error code variable getter. + /***********************************************************************************/ + + Int32& UserProcess::GetLocalCode() noexcept + { + return fLocalCode; + } + + void UserProcess::Wake(const bool should_wakeup) + { + this->Status = + should_wakeup ? ProcessStatus::kRunning : ProcessStatus::kFrozen; + } + + /***********************************************************************************/ + + VoidPtr UserProcess::New(const SizeT& sz) + { + if (this->HeapCursor) + { + if (this->FreeMemory < 1) + { + ErrLocal() = kErrorHeapOutOfMemory; + + /* We're going out of memory! crash... */ + this->Crash(); + + return nullptr; + } + + this->HeapCursor = reinterpret_cast((UIntPtr)this->HeapCursor + (sizeof(sz))); + VoidPtr cursor = this->HeapCursor; + + ++this->UsedMemory; + --this->FreeMemory; + + return cursor; + } + + return nullptr; + } + + /***********************************************************************************/ + + /* @brief checks if runtime pointer is in region. */ + bool rt_is_in_pool(VoidPtr pool_ptr, VoidPtr pool, const SizeT& pool_ptr_cur_sz, const SizeT& pool_ptr_used_sz) + { + if (pool == nullptr || + pool_ptr == nullptr) + return false; + + UIntPtr* uint_pool_ptr = (UIntPtr*)pool_ptr; + UIntPtr* uint_pool = (UIntPtr*)pool; + + return (UIntPtr)&uint_pool > (UIntPtr)&uint_pool_ptr && + pool_ptr_cur_sz > pool_ptr_used_sz; + } + + /* @brief free pointer from usage. */ + Boolean UserProcess::Delete(VoidPtr ptr, const SizeT& sz) + { + if (sz < 1 || this->HeapCursor == this->HeapPtr) + return false; + + // also check for the amount of allocations we've done so far. + if (this->UsedMemory < 1) + return false; + + if (rt_is_in_pool(ptr, this->HeapCursor, this->UsedMemory, this->FreeMemory)) + { + this->HeapCursor = (VoidPtr)((UIntPtr)this->HeapCursor - (sizeof(sz))); + rt_zero_memory(ptr, sz); + + ++this->FreeMemory; + --this->UsedMemory; + + return true; + } + + return false; + } + + /// @brief UserProcess name getter. + const Char* UserProcess::GetProcessName() noexcept + { + return this->Name; + } + + /// @brief UserProcess user getter. + const User* UserProcess::GetOwner() noexcept + { + return this->Owner; + } + + /// @brief UserProcess status getter. + const ProcessStatus& UserProcess::GetStatus() noexcept + { + return this->Status; + } + + /***********************************************************************************/ + + /** + @brief Affinity is the time slot allowed for the process. + */ + const AffinityKind& UserProcess::GetAffinity() noexcept + { + return this->Affinity; + } + + /** + @brief Standard exit proc. + */ + void UserProcess::Exit(const Int32& exit_code) + { + fLastExitCode = exit_code; + cLastExitCode = exit_code; + + //! Delete image if not done already. + if (this->Image) + mm_delete_ke_heap(this->Image); + + if (this->StackFrame) + mm_delete_ke_heap((VoidPtr)this->StackFrame); + + this->Image = nullptr; + this->StackFrame = nullptr; + + if (this->Kind == kDLLKind) + { + Bool success = false; + rtl_fini_shared_object(this, this->DLLPtr, &success); + + if (success) + { + this->DLLPtr = nullptr; + } + } + + if (this->StackReserve) + delete[] this->StackReserve; + + cProcessScheduler->Remove(this->ProcessId); + } + + /// @brief Add process to list. + /// @param process the process *Ref* class. + /// @return the process index inside the team. + SizeT UserProcessScheduler::Add(UserProcess& process) + { + if (!process.Image) + { + return -kErrorInvalidData; + } + + kcout << "UserProcessScheduler: Adding process to team...\r"; + + // Create heap according to type of process. + if (process.Kind == UserProcess::kExeKind) + { + process.HeapPtr = mm_new_ke_heap(process.SizeMemory, true, true); + } + else if (process.Kind == UserProcess::kDLLKind) + { + process.DLLPtr = rtl_init_shared_object(&process); + process.HeapPtr = mm_new_ke_heap(process.SizeMemory, true, true); + } + else + { + // Something went wrong, do not continue, process may be incorrect. + process.Crash(); + return -kErrorProcessFault; + } + + process.StackFrame = reinterpret_cast( + mm_new_ke_heap(sizeof(HAL::StackFrame), Yes, Yes)); + + MUST_PASS(process.StackFrame); + + if (process.Image) + { + // get preferred stack size by app. + const auto cMaxStackSize = process.StackSize; + + process.StackFrame->BP = reinterpret_cast(process.Image); + process.StackFrame->SP = reinterpret_cast(mm_new_ke_heap(cMaxStackSize, Yes, Yes)); + + if (!process.StackFrame->SP) + { + process.StackReserve = new UInt8[cMaxStackSz]; + process.StackFrame->SP = reinterpret_cast(process.StackReserve); + + kcout << "newoskrnl: use fallback reserve.\r"; + } + } + else + { + if (process.Kind != UserProcess::kDLLKind) + { + process.Crash(); + return -kErrorProcessFault; + } + } + + process.Status = ProcessStatus::kStarting; + + process.ProcessId = mTeam.mProcessAmount; + + ++mTeam.mProcessAmount; + + process.HeapCursor = process.HeapPtr; + + mTeam.AsArray()[process.ProcessId] = process; + + kcout << "UserProcessScheduler: Adding process to team [ OK ]...\r"; + + return process.ProcessId; + } + + /***********************************************************************************/ + + UserProcessScheduler& UserProcessScheduler::The() + { + MUST_PASS(cProcessScheduler); + return *cProcessScheduler; + } + + /***********************************************************************************/ + + /// @brief Remove process from list. + /// @param processSlot process slot inside team. + /// @retval true process was removed. + /// @retval false process doesn't exist in team. + Bool UserProcessScheduler::Remove(ProcessID processSlot) + { + // check if process is within range. + if (processSlot > mTeam.AsArray().Count()) + return false; + + // also check if the process isn't a dummy one. + if (mTeam.AsArray()[processSlot].Image == nullptr) + return false; + + kcout << "UserProcessScheduler: Removing process...\r"; + + mTeam.AsArray()[processSlot].Status = ProcessStatus::kDead; + --mTeam.mProcessAmount; + + return true; + } + + /// @brief Run scheduler. + /// @return + SizeT UserProcessScheduler::Run() noexcept + { + SizeT process_index = 0; //! we store this guy to tell the scheduler how many + //! things we have scheduled. + + for (; process_index < mTeam.AsArray().Capacity(); ++process_index) + { + auto& process = mTeam.AsArray()[process_index]; + + //! check if process needs to be scheduled. + if (ProcessHelper::CanBeScheduled(process)) + { + // set the current process. + mTeam.AsRef() = process; + + process.PTime = static_cast(process.Affinity); + + kcout << process.Name << ": will be runned.\r"; + + // tell helper to find a core to schedule on. + if (!ProcessHelper::Switch(process.StackFrame, + process.ProcessId)) + process.Crash(); + + continue; + } + else + { + // otherwise increment the P-time. + --process.PTime; + } + } + + return process_index; + } + + /// @brief Gets the current scheduled team. + /// @return + ProcessTeam& UserProcessScheduler::CurrentTeam() + { + return mTeam; + } + + /// @internal + + /// @brief Gets current running process. + /// @return + Ref& UserProcessScheduler::CurrentProcess() + { + return mTeam.AsRef(); + } + + /// @brief Current proccess id getter. + /// @return UserProcess ID integer. + PID& ProcessHelper::TheCurrentPID() + { + kcout << "ProcessHelper::TheCurrentPID: Leaking ProcessId...\r"; + return cProcessScheduler->CurrentProcess().Leak().ProcessId; + } + + /// @brief Check if process can be schedulded. + /// @param process the process reference. + /// @retval true can be schedulded. + /// @retval false cannot be schedulded. + bool ProcessHelper::CanBeScheduled(UserProcess& process) + { + if (process.Status == ProcessStatus::kFrozen || + process.Status == ProcessStatus::kDead) + return false; + + if (process.Kind == UserProcess::kDLLKind) + { + if (auto start = process.DLLPtr->Load(kPefStart, rt_string_len(kPefStart), kPefCode); + start) + { + process.Image = start; + process.StackFrame->BP = reinterpret_cast(start); + } + } + + return process.PTime < 1; + } + + /** + * @brief Scheduler helper class. + */ + + SizeT ProcessHelper::StartScheduling() + { + if (!cProcessScheduler) + { + cProcessScheduler = new UserProcessScheduler(); + MUST_PASS(cProcessScheduler); + + kcout << "newoskrnl: Team capacity: " << number(cProcessScheduler->CurrentTeam().AsArray().Capacity()) << endl; + } + + SizeT ret = cProcessScheduler->Run(); + return ret; + } + + /** + * \brief Does a context switch in a CPU. + * \param the_stack the stackframe of the running app. + * \param new_pid the process's PID. + */ + + bool ProcessHelper::Switch(HAL::StackFrame* the_stack, const PID& new_pid) + { + if (!the_stack || new_pid < 0) + return false; + + kcout << "newoskrnl: Finding hardware thread...\r"; + + for (SizeT index = 0UL; index < HardwareThreadScheduler::The().Count(); ++index) + { + if (HardwareThreadScheduler::The()[index].Leak()->Kind() == kInvalidHart) + continue; + + if (HardwareThreadScheduler::The()[index].Leak()->IsBusy()) + continue; + + if (HardwareThreadScheduler::The()[index].Leak()->Kind() != + ThreadKind::kHartBoot && + HardwareThreadScheduler::The()[index].Leak()->Kind() != + ThreadKind::kHartSystemReserved) + { + HardwareThreadScheduler::The()[index].Leak()->Busy(true); + + ProcessHelper::TheCurrentPID() = new_pid; + + kcout << "newoskrnl: Found hardware thread...\r"; + + bool ret = HardwareThreadScheduler::The()[index].Leak()->Switch(the_stack); + + HardwareThreadScheduler::The()[index].Leak()->Busy(false); + + return ret; + } + } + + return false; + } + + /// @brief this checks if any process is on the team. + UserProcessScheduler::operator bool() + { + return mTeam.AsArray().Count() > 0; + } + + /// @brief this checks if no process is on the team. + bool UserProcessScheduler::operator!() + { + return mTeam.AsArray().Count() == 0; + } +} // namespace Kernel diff --git a/dev/ZKA/Sources/Utils.cxx b/dev/ZKA/Sources/Utils.cxx index 4a56df3b..8ecfd805 100644 --- a/dev/ZKA/Sources/Utils.cxx +++ b/dev/ZKA/Sources/Utils.cxx @@ -210,48 +210,3 @@ namespace Kernel return str; } } // namespace Kernel - -#ifdef __FREESTANDING__ - -//////////////////////////////////////////////////////////////////////////////////////// -/// Exported C functions -//////////////////////////////////////////////////////////////////////////////////////// - -/// @brief memset in C++ -EXTERN_C void memset(void* dst, char src, Kernel::SizeT len) -{ - Kernel::rt_set_memory(dst, src, len); -} - -/// @brief memcpy in C++ -EXTERN_C void memcpy(void* dst, void* src, Kernel::SizeT len) -{ - Kernel::rt_copy_memory(src, dst, len); -} - -/// @brief memmove in C++ -EXTERN_C void* memmove(void* dst, void* src, Kernel::SizeT len) -{ - Kernel::rt_copy_memory(src, dst, len); - return dst; -} - -/// @brief strlen definition in C++. -EXTERN_C Kernel::SizeT strlen(const Char* whatToCheck) -{ - return Kernel::rt_string_len(whatToCheck); -} - -/// @brief memcmp in C++ -EXTERN_C Kernel::SizeT memcmp(void* dst, void* src, Kernel::SizeT len) -{ - return Kernel::rt_string_cmp((char*)src, (char*)dst, len); -} - -/// @brief strcmp in C++ -EXTERN_C Kernel::SizeT strcmp(char* dst, char* src, Kernel::SizeT len) -{ - return Kernel::rt_string_cmp(src, dst, len); -} - -#endif // __FREESTANDING__ -- cgit v1.2.3