diff options
Diffstat (limited to 'src/kernel/KernelKit/Semaphore.h')
| -rw-r--r-- | src/kernel/KernelKit/Semaphore.h | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/src/kernel/KernelKit/Semaphore.h b/src/kernel/KernelKit/Semaphore.h new file mode 100644 index 00000000..831774a5 --- /dev/null +++ b/src/kernel/KernelKit/Semaphore.h @@ -0,0 +1,110 @@ +/* ======================================== + + Copyright (C) 2024-2025, Amlal El Mahrouss, licensed under the Apache 2.0 license. + +======================================== */ + +#pragma once + +/// @author Amlal El Mahrouss +/// @file Semaphore.h +/// @brief Semaphore structure and functions for synchronization in the kernel. + +#include <CompilerKit/CompilerKit.h> +#include <KernelKit/Timer.h> +#include <NeKit/Defines.h> + +#define kSemaphoreOwnerIndex (0U) +#define kSemaphoreCountIndex (1U) + +#define kSemaphoreCount (2U) + +#define kSemaphoreIncrementOwner(sem) (sem[kSemaphoreOwnerIndex]++) +#define kSemaphoreDecrementOwner(sem) (sem[kSemaphoreOwnerIndex]--) + +namespace Kernel { +/// @brief Semaphore structure used for synchronization. +typedef UInt64 SemaphoreArr[kSemaphoreCount]; + +/// @brief Checks if the semaphore is valid. +inline BOOL rtl_sem_is_valid(const SemaphoreArr& sem, UInt64 owner = 0) { + return sem[kSemaphoreOwnerIndex] == owner && sem[kSemaphoreCountIndex] > 0; +} + +/// @brief Releases the semaphore, resetting its owner and count. +/// @param sem +/// @return +inline BOOL rtl_sem_release(SemaphoreArr& sem) { + sem[kSemaphoreOwnerIndex] = 0; + sem[kSemaphoreCountIndex] = 0; + + return TRUE; +} + +/// @brief Initializes the semaphore with an owner and a count of zero. +/// @param sem the semaphore array to use. +/// @param owner the owner to set, could be anything identifitable. +/// @return +inline BOOL rtl_sem_acquire(SemaphoreArr& sem, UInt64 owner) { + if (!owner) { + err_global_get() = kErrorInvalidData; + return FALSE; // Invalid owner + } + + sem[kSemaphoreOwnerIndex] = owner; + sem[kSemaphoreCountIndex] = 0; + + return TRUE; +} + +/// @brief Waits for the semaphore to be available, blocking until it is. +/// @param sem +/// @param timeout +/// @param condition condition pointer. +/// @return +inline BOOL rtl_sem_wait(SemaphoreArr& sem, UInt64 owner, UInt64 timeout, + BOOL* condition = nullptr) { + if (!rtl_sem_is_valid(sem, owner)) { + return FALSE; + } + + if (timeout <= 0) { + err_global_get() = kErrorTimeout; + + return FALSE; + } + + if (!condition || *condition) { + if (sem[kSemaphoreCountIndex] == 0) { + err_global_get() = kErrorUnavailable; + return FALSE; + } + + err_global_get() = kErrorSuccess; + sem[kSemaphoreCountIndex]--; + + return TRUE; + } + + HardwareTimer timer(timeout); + BOOL ret = timer.Wait(); + + if (ret) { + if (!condition || *condition) { + if (sem[kSemaphoreCountIndex] == 0) { + err_global_get() = kErrorUnavailable; + return FALSE; + } + + err_global_get() = kErrorSuccess; + sem[kSemaphoreCountIndex]--; + + return TRUE; + } + } + + err_global_get() = kErrorTimeout; + + return FALSE; // Failed to acquire semaphore +} +} // namespace Kernel
\ No newline at end of file |
