95
95
it and did not see the waiters byte set to 1, a case which would lead the
96
96
other thread to an infinite wait.
98
LEMMA 1: After a thread resets the event of a mutex (or rw_lock), some
100
thread will eventually call os_event_set() on that particular event.
101
Thus no infinite wait is possible in this case.
98
LEMMA 1: After a thread resets the event of the cell it reserves for waiting
100
for a mutex, some thread will eventually call sync_array_signal_object with
101
the mutex as an argument. Thus no infinite wait is possible.
103
103
Proof: After making the reservation the thread sets the waiters field in the
104
104
mutex to 1. Then it checks that the mutex is still reserved by some thread,
105
105
or it reserves the mutex for itself. In any case, some thread (which may be
106
106
also some earlier thread, not necessarily the one currently holding the mutex)
107
107
will set the waiters field to 0 in mutex_exit, and then call
108
os_event_set() with the mutex as an argument.
111
LEMMA 2: If an os_event_set() call is made after some thread has called
113
the os_event_reset() and before it starts wait on that event, the call
114
will not be lost to the second thread. This is true even if there is an
115
intervening call to os_event_reset() by another thread.
116
Thus no infinite wait is possible in this case.
118
Proof (non-windows platforms): os_event_reset() returns a monotonically
119
increasing value of signal_count. This value is increased at every
120
call of os_event_set() If thread A has called os_event_reset() followed
121
by thread B calling os_event_set() and then some other thread C calling
122
os_event_reset(), the is_set flag of the event will be set to FALSE;
123
but now if thread A calls os_event_wait_low() with the signal_count
124
value returned from the earlier call of os_event_reset(), it will
125
return immediately without waiting.
128
Proof (windows): If there is a writer thread which is forced to wait for
129
the lock, it may be able to set the state of rw_lock to RW_LOCK_WAIT_EX
130
The design of rw_lock ensures that there is one and only one thread
131
that is able to change the state to RW_LOCK_WAIT_EX and this thread is
132
guaranteed to acquire the lock after it is released by the current
133
holders and before any other waiter gets the lock.
134
On windows this thread waits on a separate event i.e.: wait_ex_event.
135
Since only one thread can wait on this event there is no chance
136
of this event getting reset before the writer starts wait on it.
137
Therefore, this thread is guaranteed to catch the os_set_event()
138
signalled unconditionally at the release of the lock.
108
sync_array_signal_object with the mutex as an argument.
141
111
/* The number of system calls made in this module. Intended for performance
144
UNIV_INTERN ulint mutex_system_call_count = 0;
114
ulint mutex_system_call_count = 0;
146
116
/* Number of spin waits on mutexes: for performance monitoring */
148
118
/* round=one iteration of a spin loop */
149
UNIV_INTERN ulint mutex_spin_round_count = 0;
150
UNIV_INTERN ulint mutex_spin_wait_count = 0;
151
UNIV_INTERN ulint mutex_os_wait_count = 0;
152
UNIV_INTERN ulint mutex_exit_count = 0;
119
ulint mutex_spin_round_count = 0;
120
ulint mutex_spin_wait_count = 0;
121
ulint mutex_os_wait_count = 0;
122
ulint mutex_exit_count = 0;
154
124
/* The global array of wait cells for implementation of the database's own
155
125
mutexes and read-write locks */
156
UNIV_INTERN sync_array_t* sync_primary_wait_array;
126
sync_array_t* sync_primary_wait_array;
158
128
/* This variable is set to TRUE when sync_init is called */
159
UNIV_INTERN ibool sync_initialized = FALSE;
129
ibool sync_initialized = FALSE;
162
132
typedef struct sync_level_struct sync_level_t;
166
136
/* The latch levels currently owned by threads are stored in this data
167
137
structure; the size of this array is OS_THREAD_MAX_N */
169
UNIV_INTERN sync_thread_t* sync_thread_level_arrays;
139
sync_thread_t* sync_thread_level_arrays;
171
141
/* Mutex protecting sync_thread_level_arrays */
172
UNIV_INTERN mutex_t sync_thread_mutex;
142
mutex_t sync_thread_mutex;
173
143
#endif /* UNIV_SYNC_DEBUG */
175
145
/* Global list of database mutexes (not OS mutexes) created. */
176
UNIV_INTERN ut_list_base_node_t mutex_list;
146
ut_list_base_node_t mutex_list;
178
148
/* Mutex protecting the mutex_list variable */
179
UNIV_INTERN mutex_t mutex_list_mutex;
149
mutex_t mutex_list_mutex;
181
151
#ifdef UNIV_SYNC_DEBUG
182
152
/* Latching order checks start when this is set TRUE */
183
UNIV_INTERN ibool sync_order_checks_on = FALSE;
153
ibool sync_order_checks_on = FALSE;
184
154
#endif /* UNIV_SYNC_DEBUG */
186
156
struct sync_thread_struct{
201
171
/**********************************************************************
172
A noninlined function that reserves a mutex. In ha_innodb.cc we have disabled
173
inlining of InnoDB functions, and no inlined functions should be called from
174
there. That is why we need to duplicate the inlined function here. */
177
mutex_enter_noninline(
178
/*==================*/
179
mutex_t* mutex) /* in: mutex */
184
/**********************************************************************
188
mutex_exit_noninline(
189
/*=================*/
190
mutex_t* mutex) /* in: mutex */
195
/**********************************************************************
202
196
Creates, or rather, initializes a mutex object in a specified memory
203
197
location (which must be appropriately aligned). The mutex is initialized
204
198
in the reset state. Explicit freeing of the mutex with mutex_free is
205
199
necessary only if the memory block containing it is freed. */
208
202
mutex_create_func(
209
203
/*==============*/
1048
1040
/* Do no order checking */
1050
1042
case SYNC_MEM_POOL:
1043
ut_a(sync_thread_levels_g(array, SYNC_MEM_POOL));
1051
1045
case SYNC_MEM_HASH:
1046
ut_a(sync_thread_levels_g(array, SYNC_MEM_HASH));
1052
1048
case SYNC_RECV:
1049
ut_a(sync_thread_levels_g(array, SYNC_RECV));
1053
1051
case SYNC_WORK_QUEUE:
1052
ut_a(sync_thread_levels_g(array, SYNC_WORK_QUEUE));
1055
ut_a(sync_thread_levels_g(array, SYNC_LOG));
1055
1057
case SYNC_THR_LOCAL:
1058
ut_a(sync_thread_levels_g(array, SYNC_THR_LOCAL));
1056
1060
case SYNC_ANY_LATCH:
1061
ut_a(sync_thread_levels_g(array, SYNC_ANY_LATCH));
1057
1063
case SYNC_TRX_SYS_HEADER:
1058
case SYNC_FILE_FORMAT_TAG:
1064
ut_a(sync_thread_levels_g(array, SYNC_TRX_SYS_HEADER));
1059
1066
case SYNC_DOUBLEWRITE:
1061
case SYNC_SEARCH_SYS:
1062
case SYNC_TRX_LOCK_HEAP:
1064
case SYNC_IBUF_BITMAP_MUTEX:
1067
case SYNC_PURGE_LATCH:
1068
case SYNC_PURGE_SYS:
1069
case SYNC_DICT_AUTOINC_MUTEX:
1070
case SYNC_DICT_OPERATION:
1071
case SYNC_DICT_HEADER:
1072
case SYNC_TRX_I_S_RWLOCK:
1073
case SYNC_TRX_I_S_LAST_READ:
1074
if (!sync_thread_levels_g(array, level)) {
1076
"InnoDB: sync_thread_levels_g(array, %lu)"
1077
" does not hold!\n", level);
1067
ut_a(sync_thread_levels_g(array, SYNC_DOUBLEWRITE));
1081
1069
case SYNC_BUF_BLOCK:
1082
1070
ut_a((sync_thread_levels_contain(array, SYNC_BUF_POOL)
1083
1071
&& sync_thread_levels_g(array, SYNC_BUF_BLOCK - 1))
1084
1072
|| sync_thread_levels_g(array, SYNC_BUF_BLOCK));
1075
ut_a(sync_thread_levels_g(array, SYNC_BUF_POOL));
1077
case SYNC_SEARCH_SYS:
1078
ut_a(sync_thread_levels_g(array, SYNC_SEARCH_SYS));
1080
case SYNC_TRX_LOCK_HEAP:
1081
ut_a(sync_thread_levels_g(array, SYNC_TRX_LOCK_HEAP));
1086
1083
case SYNC_REC_LOCK:
1087
1084
ut_a((sync_thread_levels_contain(array, SYNC_KERNEL)
1088
1085
&& sync_thread_levels_g(array, SYNC_REC_LOCK - 1))
1089
1086
|| sync_thread_levels_g(array, SYNC_REC_LOCK));
1089
ut_a(sync_thread_levels_g(array, SYNC_KERNEL));
1091
1091
case SYNC_IBUF_BITMAP:
1092
1092
ut_a((sync_thread_levels_contain(array, SYNC_IBUF_BITMAP_MUTEX)
1093
1093
&& sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1))
1094
1094
|| sync_thread_levels_g(array, SYNC_IBUF_BITMAP));
1096
case SYNC_IBUF_BITMAP_MUTEX:
1097
ut_a(sync_thread_levels_g(array, SYNC_IBUF_BITMAP_MUTEX));
1096
1099
case SYNC_FSP_PAGE:
1097
1100
ut_a(sync_thread_levels_contain(array, SYNC_FSP));
1113
1116
ut_a(sync_thread_levels_contain(array, SYNC_KERNEL)
1114
1117
&& sync_thread_levels_contain(array, SYNC_FSP_PAGE));
1120
ut_a(sync_thread_levels_g(array, SYNC_RSEG));
1123
ut_a(sync_thread_levels_g(array, SYNC_TRX_UNDO));
1125
case SYNC_PURGE_LATCH:
1126
ut_a(sync_thread_levels_g(array, SYNC_PURGE_LATCH));
1128
case SYNC_PURGE_SYS:
1129
ut_a(sync_thread_levels_g(array, SYNC_PURGE_SYS));
1116
1131
case SYNC_TREE_NODE:
1117
1132
ut_a(sync_thread_levels_contain(array, SYNC_INDEX_TREE)
1118
|| sync_thread_levels_contain(array, SYNC_DICT_OPERATION)
1119
1133
|| sync_thread_levels_g(array, SYNC_TREE_NODE - 1));
1121
1135
case SYNC_TREE_NODE_NEW: