1/*****************************************************************************
2
3Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
4Copyright (c) 2008, Google Inc.
5
6Portions of this file contain modifications contributed and copyrighted by
7Google, Inc. Those modifications are gratefully acknowledged and are described
8briefly in the InnoDB documentation. The contributions by Google are
9incorporated with their permission, and subject to the conditions contained in
10the file COPYING.Google.
11
12This program is free software; you can redistribute it and/or modify it under
13the terms of the GNU General Public License as published by the Free Software
14Foundation; version 2 of the License.
15
16This program is distributed in the hope that it will be useful, but WITHOUT
17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License along with
21this program; if not, write to the Free Software Foundation, Inc.,
2251 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
23
24*****************************************************************************/
25
26/**************************************************//**
27@file sync/sync0sync.cc
28Mutex, the basic synchronization primitive
29
30Created 9/5/1995 Heikki Tuuri
31*******************************************************/
32
33#include "univ.i"
34#include "sync0rw.h"
35#include "sync0sync.h"
36
37#ifdef UNIV_PFS_MUTEX
38/* Key to register autoinc_mutex with performance schema */
39mysql_pfs_key_t autoinc_mutex_key;
40mysql_pfs_key_t buffer_block_mutex_key;
41mysql_pfs_key_t buf_pool_mutex_key;
42mysql_pfs_key_t buf_pool_zip_mutex_key;
43mysql_pfs_key_t cache_last_read_mutex_key;
44mysql_pfs_key_t dict_foreign_err_mutex_key;
45mysql_pfs_key_t dict_sys_mutex_key;
46mysql_pfs_key_t fil_system_mutex_key;
47mysql_pfs_key_t flush_list_mutex_key;
48mysql_pfs_key_t fts_bg_threads_mutex_key;
49mysql_pfs_key_t fts_delete_mutex_key;
50mysql_pfs_key_t fts_optimize_mutex_key;
51mysql_pfs_key_t fts_doc_id_mutex_key;
52mysql_pfs_key_t fts_pll_tokenize_mutex_key;
53mysql_pfs_key_t hash_table_mutex_key;
54mysql_pfs_key_t ibuf_bitmap_mutex_key;
55mysql_pfs_key_t ibuf_mutex_key;
56mysql_pfs_key_t ibuf_pessimistic_insert_mutex_key;
57mysql_pfs_key_t log_sys_mutex_key;
58mysql_pfs_key_t log_sys_write_mutex_key;
59mysql_pfs_key_t log_cmdq_mutex_key;
60mysql_pfs_key_t log_flush_order_mutex_key;
61mysql_pfs_key_t mutex_list_mutex_key;
62mysql_pfs_key_t recalc_pool_mutex_key;
63mysql_pfs_key_t page_cleaner_mutex_key;
64mysql_pfs_key_t purge_sys_pq_mutex_key;
65mysql_pfs_key_t recv_sys_mutex_key;
66mysql_pfs_key_t recv_writer_mutex_key;
67mysql_pfs_key_t redo_rseg_mutex_key;
68mysql_pfs_key_t noredo_rseg_mutex_key;
69mysql_pfs_key_t page_zip_stat_per_index_mutex_key;
70# ifdef UNIV_DEBUG
71mysql_pfs_key_t rw_lock_debug_mutex_key;
72# endif /* UNIV_DEBUG */
73mysql_pfs_key_t rtr_active_mutex_key;
74mysql_pfs_key_t rtr_match_mutex_key;
75mysql_pfs_key_t rtr_path_mutex_key;
76mysql_pfs_key_t rtr_ssn_mutex_key;
77mysql_pfs_key_t rw_lock_list_mutex_key;
78mysql_pfs_key_t rw_lock_mutex_key;
79mysql_pfs_key_t srv_innodb_monitor_mutex_key;
80mysql_pfs_key_t srv_misc_tmpfile_mutex_key;
81mysql_pfs_key_t srv_monitor_file_mutex_key;
82mysql_pfs_key_t buf_dblwr_mutex_key;
83mysql_pfs_key_t trx_mutex_key;
84mysql_pfs_key_t trx_pool_mutex_key;
85mysql_pfs_key_t trx_pool_manager_mutex_key;
86mysql_pfs_key_t lock_mutex_key;
87mysql_pfs_key_t lock_wait_mutex_key;
88mysql_pfs_key_t trx_sys_mutex_key;
89mysql_pfs_key_t srv_sys_mutex_key;
90mysql_pfs_key_t srv_threads_mutex_key;
91mysql_pfs_key_t event_mutex_key;
92mysql_pfs_key_t event_manager_mutex_key;
93mysql_pfs_key_t sync_array_mutex_key;
94mysql_pfs_key_t thread_mutex_key;
95mysql_pfs_key_t zip_pad_mutex_key;
96mysql_pfs_key_t row_drop_list_mutex_key;
97mysql_pfs_key_t rw_trx_hash_element_mutex_key;
98#endif /* UNIV_PFS_MUTEX */
99#ifdef UNIV_PFS_RWLOCK
100mysql_pfs_key_t btr_search_latch_key;
101mysql_pfs_key_t buf_block_lock_key;
102# ifdef UNIV_DEBUG
103mysql_pfs_key_t buf_block_debug_latch_key;
104# endif /* UNIV_DEBUG */
105mysql_pfs_key_t checkpoint_lock_key;
106mysql_pfs_key_t dict_operation_lock_key;
107mysql_pfs_key_t dict_table_stats_key;
108mysql_pfs_key_t hash_table_locks_key;
109mysql_pfs_key_t index_tree_rw_lock_key;
110mysql_pfs_key_t index_online_log_key;
111mysql_pfs_key_t fil_space_latch_key;
112mysql_pfs_key_t fts_cache_rw_lock_key;
113mysql_pfs_key_t fts_cache_init_rw_lock_key;
114mysql_pfs_key_t trx_i_s_cache_lock_key;
115mysql_pfs_key_t trx_purge_latch_key;
116#endif /* UNIV_PFS_RWLOCK */
117
118/** For monitoring active mutexes */
119MutexMonitor mutex_monitor;
120
121/**
122Prints wait info of the sync system.
123@param file - where to print */
124static
125void
126sync_print_wait_info(FILE* file)
127{
128 fprintf(file,
129 "RW-shared spins " UINT64PF ", rounds " UINT64PF ","
130 " OS waits " UINT64PF "\n"
131 "RW-excl spins " UINT64PF ", rounds " UINT64PF ","
132 " OS waits " UINT64PF "\n"
133 "RW-sx spins " UINT64PF ", rounds " UINT64PF ","
134 " OS waits " UINT64PF "\n",
135 (ib_uint64_t) rw_lock_stats.rw_s_spin_wait_count,
136 (ib_uint64_t) rw_lock_stats.rw_s_spin_round_count,
137 (ib_uint64_t) rw_lock_stats.rw_s_os_wait_count,
138 (ib_uint64_t) rw_lock_stats.rw_x_spin_wait_count,
139 (ib_uint64_t) rw_lock_stats.rw_x_spin_round_count,
140 (ib_uint64_t) rw_lock_stats.rw_x_os_wait_count,
141 (ib_uint64_t) rw_lock_stats.rw_sx_spin_wait_count,
142 (ib_uint64_t) rw_lock_stats.rw_sx_spin_round_count,
143 (ib_uint64_t) rw_lock_stats.rw_sx_os_wait_count);
144
145 fprintf(file,
146 "Spin rounds per wait: %.2f RW-shared,"
147 " %.2f RW-excl, %.2f RW-sx\n",
148 (double) rw_lock_stats.rw_s_spin_round_count /
149 (rw_lock_stats.rw_s_spin_wait_count
150 ? rw_lock_stats.rw_s_spin_wait_count : 1LL),
151 (double) rw_lock_stats.rw_x_spin_round_count /
152 (rw_lock_stats.rw_x_spin_wait_count
153 ? rw_lock_stats.rw_x_spin_wait_count : 1LL),
154 (double) rw_lock_stats.rw_sx_spin_round_count /
155 (rw_lock_stats.rw_sx_spin_wait_count
156 ? rw_lock_stats.rw_sx_spin_wait_count : 1LL));
157}
158
159/**
160Prints info of the sync system.
161@param file - where to print */
162void
163sync_print(FILE* file)
164{
165#ifdef UNIV_DEBUG
166 rw_lock_list_print_info(file);
167#endif /* UNIV_DEBUG */
168
169 sync_array_print(file);
170
171 sync_print_wait_info(file);
172}
173
174/** Print the filename "basename" e.g., p = "/a/b/c/d/e.cc" -> p = "e.cc"
175@param[in] filename Name from where to extract the basename
176@return the basename */
177const char*
178sync_basename(const char* filename)
179{
180 const char* ptr = filename + strlen(filename) - 1;
181
182 while (ptr > filename && *ptr != '/' && *ptr != '\\') {
183 --ptr;
184 }
185
186 ++ptr;
187
188 return(ptr);
189}
190
191/** String representation of the filename and line number where the
192latch was created
193@param[in] id Latch ID
194@param[in] created Filename and line number where it was crated
195@return the string representation */
196std::string
197sync_mutex_to_string(
198 latch_id_t id,
199 const std::string& created)
200{
201 std::ostringstream msg;
202
203 msg << "Mutex " << sync_latch_get_name(id) << " "
204 << "created " << created;
205
206 return(msg.str());
207}
208
209/** Enable the mutex monitoring */
210void
211MutexMonitor::enable()
212{
213 /** Note: We don't add any latch meta-data after startup. Therefore
214 there is no need to use a mutex here. */
215
216 LatchMetaData::iterator end = latch_meta.end();
217
218 for (LatchMetaData::iterator it = latch_meta.begin(); it != end; ++it) {
219
220 if (*it != NULL) {
221 (*it)->get_counter()->enable();
222 }
223 }
224}
225
226/** Disable the mutex monitoring */
227void
228MutexMonitor::disable()
229{
230 /** Note: We don't add any latch meta-data after startup. Therefore
231 there is no need to use a mutex here. */
232
233 LatchMetaData::iterator end = latch_meta.end();
234
235 for (LatchMetaData::iterator it = latch_meta.begin(); it != end; ++it) {
236
237 if (*it != NULL) {
238 (*it)->get_counter()->disable();
239 }
240 }
241}
242
243/** Reset the mutex monitoring counters */
244void
245MutexMonitor::reset()
246{
247 /** Note: We don't add any latch meta-data after startup. Therefore
248 there is no need to use a mutex here. */
249
250 LatchMetaData::iterator end = latch_meta.end();
251
252 for (LatchMetaData::iterator it = latch_meta.begin(); it != end; ++it) {
253
254 if (*it != NULL) {
255 (*it)->get_counter()->reset();
256 }
257 }
258
259 mutex_enter(&rw_lock_list_mutex);
260
261 for (rw_lock_t* rw_lock = UT_LIST_GET_FIRST(rw_lock_list);
262 rw_lock != NULL;
263 rw_lock = UT_LIST_GET_NEXT(list, rw_lock)) {
264
265 rw_lock->count_os_wait = 0;
266 }
267
268 mutex_exit(&rw_lock_list_mutex);
269}
270