71 #if 0 // HACK removed because it gave problems in Windows 10... 72 const DWORD_PTR r = SetThreadAffinityMask(thr.
handle, (DWORD_PTR)mask);
82 for (
size_t i = 0; mask != 0; ++i, mask >>= 1)
85 int r = pthread_setaffinity_np(thr.
handle,
sizeof(cpu_set_t), &cpuset);
105 result.id = GetCurrentThreadId();
107 result.
handle = pthread_self();
130 if (!CloseHandle(thr.
handle))
133 int r = pthread_detach(thr.
handle);
149 _endthreadex((
unsigned int)res);
151 pthread_exit((
void*)(intptr_t)res);
159 return lhs.id == rhs.id;
169 uint32_t sec = (ms / 1000);
170 uint32_t nsec = (ms - sec * 1000) * 1000000;
171 clock_gettime(CLOCK_REALTIME, &ts);
175 ts.tv_sec += ts.tv_nsec / 1000000000;
176 ts.tv_nsec = ts.tv_nsec % 1000000000;
186 if (sem_init(s, 0, 0) != 0)
189 const HANDLE sem = CreateSemaphoreA(NULL, 0, 1, NULL);
203 if (sem_init(s, 0, 0) != 0)
206 const HANDLE semaphore = CreateSemaphoreA(NULL, 0, MAXLONG, NULL);
207 if (semaphore == NULL)
220 if (sem_destroy(s) != 0)
223 if (!CloseHandle(*s))
237 r = (sem_timedwait(s, &(
struct timespec){ 0 }) == 0) ? 0 : errno;
240 r = (sem_wait(s) == 0) ? 0 : errno;
244 r = (sem_timedwait(s, &ts) == 0) ? 0 : errno;
259 const DWORD r = WaitForSingleObjectEx(*s, (DWORD)ms,
FALSE);
279 if (sem_post(s) != 0)
282 if (!ReleaseSemaphore(*s, 1, NULL))
293 const int r = pthread_mutex_init(m, NULL);
307 const HANDLE mutex = CreateMutexA(NULL,
FALSE, NULL);
321 const int r = pthread_mutex_lock(m);
334 if (r != WAIT_OBJECT_0)
345 const int r = pthread_mutex_trylock(m);
359 const DWORD ms_wait = 0;
360 const DWORD r = WaitForSingleObjectEx(*m, ms_wait,
FALSE);
361 if (r != WAIT_OBJECT_0)
372 const int r = pthread_mutex_unlock(m);
384 if (!ReleaseMutex(*m))
395 const int r = pthread_mutex_destroy(m);
408 if (!CloseHandle(*m))
416 InitializeConditionVariable(&(cond->
_cond));
417 InitializeCriticalSection(&(cond->_critical_section));
419 if (pthread_cond_init(&(cond->
_cond), NULL) != 0)
429 DeleteCriticalSection(&(cond->_critical_section));
431 if (pthread_cond_destroy(&(cond->
_cond)) != 0)
441 EnterCriticalSection(&(cond->_critical_section));
450 LeaveCriticalSection(&(cond->_critical_section));
460 if (!SleepConditionVariableCS(&(cond->
_cond), &(cond->_critical_section), (DWORD)ms)) {
461 switch (GetLastError()) {
474 r = (pthread_cond_timedwait(&(cond->
_cond), &(cond->
_mutex), &(
struct timespec){ 0 }) == 0) ? 0 : errno;
477 r = (pthread_cond_wait(&(cond->
_cond), &(cond->
_mutex)) == 0) ? 0 : errno;
481 r = (pthread_cond_timedwait(&(cond->
_cond), &(cond->
_mutex), &ts) == 0) ? 0 : errno;
504 WakeConditionVariable(&(cond->
_cond));
506 const int r = pthread_cond_signal(&(cond->
_cond));
522 WakeAllConditionVariable(&(cond->
_cond));
524 const int r = pthread_cond_broadcast(&(cond->
_cond));
537 int32_t
c_thread_sleep(
const struct timespec* duration,
struct timespec* remaining) {
540 struct timespec start;
541 if (timespec_get(&start, TIME_UTC) == 0)
543 const DWORD ms = (DWORD)(duration->tv_sec * 1000 + duration->tv_nsec / 1000000 + (((duration->tv_nsec % 1000000) == 0) ? 0 : 1));
544 const DWORD r = SleepEx(ms,
TRUE);
546 if (remaining != NULL) {
547 if (timespec_get(remaining, TIME_UTC) == 0)
549 remaining->tv_sec -= start.tv_sec;
550 remaining->tv_nsec -= start.tv_nsec;
551 if (remaining->tv_nsec < 0) {
552 remaining->tv_nsec += 1000000000;
553 remaining->tv_sec -= 1;
556 ret = (r == WAIT_IO_COMPLETION) ? -1 : -2;
559 const int r = nanosleep(duration, remaining);
561 ret = (errno == EINTR) ? -1 : -2;
570 SleepEx((DWORD)ms,
FALSE);
573 const int r = usleep(ms * 1000);
605 return (
void*)(intptr_t)r;
611 #ifdef _WIN32 // Windows 624 if (wrapper == NULL) {
629 #ifdef _WIN32 // Windows 631 if (thr->
handle == NULL) {
665 r = pthread_join(thr.
handle, &lres);
669 r = pthread_timedjoin_np(thr.
handle, &lres, &ts);
690 *res = (int)(intptr_t)lres;
693 const DWORD r = WaitForSingleObjectEx(thr.
handle, (DWORD)ms,
FALSE);
707 if (!GetExitCodeThread(thr.
handle, &lres)) {
713 if (!CloseHandle(thr.
handle))
int32_t c_ticket_lock(c_ticket_t *ticket)
int32_t c_mutex_lock(c_mutex_t *m)
c_conditionvariable_t _cond
A condition variable.
int32_t c_semaphore_destroy(c_semaphore_t *s)
int32_t c_condition_unlock(c_condition_t *cond)
int32_t c_semaphore_post(c_semaphore_t *s)
int32_t c_mutex_init(c_mutex_t *m)
int32_t c_semaphore_wait(c_semaphore_t *s, int32_t ms)
#define c_unused_parameter(P)
Platform independent macro to remove unreferenced parameter warning.
int32_t c_condition_broadcast(c_condition_t *cond)
Main header and generic tools.
int32_t c_mutex_destroy(c_mutex_t *m)
int32_t c_semaphore_init(c_semaphore_t *s)
int32_t c_ticket_init(c_ticket_t *ticket)
int32_t c_thread_create(c_thread_t *thr, c_tstart_t t, void *arg)
int32_t c_sleep(uint32_t ms)
int32_t c_ticket_unlock(c_ticket_t *ticket)
c_thread_t _holding_thread_id
int32_t c_condition_lock(c_condition_t *cond)
c_thread_t c_thread_current(void)
int32_t c_thread_detach(c_thread_t thr)
c_thread_t c_thread_invalid()
pthread_mutex_t _mutex
On Linux a pthread_cond_t is use with a pthread_mutex_t.
void c_thread_exit(int res)
Functions to handle threads, inspired to C11 threads.h.
void * c_malloc(size_t size)
Generic wrappers to platform-dependent functions.
int32_t c_thread_join(c_thread_t thr, int *res)
int32_t c_ticket_delete(c_ticket_t *ticket)
int32_t c_mutex_trylock(c_mutex_t *m)
#define INIT_C_LOGGER(fname, mname)
void c_thread_yield(void)
static uint64_t _getnewticketnumber(c_ticket_t *ticket)
sem_t c_semaphore_t
Semaphore type.
int32_t c_condition_destroy(c_condition_t *cond)
int32_t c_condition_wait(c_condition_t *cond, int32_t ms)
int32_t c_condition_init(c_condition_t *cond)
pthread_mutex_t c_mutex_t
Mutex type.
#define c_use_decl_annotations
int32_t c_semaphore_multi_init(c_semaphore_t *s)
int(* c_tstart_t)(void *)
Thread function type, as defined in C11.
int32_t c_thread_setaffinity(c_thread_t thr, uint64_t mask)
int32_t c_thread_sleep(const struct timespec *duration, struct timespec *remaining)
int32_t c_mutex_unlock(c_mutex_t *m)
static struct timespec _getTimeSpecFromNow(uint32_t ms)
bool c_thread_equal(c_thread_t lhs, c_thread_t rhs)
int32_t c_condition_signal_one(c_condition_t *cond)
static void * _tstart_wrapper_function(void *_arg)
int32_t c_thread_timedjoin(c_thread_t thr, int *res, int32_t ms)
Needed because a condition variable on Linux is associated with a mutex, while on Windows it is assoc...