@@ -56,3 +56,21 @@ pthread_t pthread_self(void)
t.tid = GetCurrentThreadId();
return t;
}
+
+/* Adapted from libav's compat/w32pthreads.h. */
+int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
+{
+ BOOL pending = FALSE;
+ int ret = 0;
+
+ if (!InitOnceBeginInitialize(once_control, 0, &pending, NULL)) {
+ ret = err_win_to_posix(GetLastError());
+ } else if (pending) {
+ init_routine();
+ if (!InitOnceComplete(once_control, 0, NULL))
+ ret = err_win_to_posix(GetLastError());
+ }
+
+ /* POSIX doesn't allow pthread_once() to return EINTR */
+ return ret == EINTR ? EIO : ret;
+}
@@ -40,6 +40,11 @@ typedef int pthread_mutexattr_t;
#define pthread_cond_signal WakeConditionVariable
#define pthread_cond_broadcast WakeAllConditionVariable
+#define pthread_once_t INIT_ONCE
+
+#define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT
+int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
+
/*
* Simple thread creation implementation using pthread API
*/
@@ -122,4 +122,15 @@ int dummy_pthread_join(pthread_t pthread, void **retval)
return ENOSYS;
}
+int nothreads_pthread_once(pthread_once_t *once_control,
+ void (*init_routine)(void))
+{
+ if (*once_control == 1)
+ return 0;
+
+ init_routine();
+ *once_control = 1;
+ return 0;
+}
+
#endif
@@ -19,6 +19,7 @@
#define pthread_mutex_t int
#define pthread_cond_t int
#define pthread_key_t int
+#define pthread_once_t int
#define pthread_mutex_init(mutex, attr) dummy_pthread_init(mutex)
#define pthread_mutex_lock(mutex)
@@ -48,6 +49,12 @@ int dummy_pthread_join(pthread_t pthread, void **retval);
int dummy_pthread_init(void *);
+#define PTHREAD_ONCE_INIT 0
+#define pthread_once(once, routine) nothreads_pthread_once(once, routine)
+
+int nothreads_pthread_once(pthread_once_t *once_control,
+ void (*init_routine)(void));
+
#endif
int online_cpus(void);
Add pthread_once() emulation for Windows. This function provides an easy way to do thread-safe one-time initializations in multithreaded code. It will be used in the next commit to make hash_to_hex_algop() thread-safe. The pthread_once() implementation added comes from libav (https://git.libav.org/?p=libav.git), commit b22693b ("w32pthreads: Add pthread_once emulation", 2015-10-07). The code is licensed under LGPLv2.1 which is compatible with GPLv2. Only the section for support on Windows Vista+ has been ported, as that's the minimum version required to build Git for Windows. Also, the code was modified to (1) check and return error codes; and (2) do not call InitOnceComplete() again after a successful initialization, as that results in an error. Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br> --- compat/win32/pthread.c | 18 ++++++++++++++++++ compat/win32/pthread.h | 5 +++++ thread-utils.c | 11 +++++++++++ thread-utils.h | 7 +++++++ 4 files changed, 41 insertions(+)