summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorivan <ivan@13f79535-47bb-0310-9956-ffa450edef68>2019-05-19 17:23:14 +0000
committerivan <ivan@13f79535-47bb-0310-9956-ffa450edef68>2019-05-19 17:23:14 +0000
commit437b16abfd8da06b85ca4b02213cc975a578c75d (patch)
tree4b4ca5431b3b66b50679dcaa07dc1142c0c571e9
parentc02ab86e6d82f9759a5ab1dcf0729414d39f5bcc (diff)
downloadlibapr-437b16abfd8da06b85ca4b02213cc975a578c75d.tar.gz
Use native one-time initialization [1] to implement apr_thread_once_t on
Windows. This also fixes problem that apr_thread_once() may return before the other read completes initialization on Windows. [1] https://docs.microsoft.com/en-gb/windows/desktop/Sync/one-time-initialization git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@1859517 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--CHANGES3
-rw-r--r--include/arch/win32/apr_arch_threadproc.h2
-rw-r--r--threadproc/win32/thread.c28
3 files changed, 28 insertions, 5 deletions
diff --git a/CHANGES b/CHANGES
index 743938bd9..0ba7700de 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
-*- coding: utf-8 -*-
Changes for APR 2.0.0
+ *) apr_thread_once: Fix problem that apr_thread_once can return before
+ the other thread completes initialization on Windows.
+
*) Windows platform: Remove support for Windows 2000, XP, Vista. The minimum
supported OS versions are now Windows 7 / Windows Server 2008 R2.
diff --git a/include/arch/win32/apr_arch_threadproc.h b/include/arch/win32/apr_arch_threadproc.h
index d3ce9c518..9aee660fd 100644
--- a/include/arch/win32/apr_arch_threadproc.h
+++ b/include/arch/win32/apr_arch_threadproc.h
@@ -65,7 +65,7 @@ struct apr_procattr_t {
};
struct apr_thread_once_t {
- long value;
+ INIT_ONCE once;
};
extern apr_status_t apr_threadproc_init(apr_pool_t *pool);
diff --git a/threadproc/win32/thread.c b/threadproc/win32/thread.c
index c713e1444..3204a1c2c 100644
--- a/threadproc/win32/thread.c
+++ b/threadproc/win32/thread.c
@@ -257,19 +257,39 @@ APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd,
return APR_SUCCESS;
}
-APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control,
+APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control_p,
apr_pool_t *p)
{
- (*control) = apr_pcalloc(p, sizeof(**control));
+ apr_thread_once_t *control = apr_pcalloc(p, sizeof(*control));
+
+ InitOnceInitialize(&control->once);
+
+ *control_p = control;
+
return APR_SUCCESS;
}
+static BOOL WINAPI init_once_callback(PINIT_ONCE InitOnce,
+ PVOID Parameter,
+ PVOID *Context)
+{
+ void (*func)(void) = Parameter;
+
+ func();
+
+ return TRUE;
+}
+
APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control,
void (*func)(void))
{
- if (!InterlockedExchange(&control->value, 1)) {
- func();
+ PVOID lpContext;
+
+ if (!InitOnceExecuteOnce(&control->once, init_once_callback, func,
+ &lpContext)) {
+ return apr_get_os_error();
}
+
return APR_SUCCESS;
}