#ifndef THREADS_OS_WRAPPER_H #define THREADS_OS_WRAPPER_H #ifdef _WIN32 #include #include #else #include #include #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