From e36a776dc1070b4878b2b18538366fa369114f37 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sat, 28 Apr 2018 12:16:10 +0200 Subject: Implement thread-safe creation of proj mutex (fixes #954) --- src/pj_mutex.c | 70 +++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 23 deletions(-) diff --git a/src/pj_mutex.c b/src/pj_mutex.c index e734981f..80898a88 100644 --- a/src/pj_mutex.c +++ b/src/pj_mutex.c @@ -100,39 +100,40 @@ void pj_cleanup_lock() #include "pthread.h" -static pthread_mutex_t precreated_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t core_lock; -static int core_lock_created = 0; /************************************************************************/ -/* pj_acquire_lock() */ -/* */ -/* Acquire the PROJ.4 lock. */ +/* pj_create_lock() */ /************************************************************************/ -void pj_acquire_lock() +static void pj_create_lock() { - if (!core_lock_created) { - /* - ** We need to ensure the core mutex is created in recursive mode - ** and there is no portable way of doing that using automatic - ** initialization so we have precreated_lock only for the purpose - ** of protecting the creation of the core lock. - */ - pthread_mutexattr_t mutex_attr; - - pthread_mutex_lock( &precreated_lock); - - pthread_mutexattr_init(&mutex_attr); + /* + ** We need to ensure the core mutex is created in recursive mode + */ + pthread_mutexattr_t mutex_attr; + + pthread_mutexattr_init(&mutex_attr); #ifdef HAVE_PTHREAD_MUTEX_RECURSIVE - pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE); #else - pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE_NP); + pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE_NP); #endif - pthread_mutex_init(&core_lock, &mutex_attr); - core_lock_created = 1; + pthread_mutex_init(&core_lock, &mutex_attr); +} - pthread_mutex_unlock( &precreated_lock ); +/************************************************************************/ +/* pj_acquire_lock() */ +/* */ +/* Acquire the PROJ.4 lock. */ +/************************************************************************/ + +void pj_acquire_lock() +{ + static pthread_once_t sOnceKey = PTHREAD_ONCE_INIT; + if( pthread_once(&sOnceKey, pj_create_lock) != 0 ) + { + fprintf(stderr, "pthread_once() failed in pj_acquire_lock().\n"); } pthread_mutex_lock( &core_lock); @@ -170,6 +171,24 @@ void pj_cleanup_lock() static HANDLE mutex_lock = NULL; +#if _WIN32_WINNT >= 0x0600 + +/************************************************************************/ +/* pj_create_lock() */ +/************************************************************************/ + +static BOOL CALLBACK pj_create_lock(PINIT_ONCE InitOnce, + PVOID Parameter, + PVOID *Context) +{ + (void)InitOnce; + (void)Parameter; + (void)Context; + mutex_lock = CreateMutex( NULL, FALSE, NULL ); + return TRUE; +} +#endif + /************************************************************************/ /* pj_init_lock() */ /************************************************************************/ @@ -177,8 +196,13 @@ static HANDLE mutex_lock = NULL; static void pj_init_lock() { +#if _WIN32_WINNT >= 0x0600 + static INIT_ONCE sInitOnce = INIT_ONCE_STATIC_INIT; + InitOnceExecuteOnce( &sInitOnce, pj_create_lock, NULL, NULL ); +#else if( mutex_lock == NULL ) mutex_lock = CreateMutex( NULL, FALSE, NULL ); +#endif } /************************************************************************/ -- cgit v1.2.3