1/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
2 Copyright (c) 2009, 2017, MariaDB Corporation.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16
17/* Defines to make different thread packages compatible */
18
19#ifndef _my_pthread_h
20#define _my_pthread_h
21
22#ifndef ETIME
23#define ETIME ETIMEDOUT /* For FreeBSD */
24#endif
25
26#ifdef __cplusplus
27#define EXTERNC extern "C"
28extern "C" {
29#else
30#define EXTERNC
31#endif /* __cplusplus */
32
33#if defined(__WIN__)
34typedef CRITICAL_SECTION pthread_mutex_t;
35typedef DWORD pthread_t;
36typedef struct thread_attr {
37 DWORD dwStackSize ;
38 DWORD dwCreatingFlag ;
39} pthread_attr_t ;
40
41typedef struct { int dummy; } pthread_condattr_t;
42
43/* Implementation of posix conditions */
44
45typedef struct st_pthread_link {
46 DWORD thread_id;
47 struct st_pthread_link *next;
48} pthread_link;
49
50/**
51 Implementation of Windows condition variables.
52 We use native conditions on Vista and later, and fallback to own
53 implementation on earlier OS version.
54*/
55typedef CONDITION_VARIABLE pthread_cond_t;
56
57
58typedef int pthread_mutexattr_t;
59#define pthread_self() GetCurrentThreadId()
60#define pthread_handler_t EXTERNC void * __cdecl
61typedef void * (__cdecl *pthread_handler)(void *);
62
63typedef INIT_ONCE my_pthread_once_t;
64#define MY_PTHREAD_ONCE_INIT INIT_ONCE_STATIC_INIT;
65
66#if !STRUCT_TIMESPEC_HAS_TV_SEC || !STRUCT_TIMESPEC_HAS_TV_NSEC
67struct timespec {
68 time_t tv_sec;
69 long tv_nsec;
70};
71#endif
72
73int win_pthread_mutex_trylock(pthread_mutex_t *mutex);
74int pthread_create(pthread_t *, const pthread_attr_t *, pthread_handler, void *);
75int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
76int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
77int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
78 const struct timespec *abstime);
79int pthread_cond_signal(pthread_cond_t *cond);
80int pthread_cond_broadcast(pthread_cond_t *cond);
81int pthread_cond_destroy(pthread_cond_t *cond);
82int pthread_attr_init(pthread_attr_t *connect_att);
83int pthread_attr_setstacksize(pthread_attr_t *connect_att,size_t stack);
84int pthread_attr_destroy(pthread_attr_t *connect_att);
85int my_pthread_once(my_pthread_once_t *once_control,void (*init_routine)(void));
86
87static inline struct tm *localtime_r(const time_t *timep, struct tm *tmp)
88{
89 localtime_s(tmp, timep);
90 return tmp;
91}
92
93static inline struct tm *gmtime_r(const time_t *clock, struct tm *res)
94{
95 gmtime_s(res, clock);
96 return res;
97}
98
99void pthread_exit(void *a);
100int pthread_join(pthread_t thread, void **value_ptr);
101int pthread_cancel(pthread_t thread);
102
103#ifndef ETIMEDOUT
104#define ETIMEDOUT 145 /* Win32 doesn't have this */
105#endif
106
107#define getpid() GetCurrentThreadId()
108#define HAVE_LOCALTIME_R 1
109#define _REENTRANT 1
110#define HAVE_PTHREAD_ATTR_SETSTACKSIZE 1
111
112#undef SAFE_MUTEX /* This will cause conflicts */
113#define pthread_key(T,V) DWORD V
114#define pthread_key_create(A,B) ((*A=TlsAlloc())==0xFFFFFFFF)
115#define pthread_key_delete(A) TlsFree(A)
116#define my_pthread_setspecific_ptr(T,V) (!TlsSetValue((T),(V)))
117#define pthread_setspecific(A,B) (!TlsSetValue((A),(B)))
118#define pthread_getspecific(A) (TlsGetValue(A))
119#define my_pthread_getspecific(T,A) ((T) TlsGetValue(A))
120#define my_pthread_getspecific_ptr(T,V) ((T) TlsGetValue(V))
121
122#define pthread_equal(A,B) ((A) == (B))
123#define pthread_mutex_init(A,B) (InitializeCriticalSection(A),0)
124#define pthread_mutex_lock(A) (EnterCriticalSection(A),0)
125#define pthread_mutex_trylock(A) win_pthread_mutex_trylock((A))
126#define pthread_mutex_unlock(A) (LeaveCriticalSection(A), 0)
127#define pthread_mutex_destroy(A) (DeleteCriticalSection(A), 0)
128#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH)
129
130
131/* Dummy defines for easier code */
132#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)
133#define pthread_attr_setscope(A,B)
134#define pthread_detach_this_thread()
135#define pthread_condattr_init(A)
136#define pthread_condattr_destroy(A)
137#define pthread_yield() SwitchToThread()
138#define my_sigset(A,B) signal(A,B)
139
140#else /* Normal threads */
141
142#ifdef HAVE_rts_threads
143#define sigwait org_sigwait
144#include <signal.h>
145#undef sigwait
146#endif
147#include <pthread.h>
148#ifndef _REENTRANT
149#define _REENTRANT
150#endif
151#ifdef HAVE_THR_SETCONCURRENCY
152#include <thread.h> /* Probably solaris */
153#endif
154#ifdef HAVE_SCHED_H
155#include <sched.h>
156#endif
157#ifdef HAVE_SYNCH_H
158#include <synch.h>
159#endif
160
161#define pthread_key(T,V) pthread_key_t V
162#define my_pthread_getspecific_ptr(T,V) my_pthread_getspecific(T,(V))
163#define my_pthread_setspecific_ptr(T,V) pthread_setspecific(T,(void*) (V))
164#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(tmp); }
165#define pthread_handler_t EXTERNC void *
166typedef void *(* pthread_handler)(void *);
167
168#define my_pthread_once_t pthread_once_t
169#if defined(PTHREAD_ONCE_INITIALIZER)
170#define MY_PTHREAD_ONCE_INIT PTHREAD_ONCE_INITIALIZER
171#else
172#define MY_PTHREAD_ONCE_INIT PTHREAD_ONCE_INIT
173#endif
174#define my_pthread_once(C,F) pthread_once(C,F)
175
176/* Test first for RTS or FSU threads */
177
178#if defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM)
179#define HAVE_rts_threads
180extern int my_pthread_create_detached;
181#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C))
182#define PTHREAD_CREATE_DETACHED &my_pthread_create_detached
183#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_GLOBAL
184#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_LOCAL
185#define USE_ALARM_THREAD
186#endif /* defined(PTHREAD_SCOPE_GLOBAL) && !defined(PTHREAD_SCOPE_SYSTEM) */
187
188#if defined(_BSDI_VERSION) && _BSDI_VERSION < 199910
189int sigwait(sigset_t *set, int *sig);
190#endif
191
192#define my_sigwait(A,B) sigwait((A),(B))
193
194#if defined(HAVE_SIGTHREADMASK) && !defined(HAVE_PTHREAD_SIGMASK)
195#define pthread_sigmask(A,B,C) sigthreadmask((A),(B),(C))
196#endif
197
198#if !defined(HAVE_SIGWAIT) && !defined(HAVE_rts_threads) && !defined(sigwait) && !defined(alpha_linux_port) && !defined(_AIX)
199int sigwait(sigset_t *setp, int *sigp); /* Use our implementation */
200#endif
201
202
203/*
204 We define my_sigset() and use that instead of the system sigset() so that
205 we can favor an implementation based on sigaction(). On some systems, such
206 as Mac OS X, sigset() results in flags such as SA_RESTART being set, and
207 we want to make sure that no such flags are set.
208*/
209#if defined(HAVE_SIGACTION) && !defined(my_sigset)
210#define my_sigset(A,B) do { struct sigaction l_s; sigset_t l_set; \
211 DBUG_ASSERT((A) != 0); \
212 sigemptyset(&l_set); \
213 l_s.sa_handler = (B); \
214 l_s.sa_mask = l_set; \
215 l_s.sa_flags = 0; \
216 sigaction((A), &l_s, NULL); \
217 } while (0)
218#elif defined(HAVE_SIGSET) && !defined(my_sigset)
219#define my_sigset(A,B) sigset((A),(B))
220#elif !defined(my_sigset)
221#define my_sigset(A,B) signal((A),(B))
222#endif
223
224#if !defined(HAVE_PTHREAD_ATTR_SETSCOPE)
225#define pthread_attr_setscope(A,B)
226#undef HAVE_GETHOSTBYADDR_R /* No definition */
227#endif
228
229#define my_pthread_getspecific(A,B) ((A) pthread_getspecific(B))
230
231#ifndef HAVE_LOCALTIME_R
232struct tm *localtime_r(const time_t *clock, struct tm *res);
233#endif
234
235#ifndef HAVE_GMTIME_R
236struct tm *gmtime_r(const time_t *clock, struct tm *res);
237#endif
238
239#ifdef HAVE_PTHREAD_CONDATTR_CREATE
240/* DCE threads on HPUX 10.20 */
241#define pthread_condattr_init pthread_condattr_create
242#define pthread_condattr_destroy pthread_condattr_delete
243#endif
244
245/* FSU THREADS */
246#if !defined(HAVE_PTHREAD_KEY_DELETE) && !defined(pthread_key_delete)
247#define pthread_key_delete(A) pthread_dummy(0)
248#endif
249
250#if defined(HAVE_PTHREAD_ATTR_CREATE) && !defined(HAVE_SIGWAIT)
251/* This is set on AIX_3_2 and Siemens unix (and DEC OSF/1 3.2 too) */
252#define pthread_key_create(A,B) \
253 pthread_keycreate(A,(B) ?\
254 (pthread_destructor_t) (B) :\
255 (pthread_destructor_t) pthread_dummy)
256#define pthread_attr_init(A) pthread_attr_create(A)
257#define pthread_attr_destroy(A) pthread_attr_delete(A)
258#define pthread_attr_setdetachstate(A,B) pthread_dummy(0)
259#define pthread_create(A,B,C,D) pthread_create((A),*(B),(C),(D))
260#ifndef pthread_sigmask
261#define pthread_sigmask(A,B,C) sigprocmask((A),(B),(C))
262#endif
263#define pthread_kill(A,B) pthread_dummy((A) ? 0 : ESRCH)
264#undef pthread_detach_this_thread
265#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); }
266#else /* HAVE_PTHREAD_ATTR_CREATE && !HAVE_SIGWAIT */
267#define HAVE_PTHREAD_KILL 1
268#endif
269
270#endif /* defined(__WIN__) */
271
272#if defined(HPUX10) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS)
273#undef pthread_cond_timedwait
274#define pthread_cond_timedwait(a,b,c) my_pthread_cond_timedwait((a),(b),(c))
275int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
276 struct timespec *abstime);
277#endif
278
279#if defined(HPUX10)
280#define pthread_attr_getstacksize(A,B) my_pthread_attr_getstacksize(A,B)
281void my_pthread_attr_getstacksize(pthread_attr_t *attrib, size_t *size);
282#endif
283
284#if defined(HAVE_POSIX1003_4a_MUTEX) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS)
285#undef pthread_mutex_trylock
286#define pthread_mutex_trylock(a) my_pthread_mutex_trylock((a))
287int my_pthread_mutex_trylock(pthread_mutex_t *mutex);
288#endif
289
290#if !defined(HAVE_PTHREAD_YIELD_ZERO_ARG)
291/* no pthread_yield() available */
292#ifdef HAVE_SCHED_YIELD
293#define pthread_yield() sched_yield()
294#elif defined(HAVE_PTHREAD_YIELD_NP) /* can be Mac OS X */
295#define pthread_yield() pthread_yield_np()
296#elif defined(HAVE_THR_YIELD)
297#define pthread_yield() thr_yield()
298#endif
299#endif
300
301/*
302 The defines set_timespec and set_timespec_nsec should be used
303 for calculating an absolute time at which
304 pthread_cond_timedwait should timeout
305*/
306#define set_timespec(ABSTIME,SEC) set_timespec_nsec((ABSTIME),(SEC)*1000000000ULL)
307
308#ifndef set_timespec_nsec
309#define set_timespec_nsec(ABSTIME,NSEC) \
310 set_timespec_time_nsec((ABSTIME), my_hrtime_coarse().val*1000 + (NSEC))
311#endif /* !set_timespec_nsec */
312
313/* adapt for two different flavors of struct timespec */
314#ifdef HAVE_TIMESPEC_TS_SEC
315#define MY_tv_sec ts_sec
316#define MY_tv_nsec ts_nsec
317#else
318#define MY_tv_sec tv_sec
319#define MY_tv_nsec tv_nsec
320#endif /* HAVE_TIMESPEC_TS_SEC */
321
322/**
323 Compare two timespec structs.
324
325 @retval 1 If TS1 ends after TS2.
326
327 @retval 0 If TS1 is equal to TS2.
328
329 @retval -1 If TS1 ends before TS2.
330*/
331#ifndef cmp_timespec
332#define cmp_timespec(TS1, TS2) \
333 ((TS1.MY_tv_sec > TS2.MY_tv_sec || \
334 (TS1.MY_tv_sec == TS2.MY_tv_sec && TS1.MY_tv_nsec > TS2.MY_tv_nsec)) ? 1 : \
335 ((TS1.MY_tv_sec < TS2.MY_tv_sec || \
336 (TS1.MY_tv_sec == TS2.MY_tv_sec && TS1.MY_tv_nsec < TS2.MY_tv_nsec)) ? -1 : 0))
337#endif /* !cmp_timespec */
338
339#ifndef set_timespec_time_nsec
340#define set_timespec_time_nsec(ABSTIME,NSEC) do { \
341 ulonglong _now_= (NSEC); \
342 (ABSTIME).MY_tv_sec= (_now_ / 1000000000ULL); \
343 (ABSTIME).MY_tv_nsec= (_now_ % 1000000000ULL); \
344} while(0)
345#endif /* !set_timespec_time_nsec */
346
347#ifdef MYSQL_CLIENT
348#define _current_thd() NULL
349#elif defined(_WIN32)
350#ifdef __cplusplus
351extern "C"
352#endif
353MYSQL_THD _current_thd_noinline();
354#define _current_thd() _current_thd_noinline()
355#else
356/*
357 THR_THD is a key which will be used to set/get THD* for a thread,
358 using my_pthread_setspecific_ptr()/my_thread_getspecific_ptr().
359*/
360extern pthread_key(MYSQL_THD, THR_THD);
361static inline MYSQL_THD _current_thd(void)
362{
363 return my_pthread_getspecific_ptr(MYSQL_THD,THR_THD);
364}
365#endif
366
367/* safe_mutex adds checking to mutex for easier debugging */
368struct st_hash;
369typedef struct st_safe_mutex_t
370{
371 pthread_mutex_t global,mutex;
372 const char *file, *name;
373 uint line,count;
374 myf create_flags, active_flags;
375 ulong id;
376 pthread_t thread;
377 struct st_hash *locked_mutex, *used_mutex;
378 struct st_safe_mutex_t *prev, *next;
379#ifdef SAFE_MUTEX_DETECT_DESTROY
380 struct st_safe_mutex_info_t *info; /* to track destroying of mutexes */
381#endif
382} safe_mutex_t;
383
384typedef struct st_safe_mutex_deadlock_t
385{
386 const char *file, *name;
387 safe_mutex_t *mutex;
388 uint line;
389 ulong count;
390 ulong id;
391 my_bool warning_only;
392} safe_mutex_deadlock_t;
393
394#ifdef SAFE_MUTEX_DETECT_DESTROY
395/*
396 Used to track the destroying of mutexes. This needs to be a separate
397 structure because the safe_mutex_t structure could be freed before
398 the mutexes are destroyed.
399*/
400
401typedef struct st_safe_mutex_info_t
402{
403 struct st_safe_mutex_info_t *next;
404 struct st_safe_mutex_info_t *prev;
405 const char *init_file;
406 uint32 init_line;
407} safe_mutex_info_t;
408#endif /* SAFE_MUTEX_DETECT_DESTROY */
409
410int safe_mutex_init(safe_mutex_t *mp, const pthread_mutexattr_t *attr,
411 const char *name, const char *file, uint line);
412int safe_mutex_lock(safe_mutex_t *mp, myf my_flags, const char *file,
413 uint line);
414int safe_mutex_unlock(safe_mutex_t *mp,const char *file, uint line);
415int safe_mutex_destroy(safe_mutex_t *mp,const char *file, uint line);
416int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp,const char *file,
417 uint line);
418int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp,
419 const struct timespec *abstime,
420 const char *file, uint line);
421void safe_mutex_global_init(void);
422void safe_mutex_end(FILE *file);
423void safe_mutex_free_deadlock_data(safe_mutex_t *mp);
424
425 /* Wrappers if safe mutex is actually used */
426#define MYF_TRY_LOCK 1
427#define MYF_NO_DEADLOCK_DETECTION 2
428
429#ifdef SAFE_MUTEX
430#define safe_mutex_assert_owner(mp) \
431 DBUG_ASSERT((mp)->count > 0 && \
432 pthread_equal(pthread_self(), (mp)->thread))
433#define safe_mutex_assert_not_owner(mp) \
434 DBUG_ASSERT(! (mp)->count || \
435 ! pthread_equal(pthread_self(), (mp)->thread))
436#define safe_mutex_setflags(mp, F) do { (mp)->create_flags|= (F); } while (0)
437#define my_cond_timedwait(A,B,C) safe_cond_timedwait((A),(B),(C),__FILE__,__LINE__)
438#define my_cond_wait(A,B) safe_cond_wait((A), (B), __FILE__, __LINE__)
439#else
440
441#define safe_mutex_assert_owner(mp) do {} while (0)
442#define safe_mutex_assert_not_owner(mp) do {} while (0)
443#define safe_mutex_setflags(mp, F) do {} while (0)
444
445#define my_cond_timedwait(A,B,C) pthread_cond_timedwait((A),(B),(C))
446#define my_cond_wait(A,B) pthread_cond_wait((A), (B))
447#endif /* !SAFE_MUTEX */
448
449 /* READ-WRITE thread locking */
450
451#if defined(USE_MUTEX_INSTEAD_OF_RW_LOCKS)
452/* use these defs for simple mutex locking */
453#define rw_lock_t pthread_mutex_t
454#define my_rwlock_init(A,B) pthread_mutex_init((A),(B))
455#define rw_rdlock(A) pthread_mutex_lock((A))
456#define rw_wrlock(A) pthread_mutex_lock((A))
457#define rw_tryrdlock(A) pthread_mutex_trylock((A))
458#define rw_trywrlock(A) pthread_mutex_trylock((A))
459#define rw_unlock(A) pthread_mutex_unlock((A))
460#define rwlock_destroy(A) pthread_mutex_destroy((A))
461#elif defined(HAVE_PTHREAD_RWLOCK_RDLOCK)
462#define rw_lock_t pthread_rwlock_t
463#define my_rwlock_init(A,B) pthread_rwlock_init((A),(B))
464#define rw_rdlock(A) pthread_rwlock_rdlock(A)
465#define rw_wrlock(A) pthread_rwlock_wrlock(A)
466#define rw_tryrdlock(A) pthread_rwlock_tryrdlock((A))
467#define rw_trywrlock(A) pthread_rwlock_trywrlock((A))
468#define rw_unlock(A) pthread_rwlock_unlock(A)
469#define rwlock_destroy(A) pthread_rwlock_destroy(A)
470#elif defined(HAVE_RWLOCK_INIT)
471#ifdef HAVE_RWLOCK_T /* For example Solaris 2.6-> */
472#define rw_lock_t rwlock_t
473#endif
474#define my_rwlock_init(A,B) rwlock_init((A),USYNC_THREAD,0)
475#else
476/* Use our own version of read/write locks */
477#define NEED_MY_RW_LOCK 1
478#define rw_lock_t my_rw_lock_t
479#define my_rwlock_init(A,B) my_rw_init((A))
480#define rw_rdlock(A) my_rw_rdlock((A))
481#define rw_wrlock(A) my_rw_wrlock((A))
482#define rw_tryrdlock(A) my_rw_tryrdlock((A))
483#define rw_trywrlock(A) my_rw_trywrlock((A))
484#define rw_unlock(A) my_rw_unlock((A))
485#define rwlock_destroy(A) my_rw_destroy((A))
486#define rw_lock_assert_write_owner(A) my_rw_lock_assert_write_owner((A))
487#define rw_lock_assert_not_write_owner(A) my_rw_lock_assert_not_write_owner((A))
488#endif /* USE_MUTEX_INSTEAD_OF_RW_LOCKS */
489
490
491/**
492 Portable implementation of special type of read-write locks.
493
494 These locks have two properties which are unusual for rwlocks:
495 1) They "prefer readers" in the sense that they do not allow
496 situations in which rwlock is rd-locked and there is a
497 pending rd-lock which is blocked (e.g. due to pending
498 request for wr-lock).
499 This is a stronger guarantee than one which is provided for
500 PTHREAD_RWLOCK_PREFER_READER_NP rwlocks in Linux.
501 MDL subsystem deadlock detector relies on this property for
502 its correctness.
503 2) They are optimized for uncontended wr-lock/unlock case.
504 This is a scenario in which they are most often used
505 within MDL subsystem. Optimizing for it gives significant
506 performance improvements in some of the tests involving many
507 connections.
508
509 Another important requirement imposed on this type of rwlock
510 by the MDL subsystem is that it should be OK to destroy rwlock
511 object which is in unlocked state even though some threads might
512 have not yet fully left unlock operation for it (of course there
513 is an external guarantee that no thread will try to lock rwlock
514 which is destroyed).
515 Putting it another way the unlock operation should not access
516 rwlock data after changing its state to unlocked.
517
518 TODO/FIXME: We should consider alleviating this requirement as
519 it blocks us from doing certain performance optimizations.
520*/
521
522typedef struct st_rw_pr_lock_t {
523 /**
524 Lock which protects the structure.
525 Also held for the duration of wr-lock.
526 */
527 pthread_mutex_t lock;
528 /**
529 Condition variable which is used to wake-up
530 writers waiting for readers to go away.
531 */
532 pthread_cond_t no_active_readers;
533 /** Number of active readers. */
534 uint active_readers;
535 /** Number of writers waiting for readers to go away. */
536 uint writers_waiting_readers;
537 /** Indicates whether there is an active writer. */
538 my_bool active_writer;
539#ifdef SAFE_MUTEX
540 /** Thread holding wr-lock (for debug purposes only). */
541 pthread_t writer_thread;
542#endif
543} rw_pr_lock_t;
544
545extern int rw_pr_init(rw_pr_lock_t *);
546extern int rw_pr_rdlock(rw_pr_lock_t *);
547extern int rw_pr_wrlock(rw_pr_lock_t *);
548extern int rw_pr_unlock(rw_pr_lock_t *);
549extern int rw_pr_destroy(rw_pr_lock_t *);
550#ifdef SAFE_MUTEX
551#define rw_pr_lock_assert_write_owner(A) \
552 DBUG_ASSERT((A)->active_writer && pthread_equal(pthread_self(), \
553 (A)->writer_thread))
554#define rw_pr_lock_assert_not_write_owner(A) \
555 DBUG_ASSERT(! (A)->active_writer || ! pthread_equal(pthread_self(), \
556 (A)->writer_thread))
557#else
558#define rw_pr_lock_assert_write_owner(A)
559#define rw_pr_lock_assert_not_write_owner(A)
560#endif /* SAFE_MUTEX */
561
562
563#ifdef NEED_MY_RW_LOCK
564
565#ifdef _WIN32
566
567/**
568 Implementation of Windows rwlock.
569
570 We use native (slim) rwlocks on Win7 and later, and fallback to portable
571 implementation on earlier Windows.
572
573 slim rwlock are also available on Vista/WS2008, but we do not use it
574 ("trylock" APIs are missing on Vista)
575*/
576typedef union
577{
578 /* Native rwlock (is_srwlock == TRUE) */
579 struct
580 {
581 SRWLOCK srwlock; /* native reader writer lock */
582 BOOL have_exclusive_srwlock; /* used for unlock */
583 };
584
585 /*
586 Portable implementation (is_srwlock == FALSE)
587 Fields are identical with Unix my_rw_lock_t fields.
588 */
589 struct
590 {
591 pthread_mutex_t lock; /* lock for structure */
592 pthread_cond_t readers; /* waiting readers */
593 pthread_cond_t writers; /* waiting writers */
594 int state; /* -1:writer,0:free,>0:readers */
595 int waiters; /* number of waiting writers */
596#ifdef SAFE_MUTEX
597 pthread_t write_thread;
598#endif
599 };
600} my_rw_lock_t;
601
602
603#else /* _WIN32 */
604
605/*
606 On systems which don't support native read/write locks we have
607 to use own implementation.
608*/
609typedef struct st_my_rw_lock_t {
610 pthread_mutex_t lock; /* lock for structure */
611 pthread_cond_t readers; /* waiting readers */
612 pthread_cond_t writers; /* waiting writers */
613 int state; /* -1:writer,0:free,>0:readers */
614 int waiters; /* number of waiting writers */
615#ifdef SAFE_MUTEX
616 pthread_t write_thread;
617#endif
618} my_rw_lock_t;
619
620#endif /*! _WIN32 */
621
622extern int my_rw_init(my_rw_lock_t *);
623extern int my_rw_destroy(my_rw_lock_t *);
624extern int my_rw_rdlock(my_rw_lock_t *);
625extern int my_rw_wrlock(my_rw_lock_t *);
626extern int my_rw_unlock(my_rw_lock_t *);
627extern int my_rw_tryrdlock(my_rw_lock_t *);
628extern int my_rw_trywrlock(my_rw_lock_t *);
629#ifdef SAFE_MUTEX
630#define my_rw_lock_assert_write_owner(A) \
631 DBUG_ASSERT((A)->state == -1 && pthread_equal(pthread_self(), \
632 (A)->write_thread))
633#define my_rw_lock_assert_not_write_owner(A) \
634 DBUG_ASSERT((A)->state >= 0 || ! pthread_equal(pthread_self(), \
635 (A)->write_thread))
636#else
637#define my_rw_lock_assert_write_owner(A)
638#define my_rw_lock_assert_not_write_owner(A)
639#endif
640#endif /* NEED_MY_RW_LOCK */
641
642
643#define GETHOSTBYADDR_BUFF_SIZE 2048
644
645#ifndef HAVE_THR_SETCONCURRENCY
646#define thr_setconcurrency(A) pthread_dummy(0)
647#endif
648#if !defined(HAVE_PTHREAD_ATTR_SETSTACKSIZE) && ! defined(pthread_attr_setstacksize)
649#define pthread_attr_setstacksize(A,B) pthread_dummy(0)
650#endif
651
652/* Define mutex types, see my_thr_init.c */
653#define MY_MUTEX_INIT_SLOW NULL
654#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
655extern pthread_mutexattr_t my_fast_mutexattr;
656#define MY_MUTEX_INIT_FAST &my_fast_mutexattr
657#else
658#define MY_MUTEX_INIT_FAST NULL
659#endif
660#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
661extern pthread_mutexattr_t my_errorcheck_mutexattr;
662#define MY_MUTEX_INIT_ERRCHK &my_errorcheck_mutexattr
663#else
664#define MY_MUTEX_INIT_ERRCHK NULL
665#endif
666
667#ifndef ESRCH
668/* Define it to something */
669#define ESRCH 1
670#endif
671
672typedef uint64 my_thread_id;
673
674extern void my_threadattr_global_init(void);
675extern my_bool my_thread_global_init(void);
676extern void my_thread_global_reinit(void);
677extern void my_thread_global_end(void);
678extern my_bool my_thread_init(void);
679extern void my_thread_end(void);
680extern const char *my_thread_name(void);
681extern my_thread_id my_thread_dbug_id(void);
682extern int pthread_dummy(int);
683extern void my_mutex_init(void);
684extern void my_mutex_end(void);
685
686/* All thread specific variables are in the following struct */
687
688#define THREAD_NAME_SIZE 10
689#ifndef DEFAULT_THREAD_STACK
690/*
691 We need to have at least 256K stack to handle calls to myisamchk_init()
692 with the current number of keys and key parts.
693*/
694#define DEFAULT_THREAD_STACK (292*1024L)
695#endif
696
697#define MY_PTHREAD_LOCK_READ 0
698#define MY_PTHREAD_LOCK_WRITE 1
699
700#include <mysql/psi/mysql_thread.h>
701
702#define INSTRUMENT_ME 0
703
704struct st_my_thread_var
705{
706 int thr_errno;
707 mysql_cond_t suspend;
708 mysql_mutex_t mutex;
709 mysql_mutex_t * volatile current_mutex;
710 mysql_cond_t * volatile current_cond;
711 pthread_t pthread_self;
712 my_thread_id id, dbug_id;
713 int volatile abort;
714 my_bool init;
715 struct st_my_thread_var *next,**prev;
716 void *keycache_link;
717 uint lock_type; /* used by conditional release the queue */
718 void *stack_ends_here;
719 safe_mutex_t *mutex_in_use;
720#ifndef DBUG_OFF
721 void *dbug;
722 char name[THREAD_NAME_SIZE+1];
723#endif
724};
725
726extern struct st_my_thread_var *_my_thread_var(void) __attribute__ ((const));
727extern void **my_thread_var_dbug(void);
728extern safe_mutex_t **my_thread_var_mutex_in_use(void);
729extern uint my_thread_end_wait_time;
730extern my_bool safe_mutex_deadlock_detector;
731#define my_thread_var (_my_thread_var())
732#define my_errno my_thread_var->thr_errno
733/*
734 Keep track of shutdown,signal, and main threads so that my_end() will not
735 report errors with them
736*/
737
738/* Which kind of thread library is in use */
739
740#define THD_LIB_OTHER 1
741#define THD_LIB_NPTL 2
742#define THD_LIB_LT 4
743
744extern uint thd_lib_detected;
745
746/*
747 thread_safe_xxx functions are for critical statistic or counters.
748 The implementation is guaranteed to be thread safe, on all platforms.
749 Note that the calling code should *not* assume the counter is protected
750 by the mutex given, as the implementation of these helpers may change
751 to use my_atomic operations instead.
752*/
753
754#ifndef thread_safe_increment
755#ifdef _WIN32
756#define thread_safe_increment(V,L) InterlockedIncrement((long*) &(V))
757#define thread_safe_decrement(V,L) InterlockedDecrement((long*) &(V))
758#else
759#define thread_safe_increment(V,L) \
760 (mysql_mutex_lock((L)), (V)++, mysql_mutex_unlock((L)))
761#define thread_safe_decrement(V,L) \
762 (mysql_mutex_lock((L)), (V)--, mysql_mutex_unlock((L)))
763#endif
764#endif
765
766#ifndef thread_safe_add
767#ifdef _WIN32
768#define thread_safe_add(V,C,L) InterlockedExchangeAdd((long*) &(V),(C))
769#define thread_safe_sub(V,C,L) InterlockedExchangeAdd((long*) &(V),-(long) (C))
770#else
771#define thread_safe_add(V,C,L) \
772 (mysql_mutex_lock((L)), (V)+=(C), mysql_mutex_unlock((L)))
773#define thread_safe_sub(V,C,L) \
774 (mysql_mutex_lock((L)), (V)-=(C), mysql_mutex_unlock((L)))
775#endif
776#endif
777
778
779/*
780 statistics_xxx functions are for non critical statistic,
781 maintained in global variables.
782 When compiling with SAFE_STATISTICS:
783 - race conditions can not occur.
784 - some locking occurs, which may cause performance degradation.
785
786 When compiling without SAFE_STATISTICS:
787 - race conditions can occur, making the result slightly inaccurate.
788 - the lock given is not honored.
789*/
790#ifdef SAFE_STATISTICS
791#define statistic_increment(V,L) thread_safe_increment((V),(L))
792#define statistic_decrement(V,L) thread_safe_decrement((V),(L))
793#define statistic_add(V,C,L) thread_safe_add((V),(C),(L))
794#define statistic_sub(V,C,L) thread_safe_sub((V),(C),(L))
795#else
796#define statistic_decrement(V,L) (V)--
797#define statistic_increment(V,L) (V)++
798#define statistic_add(V,C,L) (V)+=(C)
799#define statistic_sub(V,C,L) (V)-=(C)
800#endif /* SAFE_STATISTICS */
801
802/*
803 No locking needed, the counter is owned by the thread
804*/
805#define status_var_increment(V) (V)++
806#define status_var_decrement(V) (V)--
807#define status_var_add(V,C) (V)+=(C)
808#define status_var_sub(V,C) (V)-=(C)
809
810#ifdef SAFE_MUTEX
811#define mysql_mutex_record_order(A,B) \
812 do { \
813 mysql_mutex_lock(A); mysql_mutex_lock(B); \
814 mysql_mutex_unlock(B); mysql_mutex_unlock(A); \
815 } while(0)
816#else
817#define mysql_mutex_record_order(A,B) do { } while(0)
818#endif
819
820/* At least Windows and NetBSD do not have this definition */
821#ifndef PTHREAD_STACK_MIN
822#define PTHREAD_STACK_MIN 65536
823#endif
824
825#ifdef __cplusplus
826}
827#endif
828#endif /* _my_ptread_h */
829