summaryrefslogtreecommitdiff
path: root/misc
diff options
context:
space:
mode:
authorIvan Zhakov <ivan@apache.org>2019-12-14 10:45:39 +0000
committerIvan Zhakov <ivan@apache.org>2019-12-14 10:45:39 +0000
commitc90021a5071ba646356fb1509a0cdff7416653b4 (patch)
tree2e4a61716deed375963fb907e7da61eea5499890 /misc
parentd5f961e6c40af43e0a3e1edf3005a661edb38075 (diff)
downloadapr-c90021a5071ba646356fb1509a0cdff7416653b4.tar.gz
win32: Rewrite late linking code (again) without using INIT_ONCE as groundwork
to backport r1866562 and 1859477 to APR 1.6.x and APR 1.7.x. It also slightly improves performance and reduce lock contention. * include/arch/win32/apr_arch_misc.h (apr_winapi_fpt_##fn): Declare as volatile and initialize to (ULONG_PTR) -1. (apr_winapi_ctrl_##fn, apr_winapi_init_once_##fn): Remove. (apr_winapi_ld_##fn): Concurrently invoke apr_load_dll_func() if apr_winapi_fpt_##fn == -1. * misc/win32/misc.c (win32_late_dll_t.control): Remove. (win32_late_dll_t.dll_handle): Declare as volatile. (late_dll): Initialize dll_handle to INVALID_HANDLE_VALUE (assume that is invalid module handle). (apr_load_dll_func): Concurrently load library if dll_handle == INVALID_HANDLE_VALUE. Then perform CAS and then free library if other thread performed initialization before. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1871447 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'misc')
-rw-r--r--misc/win32/misc.c75
1 files changed, 41 insertions, 34 deletions
diff --git a/misc/win32/misc.c b/misc/win32/misc.c
index 5136b9336..5631d2c9e 100644
--- a/misc/win32/misc.c
+++ b/misc/win32/misc.c
@@ -135,63 +135,70 @@ apr_status_t apr_get_oslevel(apr_oslevel_e *level)
*/
typedef struct win32_late_dll_t {
- INIT_ONCE control;
const apr_wchar_t *apiset_name;
const apr_wchar_t *dll_name;
- HMODULE dll_handle;
+ volatile HMODULE dll_handle;
} win32_late_dll_t;
static win32_late_dll_t late_dll[DLL_defined] = {
- {INIT_ONCE_STATIC_INIT, NULL, L"kernel32", NULL},
- {INIT_ONCE_STATIC_INIT, NULL, L"advapi32", NULL},
- {INIT_ONCE_STATIC_INIT, NULL, L"mswsock", NULL},
- {INIT_ONCE_STATIC_INIT, NULL, L"ws2_32", NULL},
- {INIT_ONCE_STATIC_INIT, NULL, L"shell32", NULL},
- {INIT_ONCE_STATIC_INIT, NULL, L"ntdll.dll", NULL},
- {INIT_ONCE_STATIC_INIT, NULL, L"Iphplapi", NULL},
- {INIT_ONCE_STATIC_INIT, L"api-ms-win-downlevel-shell32-l1-1-0.dll",
- L"shell32", NULL}
+ {NULL, L"kernel32", INVALID_HANDLE_VALUE},
+ {NULL, L"advapi32", INVALID_HANDLE_VALUE},
+ {NULL, L"mswsock", INVALID_HANDLE_VALUE},
+ {NULL, L"ws2_32", INVALID_HANDLE_VALUE},
+ {NULL, L"shell32", INVALID_HANDLE_VALUE},
+ {NULL, L"ntdll.dll", INVALID_HANDLE_VALUE},
+ {NULL, L"Iphplapi", INVALID_HANDLE_VALUE},
+ {L"api-ms-win-downlevel-shell32-l1-1-0.dll", L"shell32", INVALID_HANDLE_VALUE}
};
-static BOOL WINAPI load_dll_callback(PINIT_ONCE InitOnce,
- PVOID Parameter,
- PVOID *Context)
+FARPROC apr_load_dll_func(apr_dlltoken_e fnLib, char* fnName, int ordinal)
{
- win32_late_dll_t *dll = Parameter;
+ win32_late_dll_t *dll = &late_dll[fnLib];
+ HMODULE cached_dll_handle;
- /* Try api set dll first if defined. */
- if (dll->apiset_name) {
- dll->dll_handle = LoadLibraryExW(dll->apiset_name, NULL,
- LOAD_LIBRARY_SEARCH_SYSTEM32);
- }
+ /* Pointer sized reads are atomic on Windows. */
+ cached_dll_handle = dll->dll_handle;
+ if (cached_dll_handle == INVALID_HANDLE_VALUE) {
+ HMODULE dll_handle = NULL;
- if (!dll->dll_handle) {
- dll->dll_handle = LoadLibraryW(dll->dll_name);
- }
+ /* Try API Set dll first if defined. */
+ if (dll->apiset_name) {
+ dll_handle = LoadLibraryExW(dll->apiset_name, NULL,
+ LOAD_LIBRARY_SEARCH_SYSTEM32);
+ }
- return TRUE;
-}
+ if (!dll_handle) {
+ dll_handle = LoadLibraryW(dll->dll_name);
+ }
-FARPROC apr_load_dll_func(apr_dlltoken_e fnLib, char* fnName, int ordinal)
-{
- win32_late_dll_t *dll = &late_dll[fnLib];
+ cached_dll_handle = InterlockedCompareExchangePointer(&dll->dll_handle,
+ dll_handle,
+ INVALID_HANDLE_VALUE);
+ if (cached_dll_handle == INVALID_HANDLE_VALUE) {
+ cached_dll_handle = dll_handle;
+ }
+ else if (dll_handle) {
+ /* Other thread won the race: release our library handle. */
+ FreeLibrary(dll_handle);
+ }
+ }
- InitOnceExecuteOnce(&dll->control, load_dll_callback, dll, NULL);
- if (!dll->dll_handle)
+ if (!cached_dll_handle) {
return NULL;
+ }
#if defined(_WIN32_WCE)
if (ordinal)
- return GetProcAddressA(dll->dll_handle,
+ return GetProcAddressA(cached_dll_handle,
(const char *) (apr_ssize_t)ordinal);
else
- return GetProcAddressA(dll->dll_handle, fnName);
+ return GetProcAddressA(cached_dll_handle, fnName);
#else
if (ordinal)
- return GetProcAddress(dll->dll_handle,
+ return GetProcAddress(cached_dll_handle,
(const char *) (apr_ssize_t)ordinal);
else
- return GetProcAddress(dll->dll_handle, fnName);
+ return GetProcAddress(cached_dll_handle, fnName);
#endif
}