#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));
}