summaryrefslogtreecommitdiff
path: root/mysys/my_winthread.c
diff options
context:
space:
mode:
authorStaale Smedseng <staale.smedseng@sun.com>2009-12-12 19:11:25 +0100
committerStaale Smedseng <staale.smedseng@sun.com>2009-12-12 19:11:25 +0100
commit983770aa6aaa3ce7a231a80472e0ebb7095c9f86 (patch)
treee11d1534328b91e686c5a4590990a39cf3e6eeb6 /mysys/my_winthread.c
parent33aa8f59e26eb95f13bf059537f636785c1f68fd (diff)
downloadmariadb-git-983770aa6aaa3ce7a231a80472e0ebb7095c9f86.tar.gz
Bug #45058 init_available_charsets uses double checked locking
As documented in the bug report, the double checked locking pattern has inherent issues, and cannot guarantee correct initialization. This patch replaces the logic in init_available_charsets() with the use of pthread_once(3). A wrapper function, my_pthread_once(), is introduced and is used in lieu of direct calls to init_available_charsets(). Related defines MY_PTHREAD_ONCE_* are also introduced. For the Windows platform, the implementation in lp:sysbench is ported. For single-thread use, a simple define calls the function and sets the pthread_once control variable. Charset initialization is modified to use my_pthread_once().
Diffstat (limited to 'mysys/my_winthread.c')
-rw-r--r--mysys/my_winthread.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c
index e94369bec32..ef2a20c2ddc 100644
--- a/mysys/my_winthread.c
+++ b/mysys/my_winthread.c
@@ -137,4 +137,36 @@ int win_pthread_setspecific(void *a,void *b,uint length)
return 0;
}
+
+/*
+ One time initialization. For simplicity, we assume initializer thread
+ does not exit within init_routine().
+*/
+int my_pthread_once(my_pthread_once_t *once_control,
+ void (*init_routine)(void))
+{
+ LONG state= InterlockedCompareExchange(once_control, MY_PTHREAD_ONCE_INPROGRESS,
+ MY_PTHREAD_ONCE_INIT);
+ switch(state)
+ {
+ case MY_PTHREAD_ONCE_INIT:
+ /* This is initializer thread */
+ (*init_routine)();
+ *once_control= MY_PTHREAD_ONCE_DONE;
+ break;
+
+ case MY_PTHREAD_ONCE_INPROGRESS:
+ /* init_routine in progress. Wait for its completion */
+ while(*once_control == MY_PTHREAD_ONCE_INPROGRESS)
+ {
+ Sleep(1);
+ }
+ break;
+ case MY_PTHREAD_ONCE_DONE:
+ /* Nothing to do */
+ break;
+ }
+ return 0;
+}
+
#endif