26 #if !LELY_NO_THREADS && _WIN32 && !LELY_HAVE_PTHREAD_H 38 struct once_info *next;
48 static volatile LONG once_lock;
54 static struct once_info *once_list;
60 static struct once_info once_fast;
95 static thread_local
struct thrd_info *thrd_self;
101 static void thrd_start(
void *arglist);
110 if (InterlockedCompareExchange(flag, 0, 0))
113 struct once_info *info;
114 struct once_info **pinfo;
117 while (InterlockedCompareExchange(&once_lock, 1, 0))
122 for (pinfo = &once_list; *pinfo && (*pinfo)->flag != flag;
123 pinfo = &(*pinfo)->next)
130 info = malloc(
sizeof(*info));
143 InterlockedExchange(&once_lock, 0);
147 if (!InterlockedCompareExchange(info->flag, 0, 0)) {
149 InterlockedExchange(info->flag, 1);
153 while (InterlockedCompareExchange(&once_lock, 1, 0))
158 for (pinfo = &once_list; (*pinfo)->flag != flag;
159 pinfo = &(*pinfo)->next)
166 if (info == &once_fast)
172 InterlockedExchange(&once_lock, 0);
178 WakeAllConditionVariable(cond);
192 InitializeConditionVariable(cond);
200 WakeConditionVariable(cond);
208 struct timespec now = { 0, 0 };
213 LONGLONG llMilliseconds =
214 (LONGLONG)(ts->tv_sec - now.tv_sec) * 1000
215 + (ts->tv_nsec - now.tv_nsec + 999999l)
217 if (llMilliseconds < 0)
219 DWORD dwMilliseconds = llMilliseconds <= MAX_SLEEP_MS
220 ? (DWORD)llMilliseconds
222 DWORD dwResult = SleepConditionVariableCS(
223 cond, mtx, dwMilliseconds);
226 if (GetLastError() != ERROR_TIMEOUT)
230 }
while (now.tv_sec < ts->tv_sec || (now.tv_sec == ts->tv_sec
231 && now.tv_nsec < ts->tv_nsec));
240 return SleepConditionVariableCS(cond, mtx, INFINITE)
249 DeleteCriticalSection(mtx);
258 InitializeCriticalSection(mtx);
266 EnterCriticalSection(mtx);
289 LeaveCriticalSection(mtx);
297 struct thrd_info *info = malloc(
sizeof(*info));
307 info->stat = THRD_STARTED;
309 if (_beginthread(&thrd_start, 0, info) == (uintptr_t)-1) {
330 struct thrd_info *info = (
struct thrd_info *)thr;
333 if (info->stat == THRD_STOPPED) {
340 assert(info->stat != THRD_DETACHED);
341 info->stat = THRD_DETACHED;
357 struct thrd_info *info = (
struct thrd_info *)
thrd_current();
362 if (info->stat == THRD_DETACHED) {
369 assert(info->stat != THRD_STOPPED);
370 info->stat = THRD_STOPPED;
383 struct thrd_info *info = (
struct thrd_info *)thr;
386 while (info->stat == THRD_STARTED) {
390 if (info->stat != THRD_STOPPED) {
407 thrd_sleep(
const struct timespec *duration,
struct timespec *remaining)
410 int res = nanosleep(duration, remaining);
412 res = errno == EINTR ? -1 : -2;
427 DWORD dwFlsIndex = FlsAlloc(dtor);
428 if (dwFlsIndex == FLS_OUT_OF_INDEXES)
445 return FlsGetValue(key);
455 thrd_start(
void *arglist)
459 struct thrd_info *info = (
struct thrd_info *)
thrd_current();
464 #endif // !LELY_NO_THREADS && _WIN32 && !LELY_HAVE_PTHREAD_H int mtx_trylock(mtx_t *mtx)
Endeavors to lock the mutex at mtx.
void mtx_destroy(mtx_t *mtx)
Releases any resources used by the mutex at mtx.
int cnd_signal(cnd_t *cond)
Unblocks one of the threads that are blocked on the condition variable at cond at the time of the cal...
_Noreturn void thrd_exit(int res)
Terminates execution of the calling thread and sets its result code to res.
Indicates that the time specified in the call was reached without acquiring the requested resource...
Indicates that the requested operation succeeded.
int timespec_get(struct timespec *ts, int base)
Sets the interval at ts to hold the current calendar time based on the specified time base...
int thrd_detach(thrd_t thr)
Tells the operating system to dispose of any resources allocated to the thread identified by thr when...
pthread_t thrd_t
A complete object type that holds an identifier for a thread.
Indicates that the requested operation failed.
A mutex type that supports neither timeout nor test and return.
void * tss_get(tss_t key)
Returns the value for the current thread held in the thread-specific storage identified by key...
int mtx_unlock(mtx_t *mtx)
Unlocks the mutex at mtx.
pthread_key_t tss_t
A complete object type that holds an identifier for a thread-specific storage pointer.
Indicates that the requested operation failed because it was unable to allocate memory.
int thrd_sleep(const struct timespec *duration, struct timespec *remaining)
Suspends execution of the calling thread until either the interval specified by duration has elapsed ...
This header file is part of the C11 and POSIX compatibility library; it includes <threads.h>, if it exists, and defines any missing functionality.
int mtx_lock(mtx_t *mtx)
Blocks until it locks the mutex at mtx.
thrd_t thrd_current(void)
Identifies the thread that called it.
pthread_cond_t cnd_t
A complete object type that holds an identifier for a condition variable.
pthread_mutex_t mtx_t
A complete object type that holds an identifier for a mutex.
int thrd_join(thrd_t thr, int *res)
Joins the thread identified by thr with the current thread by blocking until the other thread has ter...
int cnd_init(cnd_t *cond)
Creates a condition variable.
int mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
Endeavors to block until it locks the mutex at mtx or until after the TIME_UTC-based calendar time at...
pthread_once_t once_flag
A complete object type that holds a flag for use by call_once().
int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
Atomically unlocks the mutex at mtx and endeavors to block until the condition variable at cond is si...
int thrd_equal(thrd_t thr0, thrd_t thr1)
Determines whether the thread identified by thr0 refers to the thread identified by thr1...
int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
Creates a new thread executing func(arg).
void thrd_yield(void)
Endeavors to permit other threads to run, even if the current thread would ordinarily continue to run...
Indicates that the requested operation failed because a resource requested by a test and return funct...
void call_once(once_flag *flag, void(*func)(void))
Uses the once_flag at flag to ensure that func is called exactly once, the first time the call_once()...
int tss_set(tss_t key, void *val)
Sets the value for the current thread held in the thread-specific storage identified by key to val...
int cnd_wait(cnd_t *cond, mtx_t *mtx)
Atomically unlocks the mutex at mtx and endeavors to block until the condition variable at cond is si...
This header file is part of the C11 and POSIX compatibility library; it includes <stdint.h> and defines any missing functionality.
int(* thrd_start_t)(void *)
The function pointer type that is passed to thrd_create() to create a new thread. ...
void cnd_destroy(cnd_t *cond)
Releases all resources used by the condition variable at cond.
A mutex type that supports timeout (not available with the native Windows API).
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib.h> and defines any missing functionality.
#define _Noreturn
A function declared with a _Noreturn function specifier SHALL not return to its caller.
int tss_create(tss_t *key, tss_dtor_t dtor)
Creates a thread-specific storage pointer with destructor dtor, which may be NULL.
void tss_delete(tss_t key)
Releases any resources used by the thread-specific storage identified by key.
This is the internal header file of the C11 and POSIX compatibility library.
void(* tss_dtor_t)(void *)
The function pointer type used for a destructor for a thread-specific storage pointer.
int cnd_broadcast(cnd_t *cond)
Unblocks all of the threads that are blocked on the condition variable at cond at the time of the cal...
int mtx_init(mtx_t *mtx, int type)
Creates a mutex object with properties indicated by type, which must have one of the four values: ...