diff options
author | Xanadu <xanadu.xoroi@gmail.com> | 2011-03-05 00:50:00 +0100 |
---|---|---|
committer | Xanadu <xanadu.xoroi@gmail.com> | 2011-03-05 02:41:59 +0100 |
commit | c47c94f958dd11be44bad16cd5d97d9f2fea6dbf (patch) | |
tree | f4849f06a2b5bbda7036d07efde8d393ac54e620 /dep/mysqllite/include/my_pthread.h | |
parent | ed148818942fab299f344cb9c421a4df0b09fb98 (diff) |
Dep/MySQL: Updated MySQL sources to version 5.5.9 (current GA)
Diffstat (limited to 'dep/mysqllite/include/my_pthread.h')
-rw-r--r-- | dep/mysqllite/include/my_pthread.h | 401 |
1 files changed, 282 insertions, 119 deletions
diff --git a/dep/mysqllite/include/my_pthread.h b/dep/mysqllite/include/my_pthread.h index fec7c972a7b..f1636cad136 100644 --- a/dep/mysqllite/include/my_pthread.h +++ b/dep/mysqllite/include/my_pthread.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 MySQL AB +/* Copyright (C) 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,6 +18,8 @@ #ifndef _my_pthread_h #define _my_pthread_h +#include "my_global.h" /* myf */ + #ifndef ETIME #define ETIME ETIMEDOUT /* For FreeBSD */ #endif @@ -31,11 +33,10 @@ extern "C" { #if defined(__WIN__) typedef CRITICAL_SECTION pthread_mutex_t; -typedef HANDLE pthread_t; +typedef DWORD pthread_t; typedef struct thread_attr { DWORD dwStackSize ; DWORD dwCreatingFlag ; - int priority ; } pthread_attr_t ; typedef struct { int dummy; } pthread_condattr_t; @@ -47,25 +48,35 @@ typedef struct st_pthread_link { struct st_pthread_link *next; } pthread_link; -typedef struct { - uint32 waiting; - CRITICAL_SECTION lock_waiting; - - enum { - SIGNAL= 0, - BROADCAST= 1, - MAX_EVENTS= 2 - } EVENTS; - - HANDLE events[MAX_EVENTS]; - HANDLE broadcast_block_event; - +/** + Implementation of Windows condition variables. + We use native conditions on Vista and later, and fallback to own + implementation on earlier OS version. +*/ +typedef union +{ + /* Native condition (used on Vista and later) */ + CONDITION_VARIABLE native_cond; + + /* Own implementation (used on XP) */ + struct + { + uint32 waiting; + CRITICAL_SECTION lock_waiting; + enum + { + SIGNAL= 0, + BROADCAST= 1, + MAX_EVENTS= 2 + } EVENTS; + HANDLE events[MAX_EVENTS]; + HANDLE broadcast_block_event; + }; } pthread_cond_t; typedef int pthread_mutexattr_t; -#define win_pthread_self my_thread_var->pthread_self -#define pthread_self() win_pthread_self +#define pthread_self() GetCurrentThreadId() #define pthread_handler_t EXTERNC void * __cdecl typedef void * (__cdecl *pthread_handler)(void *); @@ -104,10 +115,22 @@ struct timespec { (ABSTIME).max_timeout_msec= (long)((NSEC)/1000000); \ } -void win_pthread_init(void); -int win_pthread_setspecific(void *A,void *B,uint length); +/** + Compare two timespec structs. + + @retval 1 If TS1 ends after TS2. + + @retval 0 If TS1 is equal to TS2. + + @retval -1 If TS1 ends before TS2. +*/ +#define cmp_timespec(TS1, TS2) \ + ((TS1.tv.i64 > TS2.tv.i64) ? 1 : \ + ((TS1.tv.i64 < TS2.tv.i64) ? -1 : 0)) + + int win_pthread_mutex_trylock(pthread_mutex_t *mutex); -int pthread_create(pthread_t *,pthread_attr_t *,pthread_handler,void *); +int pthread_create(pthread_t *, const pthread_attr_t *, pthread_handler, void *); int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr); int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, @@ -117,69 +140,50 @@ int pthread_cond_broadcast(pthread_cond_t *cond); int pthread_cond_destroy(pthread_cond_t *cond); int pthread_attr_init(pthread_attr_t *connect_att); int pthread_attr_setstacksize(pthread_attr_t *connect_att,DWORD stack); -int pthread_attr_setprio(pthread_attr_t *connect_att,int priority); int pthread_attr_destroy(pthread_attr_t *connect_att); int my_pthread_once(my_pthread_once_t *once_control,void (*init_routine)(void)); struct tm *localtime_r(const time_t *timep,struct tm *tmp); struct tm *gmtime_r(const time_t *timep,struct tm *tmp); +void pthread_exit(void *a); +int pthread_join(pthread_t thread, void **value_ptr); +int pthread_cancel(pthread_t thread); -void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/ - +#ifndef ETIMEDOUT #define ETIMEDOUT 145 /* Win32 doesn't have this */ -#define getpid() GetCurrentThreadId() +#endif #define HAVE_LOCALTIME_R 1 #define _REENTRANT 1 #define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1 -/* - Windows has two ways to use thread local storage. The most efficient - is using __declspec(thread), but that does not work properly when - used in a .dll that is loaded at runtime, after program load. So for - libmysql.dll and libmysqld.dll we define USE_TLS in order to use the - TlsXxx() API instead, which works in all cases. -*/ -#ifdef USE_TLS /* For LIBMYSQL.DLL */ + #undef SAFE_MUTEX /* This will cause conflicts */ #define pthread_key(T,V) DWORD V #define pthread_key_create(A,B) ((*A=TlsAlloc())==0xFFFFFFFF) #define pthread_key_delete(A) TlsFree(A) +#define my_pthread_setspecific_ptr(T,V) (!TlsSetValue((T),(V))) +#define pthread_setspecific(A,B) (!TlsSetValue((A),(B))) #define pthread_getspecific(A) (TlsGetValue(A)) #define my_pthread_getspecific(T,A) ((T) TlsGetValue(A)) #define my_pthread_getspecific_ptr(T,V) ((T) TlsGetValue(V)) -#define my_pthread_setspecific_ptr(T,V) (!TlsSetValue((T),(V))) -#define pthread_setspecific(A,B) (!TlsSetValue((A),(B))) -#else -#define pthread_key(T,V) __declspec(thread) T V -#define pthread_key_create(A,B) pthread_dummy(0) -#define pthread_key_delete(A) pthread_dummy(0) -#define pthread_getspecific(A) (&(A)) -#define my_pthread_getspecific(T,A) (&(A)) -#define my_pthread_getspecific_ptr(T,V) (V) -#define my_pthread_setspecific_ptr(T,V) ((T)=(V),0) -#define pthread_setspecific(A,B) win_pthread_setspecific(&(A),(B),sizeof(A)) -#endif /* USE_TLS */ #define pthread_equal(A,B) ((A) == (B)) #define pthread_mutex_init(A,B) (InitializeCriticalSection(A),0) #define pthread_mutex_lock(A) (EnterCriticalSection(A),0) #define pthread_mutex_trylock(A) win_pthread_mutex_trylock((A)) -#define pthread_mutex_unlock(A) LeaveCriticalSection(A) -#define pthread_mutex_destroy(A) DeleteCriticalSection(A) -#define my_pthread_setprio(A,B) SetThreadPriority(GetCurrentThread(), (B)) +#define pthread_mutex_unlock(A) (LeaveCriticalSection(A), 0) +#define pthread_mutex_destroy(A) (DeleteCriticalSection(A), 0) #define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH) -#define pthread_join(A,B) (WaitForSingleObject((A), INFINITE) != WAIT_OBJECT_0) /* Dummy defines for easier code */ #define pthread_attr_setdetachstate(A,B) pthread_dummy(0) -#define my_pthread_attr_setprio(A,B) pthread_attr_setprio(A,B) #define pthread_attr_setscope(A,B) #define pthread_detach_this_thread() #define pthread_condattr_init(A) #define pthread_condattr_destroy(A) - -#define my_pthread_getprio(thread_id) pthread_dummy(0) +#define pthread_yield() SwitchToThread() +#define my_sigset(A,B) signal(A,B) #else /* Normal threads */ @@ -202,13 +206,6 @@ void pthread_exit(void *a); /* was #define pthread_exit(A) ExitThread(A)*/ #include <synch.h> #endif -#ifdef __NETWARE__ -void my_pthread_exit(void *status); -#define pthread_exit(A) my_pthread_exit(A) -#endif - -extern int my_pthread_getprio(pthread_t thread_id); - #define pthread_key(T,V) pthread_key_t V #define my_pthread_getspecific_ptr(T,V) my_pthread_getspecific(T,(V)) #define my_pthread_setspecific_ptr(T,V) pthread_setspecific(T,(void*) (V)) @@ -217,7 +214,11 @@ extern int my_pthread_getprio(pthread_t thread_id); typedef void *(* pthread_handler)(void *); #define my_pthread_once_t pthread_once_t +#if defined(PTHREAD_ONCE_INITIALIZER) +#define MY_PTHREAD_ONCE_INIT PTHREAD_ONCE_INITIALIZER +#else #define MY_PTHREAD_ONCE_INIT PTHREAD_ONCE_INIT +#endif #define my_pthread_once(C,F) pthread_once(C,F) /* Test first for RTS or FSU threads */ @@ -270,14 +271,12 @@ int sigwait(sigset_t *setp, int *sigp); /* Use our implemention */ */ #if defined(HAVE_SIGACTION) && !defined(my_sigset) #define my_sigset(A,B) do { struct sigaction l_s; sigset_t l_set; \ - IF_DBUG(int l_rc); \ DBUG_ASSERT((A) != 0); \ sigemptyset(&l_set); \ l_s.sa_handler = (B); \ l_s.sa_mask = l_set; \ l_s.sa_flags = 0; \ - IF_DBUG(l_rc=) sigaction((A), &l_s, NULL); \ - DBUG_ASSERT(l_rc == 0); \ + sigaction((A), &l_s, NULL); \ } while (0) #elif defined(HAVE_SIGSET) && !defined(my_sigset) #define my_sigset(A,B) sigset((A),(B)) @@ -285,26 +284,6 @@ int sigwait(sigset_t *setp, int *sigp); /* Use our implemention */ #define my_sigset(A,B) signal((A),(B)) #endif -#ifndef my_pthread_setprio -#if defined(HAVE_PTHREAD_SETPRIO_NP) /* FSU threads */ -#define my_pthread_setprio(A,B) pthread_setprio_np((A),(B)) -#elif defined(HAVE_PTHREAD_SETPRIO) -#define my_pthread_setprio(A,B) pthread_setprio((A),(B)) -#elif defined(HAVE_PTHREAD_SETSCHEDPRIO) -#define my_pthread_setprio(A,B) pthread_setschedprio((A),(B)) -#else -extern void my_pthread_setprio(pthread_t thread_id,int prior); -#endif -#endif - -#ifndef my_pthread_attr_setprio -#ifdef HAVE_PTHREAD_ATTR_SETPRIO -#define my_pthread_attr_setprio(A,B) pthread_attr_setprio((A),(B)) -#else -extern void my_pthread_attr_setprio(pthread_attr_t *attr, int priority); -#endif -#endif - #if !defined(HAVE_PTHREAD_ATTR_SETSCOPE) || defined(HAVE_DEC_3_2_THREADS) #define pthread_attr_setscope(A,B) #undef HAVE_GETHOSTBYADDR_R /* No definition */ @@ -386,7 +365,7 @@ struct tm *gmtime_r(const time_t *clock, struct tm *res); #define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH) #undef pthread_detach_this_thread #define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); } -#elif !defined(__NETWARE__) /* HAVE_PTHREAD_ATTR_CREATE && !HAVE_SIGWAIT */ +#else /* HAVE_PTHREAD_ATTR_CREATE && !HAVE_SIGWAIT */ #define HAVE_PTHREAD_KILL #endif @@ -410,6 +389,17 @@ void my_pthread_attr_getstacksize(pthread_attr_t *attrib, size_t *size); int my_pthread_mutex_trylock(pthread_mutex_t *mutex); #endif +#if !defined(HAVE_PTHREAD_YIELD_ONE_ARG) && !defined(HAVE_PTHREAD_YIELD_ZERO_ARG) +/* no pthread_yield() available */ +#ifdef HAVE_SCHED_YIELD +#define pthread_yield() sched_yield() +#elif defined(HAVE_PTHREAD_YIELD_NP) /* can be Mac OS X */ +#define pthread_yield() pthread_yield_np() +#elif defined(HAVE_THR_YIELD) +#define pthread_yield() thr_yield() +#endif +#endif + /* The defines set_timespec and set_timespec_nsec should be used for calculating an absolute time at which @@ -451,11 +441,34 @@ int my_pthread_mutex_trylock(pthread_mutex_t *mutex); #endif /* !set_timespec_nsec */ #endif /* HAVE_TIMESPEC_TS_SEC */ - /* safe_mutex adds checking to mutex for easier debugging */ +/** + Compare two timespec structs. -#if defined(__NETWARE__) && !defined(SAFE_MUTEX_DETECT_DESTROY) -#define SAFE_MUTEX_DETECT_DESTROY -#endif + @retval 1 If TS1 ends after TS2. + + @retval 0 If TS1 is equal to TS2. + + @retval -1 If TS1 ends before TS2. +*/ +#ifdef HAVE_TIMESPEC_TS_SEC +#ifndef cmp_timespec +#define cmp_timespec(TS1, TS2) \ + ((TS1.ts_sec > TS2.ts_sec || \ + (TS1.ts_sec == TS2.ts_sec && TS1.ts_nsec > TS2.ts_nsec)) ? 1 : \ + ((TS1.ts_sec < TS2.ts_sec || \ + (TS1.ts_sec == TS2.ts_sec && TS1.ts_nsec < TS2.ts_nsec)) ? -1 : 0)) +#endif /* !cmp_timespec */ +#else +#ifndef cmp_timespec +#define cmp_timespec(TS1, TS2) \ + ((TS1.tv_sec > TS2.tv_sec || \ + (TS1.tv_sec == TS2.tv_sec && TS1.tv_nsec > TS2.tv_nsec)) ? 1 : \ + ((TS1.tv_sec < TS2.tv_sec || \ + (TS1.tv_sec == TS2.tv_sec && TS1.tv_nsec < TS2.tv_nsec)) ? -1 : 0)) +#endif /* !cmp_timespec */ +#endif /* HAVE_TIMESPEC_TS_SEC */ + + /* safe_mutex adds checking to mutex for easier debugging */ typedef struct st_safe_mutex_t { @@ -492,7 +505,8 @@ int safe_mutex_destroy(safe_mutex_t *mp,const char *file, uint line); int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp,const char *file, uint line); int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp, - struct timespec *abstime, const char *file, uint line); + const struct timespec *abstime, + const char *file, uint line); void safe_mutex_global_init(void); void safe_mutex_end(FILE *file); @@ -594,30 +608,171 @@ int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp); #define my_rwlock_init(A,B) rwlock_init((A),USYNC_THREAD,0) #else /* Use our own version of read/write locks */ -typedef struct _my_rw_lock_t { - pthread_mutex_t lock; /* lock for structure */ - pthread_cond_t readers; /* waiting readers */ - pthread_cond_t writers; /* waiting writers */ - int state; /* -1:writer,0:free,>0:readers */ - int waiters; /* number of waiting writers */ -} my_rw_lock_t; - +#define NEED_MY_RW_LOCK 1 #define rw_lock_t my_rw_lock_t +#define my_rwlock_init(A,B) my_rw_init((A)) #define rw_rdlock(A) my_rw_rdlock((A)) #define rw_wrlock(A) my_rw_wrlock((A)) #define rw_tryrdlock(A) my_rw_tryrdlock((A)) #define rw_trywrlock(A) my_rw_trywrlock((A)) #define rw_unlock(A) my_rw_unlock((A)) -#define rwlock_destroy(A) my_rwlock_destroy((A)) +#define rwlock_destroy(A) my_rw_destroy((A)) +#define rw_lock_assert_write_owner(A) my_rw_lock_assert_write_owner((A)) +#define rw_lock_assert_not_write_owner(A) my_rw_lock_assert_not_write_owner((A)) +#endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */ + + +/** + Portable implementation of special type of read-write locks. + + These locks have two properties which are unusual for rwlocks: + 1) They "prefer readers" in the sense that they do not allow + situations in which rwlock is rd-locked and there is a + pending rd-lock which is blocked (e.g. due to pending + request for wr-lock). + This is a stronger guarantee than one which is provided for + PTHREAD_RWLOCK_PREFER_READER_NP rwlocks in Linux. + MDL subsystem deadlock detector relies on this property for + its correctness. + 2) They are optimized for uncontended wr-lock/unlock case. + This is scenario in which they are most oftenly used + within MDL subsystem. Optimizing for it gives significant + performance improvements in some of tests involving many + connections. + + Another important requirement imposed on this type of rwlock + by the MDL subsystem is that it should be OK to destroy rwlock + object which is in unlocked state even though some threads might + have not yet fully left unlock operation for it (of course there + is an external guarantee that no thread will try to lock rwlock + which is destroyed). + Putting it another way the unlock operation should not access + rwlock data after changing its state to unlocked. + + TODO/FIXME: We should consider alleviating this requirement as + it blocks us from doing certain performance optimizations. +*/ + +typedef struct st_rw_pr_lock_t { + /** + Lock which protects the structure. + Also held for the duration of wr-lock. + */ + pthread_mutex_t lock; + /** + Condition variable which is used to wake-up + writers waiting for readers to go away. + */ + pthread_cond_t no_active_readers; + /** Number of active readers. */ + uint active_readers; + /** Number of writers waiting for readers to go away. */ + uint writers_waiting_readers; + /** Indicates whether there is an active writer. */ + my_bool active_writer; +#ifdef SAFE_MUTEX + /** Thread holding wr-lock (for debug purposes only). */ + pthread_t writer_thread; +#endif +} rw_pr_lock_t; + +extern int rw_pr_init(rw_pr_lock_t *); +extern int rw_pr_rdlock(rw_pr_lock_t *); +extern int rw_pr_wrlock(rw_pr_lock_t *); +extern int rw_pr_unlock(rw_pr_lock_t *); +extern int rw_pr_destroy(rw_pr_lock_t *); +#ifdef SAFE_MUTEX +#define rw_pr_lock_assert_write_owner(A) \ + DBUG_ASSERT((A)->active_writer && pthread_equal(pthread_self(), \ + (A)->writer_thread)) +#define rw_pr_lock_assert_not_write_owner(A) \ + DBUG_ASSERT(! (A)->active_writer || ! pthread_equal(pthread_self(), \ + (A)->writer_thread)) +#else +#define rw_pr_lock_assert_write_owner(A) +#define rw_pr_lock_assert_not_write_owner(A) +#endif /* SAFE_MUTEX */ + + +#ifdef NEED_MY_RW_LOCK + +#ifdef _WIN32 + +/** + Implementation of Windows rwlock. + + We use native (slim) rwlocks on Win7 and later, and fallback to portable + implementation on earlier Windows. + + slim rwlock are also available on Vista/WS2008, but we do not use it + ("trylock" APIs are missing on Vista) +*/ +typedef union +{ + /* Native rwlock (is_srwlock == TRUE) */ + struct + { + SRWLOCK srwlock; /* native reader writer lock */ + BOOL have_exclusive_srwlock; /* used for unlock */ + }; + + /* + Portable implementation (is_srwlock == FALSE) + Fields are identical with Unix my_rw_lock_t fields. + */ + struct + { + pthread_mutex_t lock; /* lock for structure */ + pthread_cond_t readers; /* waiting readers */ + pthread_cond_t writers; /* waiting writers */ + int state; /* -1:writer,0:free,>0:readers */ + int waiters; /* number of waiting writers */ +#ifdef SAFE_MUTEX + pthread_t write_thread; +#endif + }; +} my_rw_lock_t; + + +#else /* _WIN32 */ -extern int my_rwlock_init(my_rw_lock_t *, void *); -extern int my_rwlock_destroy(my_rw_lock_t *); +/* + On systems which don't support native read/write locks we have + to use own implementation. +*/ +typedef struct st_my_rw_lock_t { + pthread_mutex_t lock; /* lock for structure */ + pthread_cond_t readers; /* waiting readers */ + pthread_cond_t writers; /* waiting writers */ + int state; /* -1:writer,0:free,>0:readers */ + int waiters; /* number of waiting writers */ +#ifdef SAFE_MUTEX + pthread_t write_thread; +#endif +} my_rw_lock_t; + +#endif /*! _WIN32 */ + +extern int my_rw_init(my_rw_lock_t *); +extern int my_rw_destroy(my_rw_lock_t *); extern int my_rw_rdlock(my_rw_lock_t *); extern int my_rw_wrlock(my_rw_lock_t *); extern int my_rw_unlock(my_rw_lock_t *); extern int my_rw_tryrdlock(my_rw_lock_t *); extern int my_rw_trywrlock(my_rw_lock_t *); -#endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */ +#ifdef SAFE_MUTEX +#define my_rw_lock_assert_write_owner(A) \ + DBUG_ASSERT((A)->state == -1 && pthread_equal(pthread_self(), \ + (A)->write_thread)) +#define my_rw_lock_assert_not_write_owner(A) \ + DBUG_ASSERT((A)->state >= 0 || ! pthread_equal(pthread_self(), \ + (A)->write_thread)) +#else +#define my_rw_lock_assert_write_owner(A) +#define my_rw_lock_assert_not_write_owner(A) +#endif +#endif /* NEED_MY_RW_LOCK */ + #define GETHOSTBYADDR_BUFF_SIZE 2048 @@ -651,12 +806,13 @@ extern pthread_mutexattr_t my_errorcheck_mutexattr; typedef ulong my_thread_id; extern my_bool my_thread_global_init(void); +extern my_bool my_thread_basic_global_init(void); +extern void my_thread_basic_global_reinit(void); extern void my_thread_global_end(void); extern my_bool my_thread_init(void); extern void my_thread_end(void); extern const char *my_thread_name(void); extern my_thread_id my_thread_dbug_id(void); -extern int pthread_no_free(void *); extern int pthread_dummy(int); /* All thread specific variables are in the following struct */ @@ -674,13 +830,17 @@ extern int pthread_dummy(int); #endif #endif +#include <mysql/psi/mysql_thread.h> + +#define INSTRUMENT_ME 0 + struct st_my_thread_var { int thr_errno; - pthread_cond_t suspend; - pthread_mutex_t mutex; - pthread_mutex_t * volatile current_mutex; - pthread_cond_t * volatile current_cond; + mysql_cond_t suspend; + mysql_mutex_t mutex; + mysql_mutex_t * volatile current_mutex; + mysql_cond_t * volatile current_cond; pthread_t pthread_self; my_thread_id id; int cmp_length; @@ -688,6 +848,7 @@ struct st_my_thread_var my_bool init; struct st_my_thread_var *next,**prev; void *opt_info; + void *stack_ends_here; #ifndef DBUG_OFF void *dbug; char name[THREAD_NAME_SIZE+1]; @@ -695,6 +856,7 @@ struct st_my_thread_var }; extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const)); +extern void **my_thread_var_dbug(); extern uint my_thread_end_wait_time; #define my_thread_var (_my_thread_var()) #define my_errno my_thread_var->thr_errno @@ -716,33 +878,34 @@ extern uint thd_lib_detected; The implementation is guaranteed to be thread safe, on all platforms. Note that the calling code should *not* assume the counter is protected by the mutex given, as the implementation of these helpers may change - to use atomic operations instead. + to use my_atomic operations instead. */ -/* - Warning: - When compiling without threads, this file is not included. - See the *other* declarations of thread_safe_xxx in include/my_global.h - - Second warning: - See include/config-win.h, for yet another implementation. -*/ -#ifdef THREAD #ifndef thread_safe_increment +#ifdef _WIN32 +#define thread_safe_increment(V,L) InterlockedIncrement((long*) &(V)) +#define thread_safe_decrement(V,L) InterlockedDecrement((long*) &(V)) +#else #define thread_safe_increment(V,L) \ - (pthread_mutex_lock((L)), (V)++, pthread_mutex_unlock((L))) + (mysql_mutex_lock((L)), (V)++, mysql_mutex_unlock((L))) #define thread_safe_decrement(V,L) \ - (pthread_mutex_lock((L)), (V)--, pthread_mutex_unlock((L))) + (mysql_mutex_lock((L)), (V)--, mysql_mutex_unlock((L))) +#endif #endif #ifndef thread_safe_add +#ifdef _WIN32 +#define thread_safe_add(V,C,L) InterlockedExchangeAdd((long*) &(V),(C)) +#define thread_safe_sub(V,C,L) InterlockedExchangeAdd((long*) &(V),-(long) (C)) +#else #define thread_safe_add(V,C,L) \ - (pthread_mutex_lock((L)), (V)+=(C), pthread_mutex_unlock((L))) + (mysql_mutex_lock((L)), (V)+=(C), mysql_mutex_unlock((L))) #define thread_safe_sub(V,C,L) \ - (pthread_mutex_lock((L)), (V)-=(C), pthread_mutex_unlock((L))) + (mysql_mutex_lock((L)), (V)-=(C), mysql_mutex_unlock((L))) #endif #endif + /* statistics_xxx functions are for non critical statistic, maintained in global variables. |