git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/4] pthread: provide `pthread_once()` shims for Windows and for NO_PTHREADS

From
Johannes Schindelin via GitGitGadget <gitgitgadget@gmail.com>
Date
Sep 28, 2026, 15:51 UTC
Message-ID
<2f3077b60a7777b8d4c21551f9a8d02034a49cee.1790610691.git.gitgitgadget@gmail.com>
In-Reply-To
<pull.2240.git.1790610691.gitgitgadget@gmail.com>
From: Johannes Schindelin <johannes.schindelin@gmx.de>

I am about to introduce logic that needs to perform some initialization once, and once only, even if called concurrently.

This is a perfect job for `pthread_once()`, but Git's source code currently lacks a Win32 shim. So let's add one!

Also provide a trivial shim for `NO_PTHREAD` builds.
Assisted-by: GPT-6 Sol
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 compat/win32/pthread.c | 16 ++++++++++++++++
 compat/win32/pthread.h |  5 +++++
 thread-utils.h         | 16 ++++++++++++++++
 3 files changed, 37 insertions(+)
diff --git a/compat/win32/pthread.c b/compat/win32/pthread.c
index 398caa9602..5af95edd3b 100644
--- a/compat/win32/pthread.c
+++ b/compat/win32/pthread.c
@@ -60,6 +60,22 @@ pthread_t pthread_self(void)
 	return t;
 }
 
+static BOOL CALLBACK win32_pthread_once(PINIT_ONCE once UNUSED,
+					PVOID parameter,
+					PVOID *context UNUSED)
+{
+	(*(void (**)(void))parameter)();
+	return TRUE;
+}
+
+int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
+{
+	if (!InitOnceExecuteOnce(once_control, win32_pthread_once,
+				 &init_routine, NULL))
+		return err_win_to_posix(GetLastError());
+	return 0;
+}
+
 int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
 {
 	if (SleepConditionVariableCS(cond, mutex, INFINITE) == 0)
diff --git a/compat/win32/pthread.h b/compat/win32/pthread.h
index d80df8d12a..79a6bd9680 100644
--- a/compat/win32/pthread.h
+++ b/compat/win32/pthread.h
@@ -26,6 +26,11 @@ static inline int return_0(int i UNUSED) {
 #define pthread_mutex_lock EnterCriticalSection
 #define pthread_mutex_unlock LeaveCriticalSection
 
+typedef INIT_ONCE pthread_once_t;
+#define PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT
+
+int pthread_once(pthread_once_t *once_control, void (*init_routine)(void));
+
 typedef int pthread_mutexattr_t;
 #define pthread_mutexattr_init(a) (*(a) = 0)
 #define pthread_mutexattr_destroy(a) do {} while (0)
diff --git a/thread-utils.h b/thread-utils.h
index 4961487ed9..98b574eff4 100644
--- a/thread-utils.h
+++ b/thread-utils.h
@@ -19,6 +19,22 @@
 #define pthread_mutex_t int
 #define pthread_cond_t int
 #define pthread_key_t int
+#define pthread_once_t int
+#undef PTHREAD_ONCE_INIT
+#define PTHREAD_ONCE_INIT 0
+
+static inline int dummy_pthread_once(pthread_once_t *once_control,
+				      void (*init_routine)(void))
+{
+	if (!*once_control) {
+		init_routine();
+		*once_control = 1;
+	}
+	return 0;
+}
+
+#define pthread_once(once_control, init_routine) \
+	dummy_pthread_once((once_control), (init_routine))
 
 #define pthread_mutex_init(mutex, attr) dummy_pthread_init(mutex)
 #define pthread_mutex_lock(mutex)
-- 
gitgitgadget
Previous: Johannes Schindelin via GitGitGadgetNext: Johannes Schindelin via GitGitGadget
Message 5 of 9 in “Add a compile-time option to use the new, very fast sha1dc Rust crate”
  1. 0/4 Add a compile-time option to use the new, very fast sha1dc Rust crateJohannes Schindelin via GitGitGadget, Sep 28, 2026
  2. 1/4 libgitcore: add `sha1dc` as an optional featureJohannes Schindelin via GitGitGadget, Sep 28, 2026
  3. brian m. carlsonOct 3, 2026
  4. 2/4 sha1dc: allow selecting the C backend without rebuildingJohannes Schindelin via GitGitGadget, Sep 28, 2026
  5. 3/4 pthread: provide `pthread_once()` shims for Windows and for NO_PTHREADSJohannes Schindelin via GitGitGadget, Sep 28, 2026
  6. 4/4 sha1dc: make `sha1dc_init()` thread-safeJohannes Schindelin via GitGitGadget, Sep 28, 2026
  7. Johannes SchindelinSep 28, 2026
  8. Junio C HamanoSep 29, 2026
  9. Johannes SchindelinOct 3, 2026

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.