2 * threads.c - Thread, mutex, and condition variable support. Wraps around
3 * pthreads or Windows native threads.
7 * Copyright 2016-2023 Eric Biggers
9 * This file is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU Lesser General Public License as published by the Free
11 * Software Foundation; either version 3 of the License, or (at your option) any
14 * This file is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this file; if not, see https://www.gnu.org/licenses/.
28 # include "wimlib/win32_common.h"
34 #include "wimlib/assert.h"
35 #include "wimlib/error.h"
36 #include "wimlib/threads.h"
37 #include "wimlib/util.h"
42 win32_thrproc(LPVOID lpParameter)
44 struct thread *t = (struct thread *)lpParameter;
46 (*t->thrproc)(t->arg);
50 bool thread_create(struct thread *t, void *(*thrproc)(void *), void *arg)
56 h = CreateThread(NULL, 0, win32_thrproc, (LPVOID)t, 0, NULL);
58 win32_error(GetLastError(), L"Failed to create thread");
61 t->win32_thread = (void *)h;
65 void thread_join(struct thread *t)
67 DWORD res = WaitForSingleObject((HANDLE)t->win32_thread, INFINITE);
69 wimlib_assert(res == WAIT_OBJECT_0);
72 bool mutex_init(struct mutex *m)
74 CRITICAL_SECTION *crit = MALLOC(sizeof(*crit));
78 InitializeCriticalSection(crit);
83 void mutex_destroy(struct mutex *m)
85 DeleteCriticalSection(m->win32_crit);
90 void mutex_lock(struct mutex *m)
92 CRITICAL_SECTION *crit = m->win32_crit;
94 if (unlikely(!crit)) {
95 CRITICAL_SECTION *old;
97 crit = MALLOC(sizeof(*crit));
98 wimlib_assert(crit != NULL);
99 InitializeCriticalSection(crit);
100 old = InterlockedCompareExchangePointer(&m->win32_crit, crit,
103 DeleteCriticalSection(crit);
108 EnterCriticalSection(crit);
111 void mutex_unlock(struct mutex *m)
113 LeaveCriticalSection(m->win32_crit);
116 bool condvar_init(struct condvar *c)
118 CONDITION_VARIABLE *cond = MALLOC(sizeof(*cond));
122 InitializeConditionVariable(cond);
123 c->win32_cond = cond;
127 void condvar_destroy(struct condvar *c)
130 c->win32_cond = NULL;
133 void condvar_wait(struct condvar *c, struct mutex *m)
135 BOOL ok = SleepConditionVariableCS(c->win32_cond, m->win32_crit,
140 void condvar_signal(struct condvar *c)
142 WakeConditionVariable(c->win32_cond);
145 void condvar_broadcast(struct condvar *c)
147 WakeAllConditionVariable(c->win32_cond);
152 bool thread_create(struct thread *t, void *(*thrproc)(void *), void *arg)
154 int err = pthread_create(&t->pthread, NULL, thrproc, arg);
158 ERROR_WITH_ERRNO("Failed to create thread");
164 void thread_join(struct thread *t)
166 int err = pthread_join(t->pthread, NULL);
168 wimlib_assert(err == 0);
171 bool mutex_init(struct mutex *m)
173 int err = pthread_mutex_init(&m->pthread_mutex, NULL);
177 ERROR_WITH_ERRNO("Failed to initialize mutex");
183 void mutex_destroy(struct mutex *m)
185 int err = pthread_mutex_destroy(&m->pthread_mutex);
187 wimlib_assert(err == 0);
190 void mutex_lock(struct mutex *m)
192 int err = pthread_mutex_lock(&m->pthread_mutex);
194 wimlib_assert(err == 0);
197 void mutex_unlock(struct mutex *m)
199 int err = pthread_mutex_unlock(&m->pthread_mutex);
201 wimlib_assert(err == 0);
204 bool condvar_init(struct condvar *c)
206 int err = pthread_cond_init(&c->pthread_cond, NULL);
210 ERROR_WITH_ERRNO("Failed to initialize condition variable");
216 void condvar_destroy(struct condvar *c)
218 int err = pthread_cond_destroy(&c->pthread_cond);
220 wimlib_assert(err == 0);
223 void condvar_wait(struct condvar *c, struct mutex *m)
225 int err = pthread_cond_wait(&c->pthread_cond, &m->pthread_mutex);
227 wimlib_assert(err == 0);
230 void condvar_signal(struct condvar *c)
232 int err = pthread_cond_signal(&c->pthread_cond);
234 wimlib_assert(err == 0);
237 void condvar_broadcast(struct condvar *c)
239 int err = pthread_cond_broadcast(&c->pthread_cond);
241 wimlib_assert(err == 0);