#include <os/os.h> void semInit(semaphore_t* sem) { sem->owner = NULL; sem->locks = 0; } void semAcquire(semaphore_t* sem) { if (sem->owner == NULL || sem->owner == thrGetId()) { sem->owner = thrGetId(); sem->locks++; } else { if (sem->locks) asm("int3"); while (sem->locks) ; sem->owner = thrGetId(); sem->locks++; } } void semRelease(semaphore_t* sem) { sem->locks--; if (sem->locks == 0) sem->owner = NULL; } #if 0 //! Sets the thread's local storage pointer. /*! * The kernel reserves a 32-bits value for each thread for its own use. * This function can be used to set that value. * * \param value The 32-bit value to store for the current thread. */ void thrSetTls(dword value) { asm("int $0x30" : : "a" (0x104) : "b" (value)); } //! Retrieves the thread's local storage pointer. /*! * The kernel reserves a 32-bits value for each thread for its own use. * This function can be used to retrieve that value. * * \return The 32-bit value associated with the current thread. */ dword thrGetTls() { dword ret; asm("int $0x30" : "=a" (ret) : "a" (0x105)); return ret; } #endif //! Calls a function in the context of the current thread. /*! * Pushes the parameters provided onto the thread's stack. The function * will be called just before this function returns. * * \param addr A pointer to the function to be executed. To avoid * stack corruption, this function must be declared __stdcall. * \param params The parameters to be passed to the function. On the IA32 * architecture, these should be multiples of 32 bits in width and * aligned on 32-bit boundaries. * \param sizeof_params The size, in bytes, of the parameters pointed to * by params. This should be a multiple of 32 bits on the IA32 * architecture. */ void thrCall(void* addr, void* params, size_t sizeof_params) { asm("int $0x30" : : "a" (0x103), "b" (addr), "c" (params), "d" (sizeof_params)); } //! Pauses thread execution for the specified period. /*! * Puts the current thread into an efficient sleep state and schedules other * threads until the specified time has elapsed. * \param ms The time duration to sleep for, in milliseconds. */ void thrSleep(dword ms) { asm("int $0x30" : : "a" (0x100), "b" (ms)); } //! Pauses thread execution until the specified handle is signalled. /*! * Puts the current thread into an efficient sleep state and schedules other * threads until the specified handle is signalled. * \param hnd The handle to wait for. * The meaning of "signalled" varies according to the type of handle used: * + Processes and threads are signalled when they terminate. */ unsigned thrWaitHandle(addr_t* hnd, unsigned num_handles, bool wait_all) { unsigned r; asm("int $0x30" : "=a" (r) : "a" (0x101), "b" (hnd), "c" (num_handles), "d" (wait_all)); return r; } //! Returns the ID of the current thread. /*! * \return The ID of the current thread. This is guaranteed to be unique * within the current process. */ dword thrGetId() { return thrGetInfo()->tid; } addr_t thrCreate(void* entry_point, dword param, unsigned priority) { addr_t ret; asm("int $0x30" : "=a" (ret) : "a" (0x107), "b" (entry_point), "c" (param), "d" (priority)); return ret; } void thrExit(int code) { asm("int $0x30": : "a" (0x106), "b" (code)); }