/* ------------------------------------------- Copyright (C) 2024-2025, Amlal El Mahrouss, all rights reserved. ------------------------------------------- */ #pragma once /// @author Amlal El Mahrouss /// @file Semaphore.h /// @brief Semaphore structure and functions for synchronization in the kernel. #include #include #include #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