Integrate uACPI
This commit is contained in:
290
kernel/hal/x86_64/uACPI/tests/runner/os.h
Normal file
290
kernel/hal/x86_64/uACPI/tests/runner/os.h
Normal file
@ -0,0 +1,290 @@
|
||||
#pragma once
|
||||
|
||||
#include "helpers.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#else
|
||||
#ifdef __WATCOMC__
|
||||
#include <process.h> // provides gettid
|
||||
#elif defined(__APPLE__)
|
||||
#include <mach/mach_time.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef CRITICAL_SECTION mutex_t;
|
||||
typedef CONDITION_VARIABLE condvar_t;
|
||||
#define HAVE_TIMED_WAIT 0
|
||||
#else
|
||||
typedef pthread_mutex_t mutex_t;
|
||||
typedef pthread_cond_t condvar_t;
|
||||
|
||||
#if defined(__WATCOMC__) || defined(__APPLE__)
|
||||
#define HAVE_TIMED_WAIT 0
|
||||
#else
|
||||
#define HAVE_TIMED_WAIT 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define NANOSECONDS_PER_SECOND 1000000000ull
|
||||
|
||||
static inline uint64_t get_nanosecond_timer(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
static LARGE_INTEGER frequency;
|
||||
LARGE_INTEGER counter;
|
||||
|
||||
if (frequency.QuadPart == 0)
|
||||
if (!QueryPerformanceFrequency(&frequency))
|
||||
error("QueryPerformanceFrequency failed");
|
||||
|
||||
if (!QueryPerformanceCounter(&counter))
|
||||
error("QueryPerformanceCounter failed");
|
||||
|
||||
counter.QuadPart *= NANOSECONDS_PER_SECOND;
|
||||
return counter.QuadPart / frequency.QuadPart;
|
||||
#elif defined(__APPLE__)
|
||||
static struct mach_timebase_info tb;
|
||||
static bool initialized;
|
||||
|
||||
if (!initialized) {
|
||||
if (mach_timebase_info(&tb) != KERN_SUCCESS)
|
||||
error("mach_timebase_info failed");
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
return (mach_absolute_time() * tb.numer) / tb.denom;
|
||||
#else
|
||||
struct timespec ts;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &ts))
|
||||
error("clock_gettime failed");
|
||||
|
||||
return ts.tv_sec * NANOSECONDS_PER_SECOND + ts.tv_nsec;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void *get_thread_id(void)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return (void*)((uintptr_t)GetCurrentThreadId());
|
||||
#elif defined(__APPLE__)
|
||||
uint64_t id;
|
||||
|
||||
if (pthread_threadid_np(NULL, &id))
|
||||
error("pthread_threadid_np failed");
|
||||
return (void*)id;
|
||||
#else
|
||||
return (void*)((uintptr_t)gettid());
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void millisecond_sleep(uint64_t milliseconds)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
Sleep(milliseconds);
|
||||
#else
|
||||
if (usleep(milliseconds * 1000))
|
||||
error("usleep failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void mutex_init(mutex_t *mutex)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
InitializeCriticalSection(mutex);
|
||||
#else
|
||||
if (pthread_mutex_init(mutex, NULL))
|
||||
error("pthread_mutex_init failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void mutex_free(mutex_t *mutex)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DeleteCriticalSection(mutex);
|
||||
#else
|
||||
if (pthread_mutex_destroy(mutex))
|
||||
error("pthread_mutex_destroy failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool mutex_try_lock(mutex_t *mutex)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return TryEnterCriticalSection(mutex);
|
||||
#else
|
||||
int err = pthread_mutex_trylock(mutex);
|
||||
|
||||
if (err == 0)
|
||||
return true;
|
||||
if (err != EBUSY)
|
||||
error("pthread_mutex_trylock failed");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void mutex_lock(mutex_t *mutex)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
EnterCriticalSection(mutex);
|
||||
#else
|
||||
if (pthread_mutex_lock(mutex))
|
||||
error("pthread_mutex_lock failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool mutex_lock_timeout(mutex_t *mutex, uint64_t timeout_ns)
|
||||
{
|
||||
#if !HAVE_TIMED_WAIT
|
||||
uint64_t end = get_nanosecond_timer() + timeout_ns;
|
||||
|
||||
do {
|
||||
if (mutex_try_lock(mutex))
|
||||
return true;
|
||||
millisecond_sleep(1);
|
||||
} while (get_nanosecond_timer() < end);
|
||||
|
||||
return false;
|
||||
#else
|
||||
struct timespec spec;
|
||||
int err;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &spec))
|
||||
error("clock_gettime failed");
|
||||
|
||||
spec.tv_nsec += timeout_ns;
|
||||
spec.tv_sec += spec.tv_nsec / NANOSECONDS_PER_SECOND;
|
||||
spec.tv_nsec %= NANOSECONDS_PER_SECOND;
|
||||
|
||||
err = pthread_mutex_clocklock(mutex, CLOCK_MONOTONIC, &spec);
|
||||
if (err == 0)
|
||||
return true;
|
||||
if (err != ETIMEDOUT)
|
||||
error("pthread_mutex_clocklock failed");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void mutex_unlock(mutex_t *mutex)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
LeaveCriticalSection(mutex);
|
||||
#else
|
||||
if (pthread_mutex_unlock(mutex))
|
||||
error("pthread_mutex_unlock failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void condvar_init(condvar_t *var)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
InitializeConditionVariable(var);
|
||||
#else
|
||||
if (pthread_cond_init(var, NULL))
|
||||
error("pthread_cond_init failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void condvar_free(condvar_t *var)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
UACPI_UNUSED(var);
|
||||
#else
|
||||
if (pthread_cond_destroy(var))
|
||||
error("pthread_cond_destroy failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
typedef bool (*condvar_pred_t)(void *ctx);
|
||||
|
||||
static inline void condvar_wait(
|
||||
condvar_t *var, mutex_t *mutex, condvar_pred_t pred, void *ctx
|
||||
)
|
||||
{
|
||||
while (!pred(ctx))
|
||||
#ifdef _WIN32
|
||||
if (!SleepConditionVariableCS(var, mutex, INFINITE))
|
||||
error("SleepConditionVariableCS failed");
|
||||
#else
|
||||
if (pthread_cond_wait(var, mutex))
|
||||
error("pthread_cond_wait failed");
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool condvar_wait_timeout(
|
||||
condvar_t *var, mutex_t *mutex, condvar_pred_t pred, void *ctx,
|
||||
uint64_t timeout_ns
|
||||
)
|
||||
{
|
||||
#if !HAVE_TIMED_WAIT
|
||||
uint64_t end = get_nanosecond_timer() + timeout_ns;
|
||||
|
||||
while (!pred(ctx)) {
|
||||
uint64_t cur = get_nanosecond_timer();
|
||||
#ifdef _WIN32
|
||||
DWORD milliseconds;
|
||||
#endif
|
||||
|
||||
if (cur >= end)
|
||||
return false;
|
||||
|
||||
#ifdef _WIN32
|
||||
milliseconds = (end - cur) / 1000;
|
||||
if (milliseconds == 0)
|
||||
milliseconds = 1;
|
||||
|
||||
if (!SleepConditionVariableCS(var, mutex, milliseconds) &&
|
||||
GetLastError() != ERROR_TIMEOUT) {
|
||||
error("SleepConditionVariableCS failed");
|
||||
}
|
||||
#else
|
||||
UACPI_UNUSED(var);
|
||||
mutex_unlock(mutex);
|
||||
millisecond_sleep(1);
|
||||
mutex_lock(mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
#else
|
||||
struct timespec spec;
|
||||
|
||||
if (clock_gettime(CLOCK_MONOTONIC, &spec))
|
||||
error("clock_gettime failed");
|
||||
|
||||
spec.tv_nsec += timeout_ns;
|
||||
spec.tv_sec += spec.tv_nsec / NANOSECONDS_PER_SECOND;
|
||||
spec.tv_nsec %= NANOSECONDS_PER_SECOND;
|
||||
|
||||
while (!pred(ctx)) {
|
||||
int err = pthread_cond_clockwait(var, mutex, CLOCK_MONOTONIC, &spec);
|
||||
|
||||
if (err == 0)
|
||||
continue;
|
||||
if (err != ETIMEDOUT)
|
||||
error("pthread_cond_clockwait failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void condvar_signal(condvar_t *var)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
WakeConditionVariable(var);
|
||||
#else
|
||||
if (pthread_cond_signal(var))
|
||||
error("pthread_cond_signal failed");
|
||||
#endif
|
||||
}
|
Reference in New Issue
Block a user