40
41
#include "os0sync.h"
41
42
#include "sync0arr.h"
44
/**********************************************************************
44
#if defined(UNIV_DEBUG) && !defined(UNIV_HOTBACKUP)
45
extern my_bool timed_mutexes;
46
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
48
#ifdef HAVE_WINDOWS_ATOMICS
49
typedef LONG lock_word_t; /*!< On Windows, InterlockedExchange operates
52
typedef byte lock_word_t;
55
/******************************************************************//**
45
56
Initializes the synchronization data structures. */
50
/**********************************************************************
61
/******************************************************************//**
51
62
Frees the resources in synchronization data structures. */
56
/**********************************************************************
67
/******************************************************************//**
57
68
Creates, or rather, initializes a mutex object to a specified memory
58
69
location (which must be appropriately aligned). The mutex is initialized
59
70
in the reset state. Explicit freeing of the mutex with mutex_free is
84
mutex_t* mutex, /* in: pointer to memory */
95
mutex_t* mutex, /*!< in: pointer to memory */
86
const char* cmutex_name, /* in: mutex name */
97
const char* cmutex_name, /*!< in: mutex name */
87
98
# ifdef UNIV_SYNC_DEBUG
88
ulint level, /* in: level */
99
ulint level, /*!< in: level */
89
100
# endif /* UNIV_SYNC_DEBUG */
90
101
#endif /* UNIV_DEBUG */
91
const char* cfile_name, /* in: file name where created */
92
ulint cline); /* in: file line where created */
102
const char* cfile_name, /*!< in: file name where created */
103
ulint cline); /*!< in: file line where created */
94
105
#undef mutex_free /* Fix for MacOS X */
96
/**********************************************************************
107
/******************************************************************//**
97
108
Calling this function is obligatory only if the memory buffer containing
98
109
the mutex is freed. Removes a mutex object from the mutex list. The mutex
99
110
is checked to be in the reset state. */
104
mutex_t* mutex); /* in: mutex */
105
/******************************************************************
115
mutex_t* mutex); /*!< in: mutex */
116
/**************************************************************//**
106
117
NOTE! The following macro should be used in mutex locking, not the
107
118
corresponding function. */
109
120
#define mutex_enter(M) mutex_enter_func((M), __FILE__, __LINE__)
110
/******************************************************************
121
/**************************************************************//**
111
122
NOTE! The following macro should be used in mutex locking, not the
112
123
corresponding function. */
114
125
/* NOTE! currently same as mutex_enter! */
116
127
#define mutex_enter_fast(M) mutex_enter_func((M), __FILE__, __LINE__)
117
/**********************************************************************
128
/******************************************************************//**
118
129
NOTE! Use the corresponding macro in the header file, not this function
119
130
directly. Locks a mutex for the current thread. If the mutex is reserved
120
131
the function spins a preset time (controlled by SYNC_SPIN_ROUNDS) waiting
124
135
mutex_enter_func(
125
136
/*=============*/
126
mutex_t* mutex, /* in: pointer to mutex */
127
const char* file_name, /* in: file name where locked */
128
ulint line); /* in: line where locked */
129
/******************************************************************
137
mutex_t* mutex, /*!< in: pointer to mutex */
138
const char* file_name, /*!< in: file name where locked */
139
ulint line); /*!< in: line where locked */
140
/**************************************************************//**
130
141
NOTE! The following macro should be used in mutex locking, not the
131
142
corresponding function. */
133
144
#define mutex_enter_nowait(M) \
134
145
mutex_enter_nowait_func((M), __FILE__, __LINE__)
135
/************************************************************************
146
/********************************************************************//**
136
147
NOTE! Use the corresponding macro in the header file, not this function
137
148
directly. Tries to lock the mutex for the current thread. If the lock is not
138
acquired immediately, returns with return value 1. */
149
acquired immediately, returns with return value 1.
150
@return 0 if succeed, 1 if not */
141
153
mutex_enter_nowait_func(
142
154
/*====================*/
143
/* out: 0 if succeed, 1 if not */
144
mutex_t* mutex, /* in: pointer to mutex */
145
const char* file_name, /* in: file name where mutex
155
mutex_t* mutex, /*!< in: pointer to mutex */
156
const char* file_name, /*!< in: file name where mutex
147
ulint line); /* in: line where requested */
148
/**********************************************************************
158
ulint line); /*!< in: line where requested */
159
/******************************************************************//**
149
160
Unlocks a mutex owned by the current thread. */
154
mutex_t* mutex); /* in: pointer to mutex */
155
/**********************************************************************
165
mutex_t* mutex); /*!< in: pointer to mutex */
166
#ifdef UNIV_SYNC_DEBUG
167
/******************************************************************//**
156
168
Returns TRUE if no mutex or rw-lock is currently locked.
157
Works only in the debug version. */
169
Works only in the debug version.
170
@return TRUE if no mutexes and rw-locks reserved */
160
173
sync_all_freed(void);
161
174
/*================*/
175
#endif /* UNIV_SYNC_DEBUG */
162
176
/*#####################################################################
163
177
FUNCTION PROTOTYPES FOR DEBUGGING */
164
/***********************************************************************
178
/*******************************************************************//**
165
179
Prints wait info of the sync system. */
168
182
sync_print_wait_info(
169
183
/*=================*/
170
FILE* file); /* in: file where to print */
171
/***********************************************************************
184
FILE* file); /*!< in: file where to print */
185
/*******************************************************************//**
172
186
Prints info of the sync system. */
177
FILE* file); /* in: file where to print */
191
FILE* file); /*!< in: file where to print */
178
192
#ifdef UNIV_DEBUG
179
/**********************************************************************
180
Checks that the mutex has been initialized. */
193
/******************************************************************//**
194
Checks that the mutex has been initialized.
185
const mutex_t* mutex);
186
/**********************************************************************
200
const mutex_t* mutex); /*!< in: mutex */
201
/******************************************************************//**
187
202
Checks that the current thread owns the mutex. Works only
188
in the debug version. */
203
in the debug version.
204
@return TRUE if owns */
193
/* out: TRUE if owns */
194
const mutex_t* mutex); /* in: mutex */
209
const mutex_t* mutex); /*!< in: mutex */
195
210
#endif /* UNIV_DEBUG */
196
211
#ifdef UNIV_SYNC_DEBUG
197
/**********************************************************************
212
/******************************************************************//**
198
213
Adds a latch and its level in the thread level array. Allocates the memory
199
214
for the array if called first time for this OS thread. Makes the checks
200
215
against other latch levels stored in the array for this thread. */
203
218
sync_thread_add_level(
204
219
/*==================*/
205
void* latch, /* in: pointer to a mutex or an rw-lock */
206
ulint level); /* in: level in the latching order; if
220
void* latch, /*!< in: pointer to a mutex or an rw-lock */
221
ulint level); /*!< in: level in the latching order; if
207
222
SYNC_LEVEL_VARYING, nothing is done */
208
/**********************************************************************
209
Removes a latch from the thread level array if it is found there. */
223
/******************************************************************//**
224
Removes a latch from the thread level array if it is found there.
225
@return TRUE if found in the array; it is no error if the latch is
226
not found, as we presently are not able to determine the level for
227
every latch reservation the program does */
212
230
sync_thread_reset_level(
213
231
/*====================*/
214
/* out: TRUE if found from the array; it is no error
215
if the latch is not found, as we presently are not
216
able to determine the level for every latch
217
reservation the program does */
218
void* latch); /* in: pointer to a mutex or an rw-lock */
219
/**********************************************************************
220
Checks that the level array for the current thread is empty. */
232
void* latch); /*!< in: pointer to a mutex or an rw-lock */
233
/******************************************************************//**
234
Checks that the level array for the current thread is empty.
235
@return TRUE if empty */
223
238
sync_thread_levels_empty(void);
224
239
/*==========================*/
225
/* out: TRUE if empty */
226
/**********************************************************************
227
Checks that the level array for the current thread is empty. */
240
/******************************************************************//**
241
Checks that the level array for the current thread is empty.
242
@return TRUE if empty except the exceptions specified below */
230
245
sync_thread_levels_empty_gen(
231
246
/*=========================*/
232
/* out: TRUE if empty except the
233
exceptions specified below */
234
ibool dict_mutex_allowed); /* in: TRUE if dictionary mutex is
247
ibool dict_mutex_allowed); /*!< in: TRUE if dictionary mutex is
235
248
allowed to be owned by the thread,
236
249
also purge_is_running mutex is
238
/**********************************************************************
251
/******************************************************************//**
239
252
Gets the debug information for a reserved mutex. */
242
255
mutex_get_debug_info(
243
256
/*=================*/
244
mutex_t* mutex, /* in: mutex */
245
const char** file_name, /* out: file where requested */
246
ulint* line, /* out: line where requested */
247
os_thread_id_t* thread_id); /* out: id of the thread which owns
257
mutex_t* mutex, /*!< in: mutex */
258
const char** file_name, /*!< out: file where requested */
259
ulint* line, /*!< out: line where requested */
260
os_thread_id_t* thread_id); /*!< out: id of the thread which owns
249
/**********************************************************************
250
Counts currently reserved mutexes. Works only in the debug version. */
262
/******************************************************************//**
263
Counts currently reserved mutexes. Works only in the debug version.
264
@return number of reserved mutexes */
253
267
mutex_n_reserved(void);
254
268
/*==================*/
255
269
#endif /* UNIV_SYNC_DEBUG */
256
/**********************************************************************
270
/******************************************************************//**
257
271
NOT to be used outside this module except in debugging! Gets the value
258
272
of the lock word. */
261
275
mutex_get_lock_word(
262
276
/*================*/
263
const mutex_t* mutex); /* in: mutex */
277
const mutex_t* mutex); /*!< in: mutex */
264
278
#ifdef UNIV_SYNC_DEBUG
265
/**********************************************************************
279
/******************************************************************//**
266
280
NOT to be used outside this module except in debugging! Gets the waiters
282
@return value to set */
270
285
mutex_get_waiters(
271
286
/*==============*/
272
/* out: value to set */
273
const mutex_t* mutex); /* in: mutex */
287
const mutex_t* mutex); /*!< in: mutex */
274
288
#endif /* UNIV_SYNC_DEBUG */
481
495
Do not use its fields directly! The structure used in the spin lock
482
496
implementation of a mutual exclusion semaphore. */
484
499
struct mutex_struct {
485
os_event_t event; /* Used by sync0arr.c for the wait queue */
486
byte lock_word; /* This byte is the target of the atomic
487
test-and-set instruction in Win32 and
488
x86 32/64 with GCC 4.1.0 or later version */
489
#if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER)
490
#elif defined(HAVE_GCC_ATOMIC_BUILTINS)
500
os_event_t event; /*!< Used by sync0arr.c for the wait queue */
501
volatile lock_word_t lock_word; /*!< lock_word is the target
502
of the atomic test-and-set instruction when
503
atomic operations are enabled. */
505
#if !defined(HAVE_ATOMIC_BUILTINS)
493
os_fast_mutex; /* In other systems we use this OS mutex
494
in place of lock_word */
507
os_fast_mutex; /*!< We use this OS mutex in place of lock_word
508
when atomic operations are not enabled */
496
ulint waiters; /* This ulint is set to 1 if there are (or
510
ulint waiters; /*!< This ulint is set to 1 if there are (or
497
511
may be) threads waiting in the global wait
498
512
array for this mutex to be released.
499
513
Otherwise, this is 0. */
500
UT_LIST_NODE_T(mutex_t) list; /* All allocated mutexes are put into
514
UT_LIST_NODE_T(mutex_t) list; /*!< All allocated mutexes are put into
501
515
a list. Pointers to the next and prev. */
502
516
#ifdef UNIV_SYNC_DEBUG
503
const char* file_name; /* File where the mutex was locked */
504
ulint line; /* Line where the mutex was locked */
505
ulint level; /* Level in the global latching order */
517
const char* file_name; /*!< File where the mutex was locked */
518
ulint line; /*!< Line where the mutex was locked */
519
ulint level; /*!< Level in the global latching order */
506
520
#endif /* UNIV_SYNC_DEBUG */
507
const char* cfile_name;/* File name where mutex created */
508
ulint cline; /* Line where created */
521
const char* cfile_name;/*!< File name where mutex created */
522
ulint cline; /*!< Line where created */
509
523
#ifdef UNIV_DEBUG
510
os_thread_id_t thread_id; /* The thread id of the thread
524
os_thread_id_t thread_id; /*!< The thread id of the thread
511
525
which locked the mutex. */
526
ulint magic_n; /*!< MUTEX_MAGIC_N */
527
/** Value of mutex_struct::magic_n */
513
528
# define MUTEX_MAGIC_N (ulint)979585
514
529
#endif /* UNIV_DEBUG */
515
#ifndef UNIV_HOTBACKUP
516
ulong count_os_wait; /* count of os_wait */
518
ulong count_using; /* count of times mutex used */
519
ulong count_spin_loop; /* count of spin loops */
520
ulong count_spin_rounds; /* count of spin rounds */
521
ulong count_os_yield; /* count of os_wait */
522
ulonglong lspent_time; /* mutex os_wait timer msec */
523
ulonglong lmax_spent_time; /* mutex os_wait timer msec */
524
const char* cmutex_name;/* mutex name */
525
ulint mutex_type;/* 0 - usual mutex 1 - rw_lock mutex */
526
# endif /* UNIV_DEBUG */
527
#endif /* !UNIV_HOTBACKUP */
530
ulong count_os_wait; /*!< count of os_wait */
532
ulong count_using; /*!< count of times mutex used */
533
ulong count_spin_loop; /*!< count of spin loops */
534
ulong count_spin_rounds;/*!< count of spin rounds */
535
ulong count_os_yield; /*!< count of os_wait */
536
ulonglong lspent_time; /*!< mutex os_wait timer msec */
537
ulonglong lmax_spent_time;/*!< mutex os_wait timer msec */
538
const char* cmutex_name; /*!< mutex name */
539
ulint mutex_type; /*!< 0=usual mutex, 1=rw_lock mutex */
540
#endif /* UNIV_DEBUG */
530
/* The global array of wait cells for implementation of the databases own
531
mutexes and read-write locks. Appears here for debugging purposes only! */
533
extern sync_array_t* sync_primary_wait_array;
535
/* Constant determining how long spin wait is continued before suspending
543
/** The global array of wait cells for implementation of the databases own
544
mutexes and read-write locks. */
545
extern sync_array_t* sync_primary_wait_array;/* Appears here for
546
debugging purposes only! */
548
/** Constant determining how long spin wait is continued before suspending
536
549
the thread. A value 600 rounds on a 1995 100 MHz Pentium seems to correspond
537
550
to 20 microseconds. */
539
552
#define SYNC_SPIN_ROUNDS srv_n_spin_wait_rounds
541
/* The number of system calls made in this module. Intended for performance
554
/** The number of mutex_exit calls. Intended for performance monitoring. */
544
555
extern ib_int64_t mutex_exit_count;
546
557
#ifdef UNIV_SYNC_DEBUG
547
/* Latching order checks start when this is set TRUE */
558
/** Latching order checks start when this is set TRUE */
548
559
extern ibool sync_order_checks_on;
549
560
#endif /* UNIV_SYNC_DEBUG */
551
/* This variable is set to TRUE when sync_init is called */
562
/** This variable is set to TRUE when sync_init is called */
552
563
extern ibool sync_initialized;
554
/* Global list of database mutexes (not OS mutexes) created. */
565
/** Global list of database mutexes (not OS mutexes) created. */
555
566
typedef UT_LIST_BASE_NODE_T(mutex_t) ut_list_base_node_t;
567
/** Global list of database mutexes (not OS mutexes) created. */
556
568
extern ut_list_base_node_t mutex_list;
558
/* Mutex protecting the mutex_list variable */
570
/** Mutex protecting the mutex_list variable */
559
571
extern mutex_t mutex_list_mutex;