From 7faa5e2fcf41c4fbb2241b605e8f2a11738fc4d9 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Thu, 24 Apr 2025 15:52:36 +0200 Subject: dev, kernel: scheduler, timer: hw timer and scheduler improvements. Signed-off-by: Amlal El Mahrouss --- dev/boot/BootKit/Qr.h | 4 +- dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc | 23 +---------- dev/kernel/HALKit/AMD64/HalDebugOutput.cc | 5 +++ dev/kernel/HALKit/AMD64/HalDescriptorLoader.cc | 4 +- dev/kernel/HALKit/AMD64/HalKernelMain.cc | 25 ++++++------ dev/kernel/HALKit/AMD64/HalTimerAMD64.cc | 47 ++++++++++++++-------- dev/kernel/KernelKit/Timer.h | 10 ++--- dev/kernel/KernelKit/UserProcessScheduler.h | 2 +- dev/kernel/src/BinaryMutex.cc | 2 +- dev/kernel/src/UserProcessScheduler.cc | 11 ++++- 10 files changed, 72 insertions(+), 61 deletions(-) (limited to 'dev') diff --git a/dev/boot/BootKit/Qr.h b/dev/boot/BootKit/Qr.h index 231fcee7..1bf9fa3d 100644 --- a/dev/boot/BootKit/Qr.h +++ b/dev/boot/BootKit/Qr.h @@ -957,8 +957,8 @@ namespace qr NE_COPY_DEFAULT(QrDelegate) /// @brief Draw method delegate. - template - bool draw(Qr& subject, int x, int y) noexcept + template + bool draw(Qr& subject, Int32 x, Int32 y) noexcept { return subject.draw(x, y); } diff --git a/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc b/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc index 3b98e9e8..1f865057 100644 --- a/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc +++ b/dev/kernel/HALKit/AMD64/HalApplicationProcessor.cc @@ -219,17 +219,9 @@ namespace Kernel::HAL kApicBaseAddress = kMADTBlock->Address; - constexpr auto kMemoryAPStart = 0x7C000; - Char* ptr_ap_code = reinterpret_cast(kMemoryAPStart); - - mm_map_page(ptr_ap_code, ptr_ap_code, kMMFlagsWr | kMMFlagsPCD); - - SizeT hal_ap_blob_len = hal_ap_blob_end - hal_ap_blob_start; - - rt_copy_memory((Char*)hal_ap_blob_start, ptr_ap_code, hal_ap_blob_len); - while (Yes) { + /// @note Anything bigger than x2APIC type doesn't exist. if (kMADTBlock->List[index].Type > 9 || kSMPCount > kSchedProcessLimitPerTeam) break; @@ -243,17 +235,6 @@ namespace Kernel::HAL kAPICLocales[kSMPCount] = kMADTBlock->List[kSMPCount].LAPIC.ProcessorID; (void)(kout << "SMP: APIC ID: " << number(kAPICLocales[kSMPCount]) << kendl); - // I'll just make the AP start from scratch here. - - hal_send_start_ipi(kApicBaseAddress, kAPICLocales[kSMPCount]); - - HardwareTimer timer(Kernel::rtl_ms(10)); - timer.Wait(); - - /// TODO: HAL helper to create an address. - - hal_send_sipi(kApicBaseAddress, kAPICLocales[kSMPCount], (UInt8)(((UIntPtr)ptr_ap_code) >> 12)); - ++kSMPCount; break; } @@ -264,7 +245,7 @@ namespace Kernel::HAL ++index; } - (void)(kout << "SMP: number of APs: " << number(kSMPCount) << kendl); + (void)(kout << "SMP: Number of APs: " << number(kSMPCount) << kendl); // Kernel is now SMP aware. // That means that the scheduler is now available (on MP Kernels) diff --git a/dev/kernel/HALKit/AMD64/HalDebugOutput.cc b/dev/kernel/HALKit/AMD64/HalDebugOutput.cc index b69614fd..84c8c348 100644 --- a/dev/kernel/HALKit/AMD64/HalDebugOutput.cc +++ b/dev/kernel/HALKit/AMD64/HalDebugOutput.cc @@ -121,6 +121,11 @@ namespace Kernel x += kFontSizeX; + if (x > kHandoverHeader->f_GOP.f_Width) + { + x = kFontSizeX; + } + if (y > kHandoverHeader->f_GOP.f_Height) { y = kFontSizeY; diff --git a/dev/kernel/HALKit/AMD64/HalDescriptorLoader.cc b/dev/kernel/HALKit/AMD64/HalDescriptorLoader.cc index c0c7dfcf..f205e766 100644 --- a/dev/kernel/HALKit/AMD64/HalDescriptorLoader.cc +++ b/dev/kernel/HALKit/AMD64/HalDescriptorLoader.cc @@ -107,10 +107,10 @@ namespace Kernel::HAL idt.Limit = sizeof(::Kernel::Detail::AMD64::InterruptDescriptorAMD64) * (kKernelIdtSize); - hal_load_idt(idt); - Detail::hal_enable_pit(kPITTickForScheduler); + hal_load_idt(idt); + rt_sti(); } diff --git a/dev/kernel/HALKit/AMD64/HalKernelMain.cc b/dev/kernel/HALKit/AMD64/HalKernelMain.cc index d59e9e86..0c680f97 100644 --- a/dev/kernel/HALKit/AMD64/HalKernelMain.cc +++ b/dev/kernel/HALKit/AMD64/HalKernelMain.cc @@ -19,8 +19,6 @@ EXTERN_C Kernel::VoidPtr kInterruptVectorTable[]; -STATIC Kernel::Array kTeams; - STATIC Kernel::Void hal_pre_init_scheduler() noexcept { for (Kernel::SizeT i = 0U; i < Kernel::UserProcessScheduler::The().CurrentTeam().AsArray().Count(); ++i) @@ -98,11 +96,13 @@ EXTERN_C Kernel::Void hal_real_init(Kernel::Void) noexcept idt_loader.Load(idt_reg); - /// after the scheduler runs, we must look over teams, every 200ms in order to schedule every process according to their affinity fairly. + /// after the scheduler runs, we must look over teams, every 5000s in order to schedule every process according to their affinity fairly. + + auto constexpr kSchedTeamSwitchMS = 5U; /// @brief Team switch time in milliseconds. - auto constexpr kSchedTeamSwitchMS = 200U; /// @brief Team switch time in milliseconds. + Kernel::HardwareTimer timer(rtl_milliseconds(kSchedTeamSwitchMS)); - Kernel::HardwareTimer timer(rtl_ms(kSchedTeamSwitchMS)); + STATIC Kernel::Array kTeams; SizeT team_index = 0U; @@ -110,15 +110,16 @@ EXTERN_C Kernel::Void hal_real_init(Kernel::Void) noexcept /// @details Not even round-robin, just a simple loop in this boot core we're at. while (YES) { - timer.Wait(); - - UserProcessScheduler::The().SwitchTeam(kTeams[team_index]); - - ++team_index; - - if (team_index > kSchedTeamCount) + if (team_index > (kSchedTeamCount - 1)) { team_index = 0U; } + + while (!UserProcessScheduler::The().SwitchTeam(kTeams[team_index])) + ; + + timer.Wait(); + + ++team_index; } } diff --git a/dev/kernel/HALKit/AMD64/HalTimerAMD64.cc b/dev/kernel/HALKit/AMD64/HalTimerAMD64.cc index 72de8eb0..ade41d2f 100644 --- a/dev/kernel/HALKit/AMD64/HalTimerAMD64.cc +++ b/dev/kernel/HALKit/AMD64/HalTimerAMD64.cc @@ -17,10 +17,10 @@ // timer slot 0 -#define cHPETCounterRegValue (0x00) -#define cHPETConfigRegValue (0x20) -#define cHPETCompRegValue (0x24) -#define cHPETInterruptRegValue (0x2C) +#define kHPETCounterRegValue (0x00) +#define kHPETConfigRegValue (0x20) +#define kHPETCompRegValue (0x24) +#define kHPETInterruptRegValue (0x2C) ///! BUGS: 0 ///! @file HalTimer.cc @@ -53,7 +53,19 @@ HardwareTimer::HardwareTimer(UInt64 ms) auto hpet = (Detail::HPET_BLOCK*)power.Find("HPET").Leak().Leak(); MUST_PASS(hpet); - fDigitalTimer = (UIntPtr*)hpet->address.Address; + fDigitalTimer = (UInt8*)hpet->address.Address; + + if (hpet->page_protection) + { + HAL::mm_map_page((VoidPtr)fDigitalTimer, (VoidPtr)fDigitalTimer, HAL::kMMFlagsWr | HAL::kMMFlagsPCD | HAL::kMMFlagsPwt); + } + + // if not enabled yet. + if (!(*((volatile UInt64*)((UInt8*)fDigitalTimer + kHPETConfigRegValue)) & (1 << 0))) + { + *((volatile UInt64*)((UInt8*)fDigitalTimer + kHPETConfigRegValue)) = *((volatile UInt64*)((UInt8*)fDigitalTimer + kHPETConfigRegValue)) | (1 << 0); // enable timer + *((volatile UInt64*)((UInt8*)fDigitalTimer + kHPETConfigRegValue)) = *((volatile UInt64*)((UInt8*)fDigitalTimer + kHPETConfigRegValue)) | (1 << 3); // one shot conf + } } HardwareTimer::~HardwareTimer() @@ -62,25 +74,28 @@ HardwareTimer::~HardwareTimer() fWaitFor = 0; } +/***********************************************************************************/ +/// @brief Wait for the timer to stop spinning. +/***********************************************************************************/ + BOOL HardwareTimer::Wait() noexcept { if (fWaitFor < 1) return NO; - // if not enabled yet. - if (!(*(fDigitalTimer + cHPETConfigRegValue) & (1 << 0))) - { - *(fDigitalTimer + cHPETConfigRegValue) |= (1 << 0); // enable it - *(fDigitalTimer + cHPETConfigRegValue) |= (1 << 3); // one shot conf - } + UInt64 hpet_cap = *((volatile UInt64*)(fDigitalTimer + kHPETCounterRegValue)); + UInt64 femtoseconds_per_tick = (hpet_cap >> 32); + + if (femtoseconds_per_tick == 0) + return NO; - UInt64 ticks = fWaitFor / ((*(fDigitalTimer) >> 32) & __UINT32_MAX__); - UInt64 prev = *(fDigitalTimer + cHPETCounterRegValue); + volatile UInt64* timer = (volatile UInt64*)(fDigitalTimer + kHPETCounterRegValue); - prev += ticks; + UInt64 now = *timer; + UInt64 prev = now + (fWaitFor / femtoseconds_per_tick); - while (*(fDigitalTimer + cHPETCounterRegValue) < (ticks)) - ; + while (*timer < (prev)) + asm volatile("pause"); return YES; } diff --git a/dev/kernel/KernelKit/Timer.h b/dev/kernel/KernelKit/Timer.h index b6d23e6b..1d12876b 100644 --- a/dev/kernel/KernelKit/Timer.h +++ b/dev/kernel/KernelKit/Timer.h @@ -60,24 +60,24 @@ namespace Kernel BOOL Wait() noexcept override; private: - UIntPtr* fDigitalTimer{nullptr}; + volatile UInt8* fDigitalTimer{nullptr}; Int64 fWaitFor{0}; }; - inline Int64 rtl_ms(Int64 time) + inline Int64 rtl_microseconds(Int64 time) { if (time < 0) return 0; // TODO: nanoseconds maybe? - return kTimeUnit * kTimeUnit * time; + return kTimeUnit * time; } - inline Int64 rtl_seconds(Int64 time) + inline Int64 rtl_milliseconds(Int64 time) { if (time < 0) return 0; - return kTimeUnit * rtl_ms(time); + return kTimeUnit * kTimeUnit * time; } } // namespace Kernel diff --git a/dev/kernel/KernelKit/UserProcessScheduler.h b/dev/kernel/KernelKit/UserProcessScheduler.h index 53ee3476..ec16a0e2 100644 --- a/dev/kernel/KernelKit/UserProcessScheduler.h +++ b/dev/kernel/KernelKit/UserProcessScheduler.h @@ -20,7 +20,7 @@ #define kSchedMinMicroTime (AffinityKind::kStandard) #define kSchedInvalidPID (-1) #define kSchedProcessLimitPerTeam (32U) -#define kSchedTeamCount (512U) +#define kSchedTeamCount (256U) #define kSchedMaxMemoryLimit gib_cast(128) /* max physical memory limit */ #define kSchedMaxStackSz mib_cast(8) /* maximum stack size */ diff --git a/dev/kernel/src/BinaryMutex.cc b/dev/kernel/src/BinaryMutex.cc index c149b362..f9faadd2 100644 --- a/dev/kernel/src/BinaryMutex.cc +++ b/dev/kernel/src/BinaryMutex.cc @@ -67,7 +67,7 @@ namespace Kernel /***********************************************************************************/ BOOL BinaryMutex::WaitForProcess(const Int16& sec) noexcept { - HardwareTimer hw_timer(rtl_seconds(sec)); + HardwareTimer hw_timer(rtl_milliseconds(sec)); hw_timer.Wait(); return !this->IsLocked(); diff --git a/dev/kernel/src/UserProcessScheduler.cc b/dev/kernel/src/UserProcessScheduler.cc index 8df98f87..7aded611 100644 --- a/dev/kernel/src/UserProcessScheduler.cc +++ b/dev/kernel/src/UserProcessScheduler.cc @@ -31,8 +31,10 @@ namespace Kernel STATIC UInt32 kLastExitCode = 0U; + STATIC BOOL kCurrentlySwitching = No; + /***********************************************************************************/ - /// @brief External reference of the thread scheduler. + /// @brief Scheduler itself. /***********************************************************************************/ STATIC UserProcessScheduler kScheduler; @@ -470,6 +472,8 @@ namespace Kernel return 0UL; } + kCurrentlySwitching = Yes; + for (; process_index < mTeam.AsArray().Capacity(); ++process_index) { auto& process = mTeam.AsArray()[process_index]; @@ -502,6 +506,8 @@ namespace Kernel } } + kCurrentlySwitching = No; + return process_index; } @@ -524,6 +530,9 @@ namespace Kernel if (team.AsArray().Count() < 1) return No; + if (kCurrentlySwitching) + return No; + kScheduler.mTeam = team; return Yes; -- cgit v1.2.3