| 1 | #ifdef MYSQL_TOKUDB_ENGINE |
| 2 | #include "toku_portability.h" |
| 3 | #include "toku_pthread.h" |
| 4 | |
| 5 | toku_instr_probe_pfs::toku_instr_probe_pfs(const toku_instr_key &key) |
| 6 | : mutex(new toku_mutex_t) { |
| 7 | toku_mutex_init(key, mutex.get(), nullptr); |
| 8 | } |
| 9 | |
| 10 | toku_instr_probe_pfs::~toku_instr_probe_pfs() { |
| 11 | toku_mutex_destroy(mutex.get()); |
| 12 | } |
| 13 | |
| 14 | // Thread instrumentation |
| 15 | |
| 16 | int toku_pthread_create(const toku_instr_key &key, |
| 17 | pthread_t *thread, |
| 18 | const pthread_attr_t *attr, |
| 19 | void *(*start_routine)(void *), |
| 20 | void *arg) { |
| 21 | #if (MYSQL_VERSION_MAJOR >= 5) && (MYSQL_VERSION_MINOR >= 7) |
| 22 | return PSI_THREAD_CALL(spawn_thread)( |
| 23 | key.id(), reinterpret_cast<my_thread_handle *>(thread), |
| 24 | attr, start_routine, arg); |
| 25 | #else |
| 26 | return PSI_THREAD_CALL(spawn_thread)( |
| 27 | key.id(), thread, attr, start_routine, arg); |
| 28 | #endif |
| 29 | } |
| 30 | |
| 31 | void toku_instr_register_current_thread(const toku_instr_key &key) { |
| 32 | struct PSI_thread *psi_thread = |
| 33 | PSI_THREAD_CALL(new_thread)(key.id(), nullptr, 0); |
| 34 | PSI_THREAD_CALL(set_thread)(psi_thread); |
| 35 | } |
| 36 | |
| 37 | void toku_instr_delete_current_thread() { |
| 38 | PSI_THREAD_CALL(delete_current_thread)(); |
| 39 | } |
| 40 | |
| 41 | // I/O instrumentation |
| 42 | |
| 43 | void toku_instr_file_open_begin(toku_io_instrumentation &io_instr, |
| 44 | const toku_instr_key &key, |
| 45 | toku_instr_file_op op, |
| 46 | const char *name, |
| 47 | const char *src_file, |
| 48 | int src_line) { |
| 49 | io_instr.locker = |
| 50 | PSI_FILE_CALL(get_thread_file_name_locker)( |
| 51 | &io_instr.state, key.id(), static_cast<PSI_file_operation>(op), |
| 52 | name, io_instr.locker); |
| 53 | if (io_instr.locker != nullptr) { |
| 54 | PSI_FILE_CALL(start_file_open_wait) |
| 55 | (io_instr.locker, src_file, src_line); |
| 56 | } |
| 57 | } |
| 58 | |
| 59 | void toku_instr_file_stream_open_end(toku_io_instrumentation &io_instr, |
| 60 | TOKU_FILE &file) { |
| 61 | file.key = nullptr; |
| 62 | if (FT_LIKELY(io_instr.locker)) { |
| 63 | file.key = |
| 64 | PSI_FILE_CALL(end_file_open_wait)(io_instr.locker, file.file); |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | void toku_instr_file_open_end(toku_io_instrumentation &io_instr, int fd) { |
| 69 | if (FT_LIKELY(io_instr.locker)) |
| 70 | PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor) |
| 71 | (io_instr.locker, fd); |
| 72 | } |
| 73 | |
| 74 | void toku_instr_file_name_close_begin(toku_io_instrumentation &io_instr, |
| 75 | const toku_instr_key &key, |
| 76 | toku_instr_file_op op, |
| 77 | const char *name, |
| 78 | const char *src_file, |
| 79 | int src_line) { |
| 80 | io_instr.locker = |
| 81 | PSI_FILE_CALL(get_thread_file_name_locker)( |
| 82 | &io_instr.state, key.id(), static_cast<PSI_file_operation>(op), |
| 83 | name, |
| 84 | io_instr.locker); |
| 85 | if (FT_LIKELY(io_instr.locker)) { |
| 86 | PSI_FILE_CALL(start_file_close_wait) |
| 87 | (io_instr.locker, src_file, src_line); |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | void toku_instr_file_stream_close_begin(toku_io_instrumentation &io_instr, |
| 92 | toku_instr_file_op op, |
| 93 | const TOKU_FILE &file, |
| 94 | const char *src_file, |
| 95 | int src_line) { |
| 96 | io_instr.locker = nullptr; |
| 97 | if (FT_LIKELY(file.key)) { |
| 98 | io_instr.locker = PSI_FILE_CALL(get_thread_file_stream_locker)( |
| 99 | &io_instr.state, file.key, (PSI_file_operation)op); |
| 100 | if (FT_LIKELY(io_instr.locker)) { |
| 101 | PSI_FILE_CALL(start_file_close_wait) |
| 102 | (io_instr.locker, src_file, src_line); |
| 103 | } |
| 104 | } |
| 105 | } |
| 106 | |
| 107 | void toku_instr_file_fd_close_begin(toku_io_instrumentation &io_instr, |
| 108 | toku_instr_file_op op, |
| 109 | int fd, |
| 110 | const char *src_file, |
| 111 | int src_line) { |
| 112 | io_instr.locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( |
| 113 | &io_instr.state, fd, (PSI_file_operation)op); |
| 114 | if (FT_LIKELY(io_instr.locker)) { |
| 115 | PSI_FILE_CALL(start_file_close_wait) |
| 116 | (io_instr.locker, src_file, src_line); |
| 117 | } |
| 118 | } |
| 119 | |
| 120 | void toku_instr_file_close_end(const toku_io_instrumentation &io_instr, |
| 121 | int result) { |
| 122 | if (FT_LIKELY(io_instr.locker)) |
| 123 | PSI_FILE_CALL(end_file_close_wait) |
| 124 | (io_instr.locker, result); |
| 125 | } |
| 126 | |
| 127 | void toku_instr_file_io_begin(toku_io_instrumentation &io_instr, |
| 128 | toku_instr_file_op op, |
| 129 | int fd, |
| 130 | ssize_t count, |
| 131 | const char *src_file, |
| 132 | int src_line) { |
| 133 | io_instr.locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( |
| 134 | &io_instr.state, fd, (PSI_file_operation)op); |
| 135 | if (FT_LIKELY(io_instr.locker)) { |
| 136 | PSI_FILE_CALL(start_file_wait) |
| 137 | (io_instr.locker, count, src_file, src_line); |
| 138 | } |
| 139 | } |
| 140 | |
| 141 | void toku_instr_file_name_io_begin(toku_io_instrumentation &io_instr, |
| 142 | const toku_instr_key &key, |
| 143 | toku_instr_file_op op, |
| 144 | const char *name, |
| 145 | ssize_t count, |
| 146 | const char *src_file, |
| 147 | int src_line) { |
| 148 | io_instr.locker = |
| 149 | PSI_FILE_CALL(get_thread_file_name_locker)(&io_instr.state, |
| 150 | key.id(), |
| 151 | (PSI_file_operation)op, |
| 152 | name, |
| 153 | &io_instr.locker); |
| 154 | if (FT_LIKELY(io_instr.locker)) { |
| 155 | PSI_FILE_CALL(start_file_wait) |
| 156 | (io_instr.locker, count, src_file, src_line); |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | void toku_instr_file_stream_io_begin(toku_io_instrumentation &io_instr, |
| 161 | toku_instr_file_op op, |
| 162 | const TOKU_FILE &file, |
| 163 | ssize_t count, |
| 164 | const char *src_file, |
| 165 | int src_line) { |
| 166 | io_instr.locker = nullptr; |
| 167 | if (FT_LIKELY(file.key)) { |
| 168 | io_instr.locker = PSI_FILE_CALL(get_thread_file_stream_locker)( |
| 169 | &io_instr.state, file.key, (PSI_file_operation)op); |
| 170 | if (FT_LIKELY(io_instr.locker)) { |
| 171 | PSI_FILE_CALL(start_file_wait) |
| 172 | (io_instr.locker, count, src_file, src_line); |
| 173 | } |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | void toku_instr_file_io_end(toku_io_instrumentation &io_instr, ssize_t count) { |
| 178 | if (FT_LIKELY(io_instr.locker)) |
| 179 | PSI_FILE_CALL(end_file_wait) |
| 180 | (io_instr.locker, count); |
| 181 | } |
| 182 | |
| 183 | // Mutex instrumentation |
| 184 | |
| 185 | void toku_instr_mutex_init(const toku_instr_key &key, toku_mutex_t &mutex) { |
| 186 | mutex.psi_mutex = PSI_MUTEX_CALL(init_mutex)(key.id(), &mutex.pmutex); |
| 187 | #if TOKU_PTHREAD_DEBUG |
| 188 | mutex.instr_key_id = key.id(); |
| 189 | #endif |
| 190 | } |
| 191 | |
| 192 | void toku_instr_mutex_destroy(PSI_mutex *&mutex_instr) { |
| 193 | if (mutex_instr != nullptr) { |
| 194 | PSI_MUTEX_CALL(destroy_mutex)(mutex_instr); |
| 195 | mutex_instr = nullptr; |
| 196 | } |
| 197 | } |
| 198 | |
| 199 | void toku_instr_mutex_lock_start(toku_mutex_instrumentation &mutex_instr, |
| 200 | toku_mutex_t &mutex, |
| 201 | const char *src_file, |
| 202 | int src_line) { |
| 203 | mutex_instr.locker = nullptr; |
| 204 | if (mutex.psi_mutex) { |
| 205 | mutex_instr.locker = |
| 206 | PSI_MUTEX_CALL(start_mutex_wait)(&mutex_instr.state, |
| 207 | mutex.psi_mutex, |
| 208 | PSI_MUTEX_LOCK, |
| 209 | src_file, |
| 210 | src_line); |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | void toku_instr_mutex_trylock_start(toku_mutex_instrumentation &mutex_instr, |
| 215 | toku_mutex_t &mutex, |
| 216 | const char *src_file, |
| 217 | int src_line) { |
| 218 | mutex_instr.locker = nullptr; |
| 219 | if (mutex.psi_mutex) { |
| 220 | mutex_instr.locker = |
| 221 | PSI_MUTEX_CALL(start_mutex_wait)(&mutex_instr.state, |
| 222 | mutex.psi_mutex, |
| 223 | PSI_MUTEX_TRYLOCK, |
| 224 | src_file, |
| 225 | src_line); |
| 226 | } |
| 227 | } |
| 228 | |
| 229 | void toku_instr_mutex_lock_end(toku_mutex_instrumentation &mutex_instr, |
| 230 | int pthread_mutex_lock_result) { |
| 231 | if (mutex_instr.locker) |
| 232 | PSI_MUTEX_CALL(end_mutex_wait) |
| 233 | (mutex_instr.locker, pthread_mutex_lock_result); |
| 234 | } |
| 235 | |
| 236 | void toku_instr_mutex_unlock(PSI_mutex *mutex_instr) { |
| 237 | if (mutex_instr) |
| 238 | PSI_MUTEX_CALL(unlock_mutex)(mutex_instr); |
| 239 | } |
| 240 | |
| 241 | // Condvar instrumentation |
| 242 | |
| 243 | void toku_instr_cond_init(const toku_instr_key &key, toku_cond_t &cond) { |
| 244 | cond.psi_cond = PSI_COND_CALL(init_cond)(key.id(), &cond.pcond); |
| 245 | #if TOKU_PTHREAD_DEBUG |
| 246 | cond.instr_key_id = key.id(); |
| 247 | #endif |
| 248 | } |
| 249 | |
| 250 | void toku_instr_cond_destroy(PSI_cond *&cond_instr) { |
| 251 | if (cond_instr != nullptr) { |
| 252 | PSI_COND_CALL(destroy_cond)(cond_instr); |
| 253 | cond_instr = nullptr; |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | void toku_instr_cond_wait_start(toku_cond_instrumentation &cond_instr, |
| 258 | toku_instr_cond_op op, |
| 259 | toku_cond_t &cond, |
| 260 | toku_mutex_t &mutex, |
| 261 | const char *src_file, |
| 262 | int src_line) { |
| 263 | cond_instr.locker = nullptr; |
| 264 | if (cond.psi_cond) { |
| 265 | /* Instrumentation start */ |
| 266 | cond_instr.locker = |
| 267 | PSI_COND_CALL(start_cond_wait)(&cond_instr.state, |
| 268 | cond.psi_cond, |
| 269 | mutex.psi_mutex, |
| 270 | (PSI_cond_operation)op, |
| 271 | src_file, |
| 272 | src_line); |
| 273 | } |
| 274 | } |
| 275 | |
| 276 | void toku_instr_cond_wait_end(toku_cond_instrumentation &cond_instr, |
| 277 | int pthread_cond_wait_result) { |
| 278 | if (cond_instr.locker) |
| 279 | PSI_COND_CALL(end_cond_wait) |
| 280 | (cond_instr.locker, pthread_cond_wait_result); |
| 281 | } |
| 282 | |
| 283 | void toku_instr_cond_signal(const toku_cond_t &cond) { |
| 284 | if (cond.psi_cond) |
| 285 | PSI_COND_CALL(signal_cond)(cond.psi_cond); |
| 286 | } |
| 287 | |
| 288 | void toku_instr_cond_broadcast(const toku_cond_t &cond) { |
| 289 | if (cond.psi_cond) |
| 290 | PSI_COND_CALL(broadcast_cond)(cond.psi_cond); |
| 291 | } |
| 292 | |
| 293 | // rwlock instrumentation |
| 294 | |
| 295 | void toku_instr_rwlock_init(const toku_instr_key &key, |
| 296 | toku_pthread_rwlock_t &rwlock) { |
| 297 | rwlock.psi_rwlock = PSI_RWLOCK_CALL(init_rwlock)(key.id(), &rwlock.rwlock); |
| 298 | #if TOKU_PTHREAD_DEBUG |
| 299 | rwlock.instr_key_id = key.id(); |
| 300 | #endif |
| 301 | } |
| 302 | |
| 303 | void toku_instr_rwlock_destroy(PSI_rwlock *&rwlock_instr) { |
| 304 | if (rwlock_instr != nullptr) { |
| 305 | PSI_RWLOCK_CALL(destroy_rwlock)(rwlock_instr); |
| 306 | rwlock_instr = nullptr; |
| 307 | } |
| 308 | } |
| 309 | |
| 310 | void toku_instr_rwlock_rdlock_wait_start( |
| 311 | toku_rwlock_instrumentation &rwlock_instr, |
| 312 | toku_pthread_rwlock_t &rwlock, |
| 313 | const char *src_file, |
| 314 | int src_line) { |
| 315 | rwlock_instr.locker = nullptr; |
| 316 | if (rwlock.psi_rwlock) { |
| 317 | /* Instrumentation start */ |
| 318 | rwlock_instr.locker = |
| 319 | PSI_RWLOCK_CALL(start_rwlock_rdwait)(&rwlock_instr.state, |
| 320 | rwlock.psi_rwlock, |
| 321 | PSI_RWLOCK_READLOCK, |
| 322 | src_file, |
| 323 | src_line); |
| 324 | } |
| 325 | } |
| 326 | |
| 327 | void toku_instr_rwlock_wrlock_wait_start( |
| 328 | toku_rwlock_instrumentation &rwlock_instr, |
| 329 | toku_pthread_rwlock_t &rwlock, |
| 330 | const char *src_file, |
| 331 | int src_line) { |
| 332 | rwlock_instr.locker = nullptr; |
| 333 | if (rwlock.psi_rwlock) { |
| 334 | /* Instrumentation start */ |
| 335 | rwlock_instr.locker = |
| 336 | PSI_RWLOCK_CALL(start_rwlock_wrwait)(&rwlock_instr.state, |
| 337 | rwlock.psi_rwlock, |
| 338 | PSI_RWLOCK_WRITELOCK, |
| 339 | src_file, |
| 340 | src_line); |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | void toku_instr_rwlock_rdlock_wait_end( |
| 345 | toku_rwlock_instrumentation &rwlock_instr, |
| 346 | int pthread_rwlock_wait_result) { |
| 347 | if (rwlock_instr.locker) |
| 348 | PSI_RWLOCK_CALL(end_rwlock_rdwait) |
| 349 | (rwlock_instr.locker, pthread_rwlock_wait_result); |
| 350 | } |
| 351 | |
| 352 | void toku_instr_rwlock_wrlock_wait_end( |
| 353 | toku_rwlock_instrumentation &rwlock_instr, |
| 354 | int pthread_rwlock_wait_result) { |
| 355 | if (rwlock_instr.locker) |
| 356 | PSI_RWLOCK_CALL(end_rwlock_wrwait) |
| 357 | (rwlock_instr.locker, pthread_rwlock_wait_result); |
| 358 | } |
| 359 | |
| 360 | void toku_instr_rwlock_unlock(toku_pthread_rwlock_t &rwlock) { |
| 361 | if (rwlock.psi_rwlock) |
| 362 | PSI_RWLOCK_CALL(unlock_rwlock)(rwlock.psi_rwlock); |
| 363 | } |
| 364 | |
| 365 | #endif // MYSQL_TOKUDB_ENGINE |
| 366 | |