From 4e61e22c3da59b259741e57298725330791aed3e Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Mon, 21 Jul 2025 08:51:41 +0100 Subject: feat: NeKernel Semaphore API. includes: - New semaphore API for the kernel, we also make use of the HardwareTimer class here. - Defined header only for now. - New HAL HW Timer API in AMD64. Signed-off-by: Amlal El Mahrouss --- dev/kernel/HALKit/AMD64/HalTimer.cc | 18 ++++----- dev/kernel/KernelKit/KPC.h | 1 + dev/kernel/KernelKit/Semaphore.h | 79 ++++++++++++++++++++++++++++++++++++- 3 files changed, 88 insertions(+), 10 deletions(-) (limited to 'dev/kernel') diff --git a/dev/kernel/HALKit/AMD64/HalTimer.cc b/dev/kernel/HALKit/AMD64/HalTimer.cc index 13573880..ae3271f6 100644 --- a/dev/kernel/HALKit/AMD64/HalTimer.cc +++ b/dev/kernel/HALKit/AMD64/HalTimer.cc @@ -61,11 +61,8 @@ HardwareTimer::HardwareTimer(UInt64 ms) : fWaitFor(ms) { // 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 + *((volatile UInt64*) ((UInt8*) fDigitalTimer + kHPETConfigRegValue)) | (1 << 0) | + (1 << 3); // enable timer } } @@ -80,18 +77,21 @@ HardwareTimer::~HardwareTimer() { BOOL HardwareTimer::Wait() noexcept { if (fWaitFor < 1) return NO; + if (fWaitFor > 1'000'000) return NO; // max 1000s = 16 minutes - UInt64 hpet_cap = *((volatile UInt64*) (fDigitalTimer + kHPETCounterRegValue)); + UInt64 hpet_cap = *((volatile UInt64*) (fDigitalTimer)); UInt64 femtoseconds_per_tick = (hpet_cap >> 32); if (femtoseconds_per_tick == 0) return NO; volatile UInt64* timer = (volatile UInt64*) (fDigitalTimer + kHPETCounterRegValue); - UInt64 now = *timer; - UInt64 prev = now + (fWaitFor / femtoseconds_per_tick); + UInt64 now = *timer; + + UInt64 fs_wait = fWaitFor * 1'000'000'000'000ULL; + UInt64 stop_at = now + (fs_wait / femtoseconds_per_tick); - while (*timer < (prev)) asm volatile("pause"); + while (*timer < (stop_at)) asm volatile("pause"); return YES; } diff --git a/dev/kernel/KernelKit/KPC.h b/dev/kernel/KernelKit/KPC.h index a3b13de6..26d1b113 100644 --- a/dev/kernel/KernelKit/KPC.h +++ b/dev/kernel/KernelKit/KPC.h @@ -65,6 +65,7 @@ inline constexpr KPCError kErrorFileLocked = 64; inline constexpr KPCError kErrorDiskIsTooTiny = 65; inline constexpr KPCError kErrorDmaExhausted = 66; inline constexpr KPCError kErrorOutOfBitMapMemory = 67; +inline constexpr KPCError kErrorNetworkTimeout = 68; /// Generic errors. inline constexpr KPCError kErrorUnimplemented = -1; diff --git a/dev/kernel/KernelKit/Semaphore.h b/dev/kernel/KernelKit/Semaphore.h index a1b5ecad..7fa05008 100644 --- a/dev/kernel/KernelKit/Semaphore.h +++ b/dev/kernel/KernelKit/Semaphore.h @@ -6,10 +6,87 @@ #pragma once +/// @author Amlal El Mahrouss +/// @file Semaphore.h +/// @brief Semaphore structure and functions for synchronization in the kernel. + #include #include #include +#define kSemaphoreOwnerIndex (0) +#define kSemaphoreCountIndex (1) + +#define kSemaphoreCount (2) + namespace Kernel { -typedef Int64 Semaphore; +/// @brief Semaphore structure used for synchronization. +typedef UInt64 Semaphore[kSemaphoreCount]; + +/// @brief Checks if the semaphore is valid. +inline BOOL rtl_sem_is_valid(const Semaphore& sem) { + return sem[kSemaphoreOwnerIndex] != 0 || sem[kSemaphoreCountIndex] > 0; +} + +/// @brief Releases the semaphore, resetting its owner and count. +/// @param sem +/// @return +inline BOOL rtl_sem_release(Semaphore& sem) { + sem[kSemaphoreOwnerIndex] = 0; + sem[kSemaphoreCountIndex] = 0; + + return TRUE; +} + +/// @brief Initializes the semaphore with an owner and a count of zero. +/// @param sem +/// @param owner +/// @return +inline BOOL rtl_sem_init(Semaphore& sem, Int64 owner) { + if (!owner || sem[kSemaphoreOwnerIndex] > 0) { + return FALSE; + } + + sem[kSemaphoreOwnerIndex] = owner; + sem[kSemaphoreCountIndex] = 0; + + return TRUE; +} + +/// @brief Waits for the semaphore to be available, blocking until it is. +/// @param sem +/// @param timeout +/// @return +inline BOOL rtl_sem_wait(Semaphore& sem, Int64 timeout) { + if (!rtl_sem_is_valid(sem)) { + return FALSE; + } + + if (timeout <= 0) { + err_global_get() = kErrorNetworkTimeout; + + return FALSE; + } + + if (sem[kSemaphoreCountIndex] > 0) { + err_global_get() = kErrorSuccess; + sem[kSemaphoreCountIndex]--; + + return TRUE; + } + + HardwareTimer timer(timeout); + timer.Wait(); + + if (sem[kSemaphoreCountIndex] > 0) { + err_global_get() = kErrorSuccess; + sem[kSemaphoreCountIndex]--; + + return TRUE; + } + + err_global_get() = kErrorNetworkTimeout; + + return FALSE; // Failed to acquire semaphore +} // namespace Kernel } // namespace Kernel \ No newline at end of file -- cgit v1.2.3