diff options
Diffstat (limited to 'storage/xtradb/sync/sync0arr.c')
-rw-r--r-- | storage/xtradb/sync/sync0arr.c | 177 |
1 files changed, 122 insertions, 55 deletions
diff --git a/storage/xtradb/sync/sync0arr.c b/storage/xtradb/sync/sync0arr.c index fb5829fb732..7f27fd926eb 100644 --- a/storage/xtradb/sync/sync0arr.c +++ b/storage/xtradb/sync/sync0arr.c @@ -2,6 +2,7 @@ Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. +Copyright (c) 2013, 2014, SkySQL Ab. All Rights Reserved. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -466,11 +467,13 @@ static void sync_array_cell_print( /*==================*/ - FILE* file, /*!< in: file where to print */ - sync_cell_t* cell) /*!< in: sync cell */ + FILE* file, /*!< in: file where to print */ + sync_cell_t* cell, /*!< in: sync cell */ + os_thread_id_t* reserver) /*!< out: write reserver or + 0 */ { - mutex_t* mutex; - rw_lock_t* rwlock; + mutex_t* mutex = NULL; + rw_lock_t* rwlock = NULL; ulint type; ulint writer; @@ -483,32 +486,34 @@ sync_array_cell_print( innobase_basename(cell->file), (ulong) cell->line, difftime(time(NULL), cell->reservation_time)); - /* If stacktrace feature is enabled we will send a SIGUSR2 - signal to thread waiting for the semaphore. Signal handler - will then dump the current stack to error log. */ - if (srv_use_stacktrace) { -#ifdef __linux__ - pthread_kill(cell->thread, SIGUSR2); -#endif - } - if (type == SYNC_MUTEX) { /* We use old_wait_mutex in case the cell has already been freed meanwhile */ mutex = cell->old_wait_mutex; - fprintf(file, - "Mutex at %p '%s', lock var %lu\n" + if (mutex) { + fprintf(file, + "Mutex at %p '%s', lock var %lu\n" #ifdef UNIV_SYNC_DEBUG - "Last time reserved in file %s line %lu, " + "Last time reserved in file %s line %lu, " #endif /* UNIV_SYNC_DEBUG */ - "waiters flag %lu\n", - (void*) mutex, mutex->cmutex_name, - (ulong) mutex->lock_word, + "waiters flag %lu\n", + (void*) mutex, mutex->cmutex_name, + (ulong) mutex->lock_word, #ifdef UNIV_SYNC_DEBUG - mutex->file_name, (ulong) mutex->line, + mutex->file_name, (ulong) mutex->line, #endif /* UNIV_SYNC_DEBUG */ - (ulong) mutex->waiters); + (ulong) mutex->waiters); + } + + /* If stacktrace feature is enabled we will send a SIGUSR2 + signal to thread waiting for the semaphore. Signal handler + will then dump the current stack to error log. */ + if (srv_use_stacktrace && cell && cell->thread) { +#ifdef __linux__ + pthread_kill(cell->thread, SIGUSR2); +#endif + } } else if (type == RW_LOCK_EX || type == RW_LOCK_WAIT_EX @@ -520,40 +525,47 @@ sync_array_cell_print( rwlock = cell->old_wait_rw_lock; - fprintf(file, - " RW-latch at %p '%s'\n", - (void*) rwlock, rwlock->lock_name); - writer = rw_lock_get_writer(rwlock); - if (writer != RW_LOCK_NOT_LOCKED) { + if (rwlock) { fprintf(file, - "a writer (thread id %lu) has" - " reserved it in mode %s", - (ulong) os_thread_pf(rwlock->writer_thread), - writer == RW_LOCK_EX - ? " exclusive\n" - : " wait exclusive\n"); - } + " RW-latch at %p '%s'\n", + (void*) rwlock, rwlock->lock_name); - fprintf(file, - "number of readers %lu, waiters flag %lu, " - "lock_word: %lx\n" - "Last time read locked in file %s line %lu\n" - "Last time write locked in file %s line %lu\n", - (ulong) rw_lock_get_reader_count(rwlock), - (ulong) rwlock->waiters, - rwlock->lock_word, - innobase_basename(rwlock->last_s_file_name), - (ulong) rwlock->last_s_line, - rwlock->last_x_file_name, - (ulong) rwlock->last_x_line); + writer = rw_lock_get_writer(rwlock); - /* If stacktrace feature is enabled we will send a SIGUSR2 - signal to thread that has locked RW-latch with write mode. - Signal handler will then dump the current stack to error log. */ - if (writer != RW_LOCK_NOT_LOCKED && srv_use_stacktrace) { + if (writer && writer != RW_LOCK_NOT_LOCKED) { + fprintf(file, + "a writer (thread id %lu) has" + " reserved it in mode %s", + (ulong) os_thread_pf(rwlock->writer_thread), + writer == RW_LOCK_EX + ? " exclusive\n" + : " wait exclusive\n"); + + *reserver = rwlock->writer_thread; + } + + fprintf(file, + "number of readers %lu, waiters flag %lu, " + "lock_word: %lx\n" + "Last time read locked in file %s line %lu\n" + "Last time write locked in file %s line %lu\n", + (ulong) rw_lock_get_reader_count(rwlock), + (ulong) rwlock->waiters, + rwlock->lock_word, + innobase_basename(rwlock->last_s_file_name), + (ulong) rwlock->last_s_line, + rwlock->last_x_file_name, + (ulong) rwlock->last_x_line); + + /* If stacktrace feature is enabled we will send a SIGUSR2 + signal to thread that has locked RW-latch with write mode. + Signal handler will then dump the current stack to error log. */ + if (writer != RW_LOCK_NOT_LOCKED && srv_use_stacktrace && + rwlock && rwlock->writer_thread) { #ifdef __linux__ - pthread_kill(rwlock->writer_thread, SIGUSR2); + pthread_kill(rwlock->writer_thread, SIGUSR2); #endif + } } } else { @@ -565,7 +577,6 @@ sync_array_cell_print( } } -#ifdef UNIV_SYNC_DEBUG /******************************************************************//** Looks for a cell with the given thread id. @return pointer to cell or NULL if not found */ @@ -593,6 +604,8 @@ sync_array_find_thread( return(NULL); /* Not found */ } +#ifdef UNIV_SYNC_DEBUG + /******************************************************************//** Recursion step for deadlock detection. @return TRUE if deadlock detected */ @@ -964,6 +977,7 @@ sync_array_print_long_waits( double diff; void* wait_object; + os_thread_id_t reserver=0; cell = sync_array_get_nth_cell(sync_primary_wait_array, i); @@ -979,7 +993,7 @@ sync_array_print_long_waits( if (diff > SYNC_ARRAY_TIMEOUT) { fputs("InnoDB: Warning: a long semaphore wait:\n", stderr); - sync_array_cell_print(stderr, cell); + sync_array_cell_print(stderr, cell, &reserver); noticed = TRUE; } @@ -994,6 +1008,58 @@ sync_array_print_long_waits( } } + /* We found a long semaphore wait, wait all threads that are + waiting for a semaphore. */ + if (noticed) { + for (i = 0; i < sync_primary_wait_array->n_cells; i++) { + void* wait_object; + os_thread_id_t reserver=ULINT_UNDEFINED; + ulint loop=0; + + cell = sync_array_get_nth_cell(sync_primary_wait_array, i); + + wait_object = cell->wait_object; + + if (wait_object == NULL || !cell->waiting) { + + continue; + } + + fputs("InnoDB: Warning: semaphore wait:\n", + stderr); + sync_array_cell_print(stderr, cell, &reserver); + noticed = TRUE; + + /* Try to output cell information for writer recursive way */ + while (reserver != ULINT_UNDEFINED) { + sync_cell_t* reserver_wait; + + reserver_wait = sync_array_find_thread(sync_primary_wait_array, reserver); + + if (reserver_wait && + reserver_wait->wait_object != NULL && + reserver_wait->waiting) { + fputs("InnoDB: Warning: Writer thread is waiting this semaphore:\n", + stderr); + reserver = ULINT_UNDEFINED; + sync_array_cell_print(stderr, reserver_wait, &reserver); + loop++; + + if (reserver_wait->thread == reserver) { + reserver = ULINT_UNDEFINED; + } + } else { + reserver = ULINT_UNDEFINED; + } + /* This is protection against loop */ + if (loop > 100) { + fputs("InnoDB: Warning: Too many waiting threads.\n", stderr); + break; + } + } + } + } + sync_array_exit(sync_primary_wait_array); if (noticed) { @@ -1042,6 +1108,7 @@ sync_array_output_info( sync_cell_t* cell; ulint count; ulint i; + os_thread_id_t r; fprintf(file, "OS WAIT ARRAY INFO: reservation count %ld, signal count %ld\n", @@ -1053,9 +1120,9 @@ sync_array_output_info( cell = sync_array_get_nth_cell(arr, i); - if (cell->wait_object != NULL) { - count++; - sync_array_cell_print(file, cell); + if (cell->wait_object != NULL) { + count++; + sync_array_cell_print(file, cell, &r); } i++; |