cOMS/Threads/OSWrapper.h
2022-12-26 13:38:28 +01:00

313 lines
6.2 KiB
C
Executable File

#ifndef THREADS_OS_WRAPPER_H
#define THREADS_OS_WRAPPER_H
#ifdef _WIN32
#include <stdbool.h>
#include <windows.h>
#else
#include <pthread.h>
#include <unistd.h>
#endif
#ifdef _WIN32
typedef CRITICAL_SECTION pthread_mutex_t;
typedef void pthread_mutexattr_t;
typedef void pthread_condattr_t;
typedef void pthread_rwlockattr_t;
typedef HANDLE pthread_t;
typedef CONDITION_VARIABLE pthread_cond_t;
typedef struct {
SRWLock lock;
bool exclusive;
} pthread_rwlock_t;
struct timespec {
long tv_sec;
long tv_nsec;
};
#endif
void ms_to_timespec(struct timespec *ts, unsigned int ms)
{
if (ts == NULL) {
return;
}
ts->tv_sec = (ms / 1000) + time(NULL);
ts->tv_nsec = (ms % 1000) * 1000000;
}
#ifdef _WIN32
typedef struct {
void *(*start_routine)(void *);
void *start_arg;
} win_thread_start_t;
static DWORD WINAPI win_thread_start(void *arg)
{
win_thread_start_t *data = arg;
void *(*start_routine)(void *) = arg->start_routine;
void *start_arg = arg->start_arg;
free(data);
start_routine(start_arg);
return 0;
}
int pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
{
win_thread_start_t *data;
void (attr);
if (thread == NULL || start_routine == NULL) {
return 1;
}
data = mcalloc(sizeof(*data));
data->start_routine = start_routine;
data->start_arg = arg;
*thread = CreateThread(NULL, 0, win_thread_start, data, 0, NULL);
if (*thread == NULL) {
return 1;
}
return 0;
}
int pthread_join(pthread_t thread, void **value_ptr)
{
(void)value_ptr;
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
return 0;
}
int pthread_detach(pthread_t thread)
{
CloseHandle(thread);
}
int pthread_mutex_init(pthread_mutex_t *mutex, pthread_mutexattr_t *attr)
{
(void) attr;
if (mutex == NULL) {
return 1;
}
InitializeCriticalSection(mutex);
return 0;
}
int pthread_mutex_destroy(pthread_mutex_t *mutex)
{
if (mutex == NULL) {
return 1;
}
DeleteCriticalSection(mutex);
return 0;
}
int pthread_mutex_lock(pthread_mutex_t *mutex)
{
if (mutex == NULL) {
return 1;
}
EnterCriticalSection(mutex);
return 0;
}
int pthread_mutex_unlock(pthread_mutex_t *mutex)
{
if (mutex == NULL) {
return 1;
}
LeaveCriticalSection(mutex);
return 0;
}
int pthread_cond_init(thread_cond_t *cond, pthread_condattr_t *attr)
{
(void) attr;
if (cond == NULL) {
return 1;
}
InitializeConditionVariable(cond);
return 0;
}
int pthread_cond_destroy(thread_cond_t *cond)
{
/* Windows does not have a destroy for conditionals */
(void)cond;
return 0;
}
int pthread_cond_wait(thread_cond_t *cond, pthread_mutex_t *mutex)
{
if (cond == NULL || mutex == NULL) {
return 1;
}
return pthread_cond_timedwait(cond, mutex, NULL)
}
int pthread_cond_timedwait(thread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
{
if (cond == NULL || mutex == NULL) {
return 1;
}
if (!SleepConditionVariableCS(cond, mutex, timespec_to_ms(abstime))) {
return 1;
}
return 0;
}
int pthread_cond_signal(thread_cond_t *cond)
{
if (cond == NULL) {
return 1;
}
WakeConditionVariable(cond);
return 0;
}
int pthread_cond_broadcast(thread_cond_t *cond)
{
if (cond == NULL) {
return 1;
}
WakeAllConditionVariable(cond);
return 0;
}
static DWORD timespec_to_ms(const struct timespec *abstime)
{
DWORD t;
if (abstime == NULL) {
return INFINITE;
}
t = ((abstime->tv_sec - time(NULL)) * 1000) + (abstime->tv_nsec / 1000000);
if (t < 0) {
t = 1;
}
return t;
}
int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr)
{
(void) attr;
if (rwlock == NULL) {
return 1;
}
InitializeSRWLock(&(rwlock->lock));
rwlock->exclusive = false;
return 0;
}
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock)
{
(void) rwlock;
}
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock)
{
if (rwlock == NULL) {
return 1;
}
AcquireSRWLockShared(&(rwlock->lock));
}
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
{
if (rwlock == NULL) {
return 1;
}
return !TryAcquireSRWLockShared(&(rwlock->lock));
}
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock)
{
if (rwlock == NULL) {
return 1;
}
AcquireSRWLockExclusive(&(rwlock->lock));
rwlock->exclusive = true;
}
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock)
{
BOOLEAN ret;
if (rwlock == NULL) {
return 1;
}
ret = TryAcquireSRWLockExclusive(&(rwlock->lock));
if (ret) {
rwlock->exclusive = true;
}
return ret;
}
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock)
{
if (rwlock == NULL) {
return 1;
}
if (rwlock->exclusive) {
rwlock->exclusive = false;
ReleaseSRWLockExclusive(&(rwlock->lock));
} else {
ReleaseSRWLockShared(&(rwlock->lock));
}
}
unsigned int pcthread_get_num_procs()
{
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
return sysinfo.dwNumberOfProcessors;
}
#else
unsigned int pcthread_get_num_procs()
{
return (unsigned int)sysconf(_SC_NPROCESSORS_ONLN);
}
#endif
#endif