Coverage Report

Created: 2024-06-18 07:03

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