summaryrefslogtreecommitdiff
path: root/innobase
diff options
context:
space:
mode:
Diffstat (limited to 'innobase')
-rw-r--r--innobase/include/que0que.h6
-rw-r--r--innobase/include/srv0srv.h5
-rw-r--r--innobase/include/sync0rw.h8
-rw-r--r--innobase/include/sync0sync.h24
-rw-r--r--innobase/include/sync0sync.ic6
-rw-r--r--innobase/include/univ.i1
-rw-r--r--innobase/que/que0que.c1
-rw-r--r--innobase/row/row0mysql.c7
-rw-r--r--innobase/row/row0sel.c4
-rw-r--r--innobase/srv/srv0srv.c50
-rw-r--r--innobase/sync/sync0rw.c7
-rw-r--r--innobase/sync/sync0sync.c260
-rw-r--r--innobase/ut/ut0ut.c15
13 files changed, 273 insertions, 121 deletions
diff --git a/innobase/include/que0que.h b/innobase/include/que0que.h
index e1874edcaf2..d45ae032ddb 100644
--- a/innobase/include/que0que.h
+++ b/innobase/include/que0que.h
@@ -359,6 +359,7 @@ struct que_thr_struct{
the control came */
ulint resource; /* resource usage of the query thread
thus far */
+ ulint lock_state; /* lock state of thread (table or row) */
};
#define QUE_THR_MAGIC_N 8476583
@@ -482,6 +483,11 @@ struct que_fork_struct{
#define QUE_THR_SUSPENDED 7
#define QUE_THR_ERROR 8
+/* Query thread lock states */
+#define QUE_THR_LOCK_NOLOCK 0
+#define QUE_THR_LOCK_ROW 1
+#define QUE_THR_LOCK_TABLE 2
+
/* From where the cursor position is counted */
#define QUE_CUR_NOT_DEFINED 1
#define QUE_CUR_START 2
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index 84b7d14ca00..5f752717fcc 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -525,6 +525,11 @@ struct export_var_struct{
ulint innodb_pages_created;
ulint innodb_pages_read;
ulint innodb_pages_written;
+ ulint innodb_row_lock_waits;
+ ulint innodb_row_lock_current_waits;
+ ib_longlong innodb_row_lock_time;
+ ulint innodb_row_lock_time_avg;
+ ulint innodb_row_lock_time_max;
ulint innodb_rows_read;
ulint innodb_rows_inserted;
ulint innodb_rows_updated;
diff --git a/innobase/include/sync0rw.h b/innobase/include/sync0rw.h
index 9a988a03e92..6e3a4cf4dc7 100644
--- a/innobase/include/sync0rw.h
+++ b/innobase/include/sync0rw.h
@@ -61,8 +61,9 @@ Creates, or rather, initializes an rw-lock object in a specified memory
location (which must be appropriately aligned). The rw-lock is initialized
to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free
is necessary only if the memory block containing it is freed. */
-
-#define rw_lock_create(L) rw_lock_create_func((L), __FILE__, __LINE__)
+#define rw_lock_create(L) rw_lock_create_func(\
+ (L), __FILE__, __LINE__, __STRING(L))
+
/*=====================*/
/**********************************************************************
Creates, or rather, initializes an rw-lock object in a specified memory
@@ -75,7 +76,8 @@ rw_lock_create_func(
/*================*/
rw_lock_t* lock, /* in: pointer to memory */
const char* cfile_name, /* in: file name where created */
- ulint cline); /* in: file line where created */
+ ulint cline, /* in: file line where created */
+ const char* cmutex_name); /* in: mutex name */
/**********************************************************************
Calling this function is obligatory only if the memory buffer containing
the rw-lock is freed. Removes an rw-lock object from the global list. The
diff --git a/innobase/include/sync0sync.h b/innobase/include/sync0sync.h
index 8e0ec715b12..98d61c129b1 100644
--- a/innobase/include/sync0sync.h
+++ b/innobase/include/sync0sync.h
@@ -17,6 +17,8 @@ Created 9/5/1995 Heikki Tuuri
#include "os0sync.h"
#include "sync0arr.h"
+extern my_bool timed_mutexes;
+
/**********************************************************************
Initializes the synchronization data structures. */
@@ -35,8 +37,7 @@ location (which must be appropriately aligned). The mutex is initialized
in the reset state. Explicit freeing of the mutex with mutex_free is
necessary only if the memory block containing it is freed. */
-
-#define mutex_create(M) mutex_create_func((M), __FILE__, __LINE__)
+#define mutex_create(M) mutex_create_func((M), __FILE__, __LINE__, __STRING(M))
/*===================*/
/**********************************************************************
Creates, or rather, initializes a mutex object in a specified memory
@@ -49,7 +50,8 @@ mutex_create_func(
/*==============*/
mutex_t* mutex, /* in: pointer to memory */
const char* cfile_name, /* in: file name where created */
- ulint cline); /* in: file line where created */
+ ulint cline, /* in: file line where created */
+ const char* cmutex_name); /* in: mutex name */
/**********************************************************************
Calling this function is obligatory only if the memory buffer containing
the mutex is freed. Removes a mutex object from the mutex list. The mutex
@@ -471,6 +473,15 @@ struct mutex_struct {
const char* cfile_name;/* File name where mutex created */
ulint cline; /* Line where created */
ulint magic_n;
+ ulong count_using; /* count of times mutex used */
+ ulong count_spin_loop; /* count of spin loops */
+ ulong count_spin_rounds; /* count of spin rounds */
+ ulong count_os_wait; /* count of os_wait */
+ ulong count_os_yield; /* count of os_wait */
+ ulonglong lspent_time; /* mutex os_wait timer msec */
+ ulonglong lmax_spent_time; /* mutex os_wait timer msec */
+ const char* cmutex_name;/* mutex name */
+ ulint mutex_type;/* 0 - usual mutex 1 - rw_lock mutex */
};
#define MUTEX_MAGIC_N (ulint)979585
@@ -504,6 +515,13 @@ extern ibool sync_order_checks_on;
/* This variable is set to TRUE when sync_init is called */
extern ibool sync_initialized;
+/* Global list of database mutexes (not OS mutexes) created. */
+UT_LIST_BASE_NODE_T(mutex_t) mutex_list;
+
+/* Mutex protecting the mutex_list variable */
+mutex_t mutex_list_mutex;
+
+
#ifndef UNIV_NONINL
#include "sync0sync.ic"
#endif
diff --git a/innobase/include/sync0sync.ic b/innobase/include/sync0sync.ic
index aaf5e1fd9e9..1731b47db58 100644
--- a/innobase/include/sync0sync.ic
+++ b/innobase/include/sync0sync.ic
@@ -249,8 +249,11 @@ mutex_enter_func(
/* Note that we do not peek at the value of lock_word before trying
the atomic test_and_set; we could peek, and possibly save time. */
+
+ mutex->count_using++;
- if (!mutex_test_and_set(mutex)) {
+ if (!mutex_test_and_set(mutex))
+ {
#ifdef UNIV_SYNC_DEBUG
mutex_set_debug_info(mutex, file_name, line);
#endif
@@ -258,4 +261,5 @@ mutex_enter_func(
}
mutex_spin_wait(mutex, file_name, line);
+
}
diff --git a/innobase/include/univ.i b/innobase/include/univ.i
index be71d4211b3..80024f71992 100644
--- a/innobase/include/univ.i
+++ b/innobase/include/univ.i
@@ -88,6 +88,7 @@ memory is read outside the allocated blocks. */
#define UNIV_SEARCH_DEBUG
#define UNIV_SYNC_PERF_STAT
#define UNIV_SEARCH_PERF_STAT
+#define UNIV_SRV_PRINT_LATCH_WAITS;
*/
#define UNIV_LIGHT_MEM_DEBUG
diff --git a/innobase/que/que0que.c b/innobase/que/que0que.c
index 22878dec27f..a0a6adf9b83 100644
--- a/innobase/que/que0que.c
+++ b/innobase/que/que0que.c
@@ -163,6 +163,7 @@ que_thr_create(
thr->run_node = NULL;
thr->resource = 0;
+ thr->lock_state = QUE_THR_LOCK_NOLOCK;
UT_LIST_ADD_LAST(thrs, parent->thrs, thr);
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index e959c28f6bb..0a2e9e5eaad 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -937,9 +937,10 @@ run_again:
if (err != DB_SUCCESS) {
que_thr_stop_for_mysql(thr);
-
+ thr->lock_state= QUE_THR_LOCK_ROW;
was_lock_wait = row_mysql_handle_errors(&err, trx, thr,
&savept);
+ thr->lock_state= QUE_THR_LOCK_NOLOCK;
if (was_lock_wait) {
goto run_again;
}
@@ -1171,9 +1172,11 @@ run_again:
return((int) err);
}
-
+
+ thr->lock_state= QUE_THR_LOCK_ROW;
was_lock_wait = row_mysql_handle_errors(&err, trx, thr,
&savept);
+ thr->lock_state= QUE_THR_LOCK_NOLOCK;;
if (was_lock_wait) {
goto run_again;
}
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index a3d844d1dac..c079557ca8b 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -3791,8 +3791,10 @@ lock_wait_or_error:
que_thr_stop_for_mysql(thr);
+ thr->lock_state= QUE_THR_LOCK_ROW;
was_lock_wait = row_mysql_handle_errors(&err, trx, thr, NULL);
-
+ thr->lock_state= QUE_THR_LOCK_NOLOCK;
+
if (was_lock_wait) {
mtr_start(&mtr);
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index 83d4fb4d39d..aa2a7fa9169 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -346,6 +346,12 @@ static ulint srv_n_rows_updated_old = 0;
static ulint srv_n_rows_deleted_old = 0;
static ulint srv_n_rows_read_old = 0;
+ulint srv_n_lock_wait_count= 0;
+ulint srv_n_lock_wait_current_count= 0;
+ib_longlong srv_n_lock_wait_time= 0;
+ulint srv_n_lock_max_wait_time= 0;
+
+
/*
Set the following to 0 if you want InnoDB to write messages on
stderr on startup/shutdown
@@ -1378,7 +1384,11 @@ srv_suspend_mysql_thread(
trx_t* trx;
ibool had_dict_lock = FALSE;
ibool was_declared_inside_innodb = FALSE;
-
+ ib_longlong start_time, finish_time;
+ ulint diff_time;
+ ulint sec;
+ ulint ms;
+
#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
@@ -1420,7 +1430,15 @@ srv_suspend_mysql_thread(
os_event_reset(event);
slot->suspend_time = ut_time();
+ if (thr->lock_state == QUE_THR_LOCK_ROW)
+ {
+ srv_n_lock_wait_count++;
+ srv_n_lock_wait_current_count++;
+
+ ut_usectime(&sec, &ms);
+ start_time= (ib_longlong)sec * 1000000 + ms;
+ }
/* Wake the lock timeout monitor thread, if it is suspended */
os_event_set(srv_lock_timeout_thread_event);
@@ -1471,7 +1489,22 @@ srv_suspend_mysql_thread(
slot->in_use = FALSE;
wait_time = ut_difftime(ut_time(), slot->suspend_time);
-
+
+ if (thr->lock_state == QUE_THR_LOCK_ROW)
+ {
+ ut_usectime(&sec, &ms);
+ finish_time= (ib_longlong)sec * 1000000 + ms;
+
+ diff_time= finish_time-start_time;
+
+ srv_n_lock_wait_current_count--;
+ srv_n_lock_wait_time= srv_n_lock_wait_time + diff_time;
+ if (diff_time > srv_n_lock_max_wait_time)
+ {
+ srv_n_lock_max_wait_time= diff_time;
+ }
+ }
+
if (trx->was_chosen_as_deadlock_victim) {
trx->error_state = DB_DEADLOCK;
@@ -1689,15 +1722,14 @@ srv_printf_innodb_monitor(
(srv_n_rows_read - srv_n_rows_read_old)
/ time_elapsed);
- srv_n_rows_inserted_old = srv_n_rows_inserted;
+ srv_n_rows_inserted_old = srv_n_rows_inserted;
srv_n_rows_updated_old = srv_n_rows_updated;
srv_n_rows_deleted_old = srv_n_rows_deleted;
srv_n_rows_read_old = srv_n_rows_read;
- fputs("----------------------------\n"
+ fputs("----------------------------\n"
"END OF INNODB MONITOR OUTPUT\n"
"============================\n", file);
-
mutex_exit(&srv_innodb_monitor_mutex);
fflush(file);
}
@@ -1746,11 +1778,19 @@ srv_export_innodb_status(void)
export_vars.innodb_pages_created= buf_pool->n_pages_created;
export_vars.innodb_pages_read= buf_pool->n_pages_read;
export_vars.innodb_pages_written= buf_pool->n_pages_written;
+ export_vars.innodb_row_lock_waits= srv_n_lock_wait_count;
+ export_vars.innodb_row_lock_current_waits= srv_n_lock_wait_current_count;
+ export_vars.innodb_row_lock_time= srv_n_lock_wait_time / 10000;
+ export_vars.innodb_row_lock_time_avg=
+ (srv_n_lock_wait_count > 0) ?
+ (srv_n_lock_wait_time / 10000 / srv_n_lock_wait_count) : 0;
+ export_vars.innodb_row_lock_time_max= srv_n_lock_max_wait_time / 10000;
export_vars.innodb_rows_read= srv_n_rows_read;
export_vars.innodb_rows_inserted= srv_n_rows_inserted;
export_vars.innodb_rows_updated= srv_n_rows_updated;
export_vars.innodb_rows_deleted= srv_n_rows_deleted;
mutex_exit(&srv_innodb_monitor_mutex);
+
}
/*************************************************************************
diff --git a/innobase/sync/sync0rw.c b/innobase/sync/sync0rw.c
index 77757685208..e57974a375b 100644
--- a/innobase/sync/sync0rw.c
+++ b/innobase/sync/sync0rw.c
@@ -90,7 +90,8 @@ rw_lock_create_func(
/*================*/
rw_lock_t* lock, /* in: pointer to memory */
const char* cfile_name, /* in: file name where created */
- ulint cline) /* in: file line where created */
+ ulint cline, /* in: file line where created */
+ const char* cmutex_name) /* in: mutex name */
{
/* If this is the very first time a synchronization
object is created, then the following call initializes
@@ -101,7 +102,9 @@ rw_lock_create_func(
lock->mutex.cfile_name = cfile_name;
lock->mutex.cline = cline;
-
+ lock->mutex.cmutex_name = cmutex_name;
+ lock->mutex.mutex_type = 1;
+
rw_lock_set_waiters(lock, 0);
rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
lock->writer_count = 0;
diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c
index 86306e49cac..fb46c692830 100644
--- a/innobase/sync/sync0sync.c
+++ b/innobase/sync/sync0sync.c
@@ -129,11 +129,6 @@ sync_array_t* sync_primary_wait_array;
/* This variable is set to TRUE when sync_init is called */
ibool sync_initialized = FALSE;
-/* Global list of database mutexes (not OS mutexes) created. */
-UT_LIST_BASE_NODE_T(mutex_t) mutex_list;
-
-/* Mutex protecting the mutex_list variable */
-mutex_t mutex_list_mutex;
typedef struct sync_level_struct sync_level_t;
typedef struct sync_thread_struct sync_thread_t;
@@ -202,7 +197,8 @@ mutex_create_func(
/*==============*/
mutex_t* mutex, /* in: pointer to memory */
const char* cfile_name, /* in: file name where created */
- ulint cline) /* in: file line where created */
+ ulint cline, /* in: file line where created */
+ const char* cmutex_name) /* in: mutex name */
{
#if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER)
mutex_reset_lock_word(mutex);
@@ -219,6 +215,16 @@ mutex_create_func(
mutex->level = SYNC_LEVEL_NONE;
mutex->cfile_name = cfile_name;
mutex->cline = cline;
+ mutex->cmutex_name= cmutex_name;
+ mutex->count_using= 0;
+ mutex->mutex_type= 0;
+ mutex->lspent_time= 0;
+ mutex->lmax_spent_time= 0;
+ mutex->count_spin_loop= 0;
+ mutex->count_spin_rounds= 0;
+ mutex->count_os_wait= 0;
+ mutex->count_os_yield= 0;
+
/* Check that lock_word is aligned; this is important on Intel */
ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0);
@@ -355,135 +361,180 @@ for the mutex before suspending the thread. */
void
mutex_spin_wait(
/*============*/
- mutex_t* mutex, /* in: pointer to mutex */
- const char* file_name, /* in: file name where
- mutex requested */
- ulint line) /* in: line where requested */
+ mutex_t* mutex, /* in: pointer to mutex */
+ const char* file_name, /* in: file name where
+ mutex requested */
+ ulint line) /* in: line where requested */
{
- ulint index; /* index of the reserved wait cell */
- ulint i; /* spin round count */
-
- ut_ad(mutex);
+ ulint index; /* index of the reserved wait cell */
+ ulint i; /* spin round count */
+ ib_longlong lstart_time, lfinish_time; /* for timing os_wait */
+ ulint ltime_diff;
+ ulint sec;
+ ulint ms;
-mutex_loop:
+ uint timer_started = 0;
- i = 0;
+ ut_ad(mutex);
- /* Spin waiting for the lock word to become zero. Note that we do not
- have to assume that the read access to the lock word is atomic, as the
- actual locking is always committed with atomic test-and-set. In
- reality, however, all processors probably have an atomic read of a
- memory word. */
-
-spin_loop:
- mutex_spin_wait_count++;
+mutex_loop:
- while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS) {
+ i = 0;
- if (srv_spin_wait_delay) {
- ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
- }
-
- i++;
- }
+/* Spin waiting for the lock word to become zero. Note that we do not
+ have to assume that the read access to the lock word is atomic, as the
+ actual locking is always committed with atomic test-and-set. In
+ reality, however, all processors probably have an atomic read of a
+ memory word. */
- if (i == SYNC_SPIN_ROUNDS) {
- os_thread_yield();
- }
+spin_loop:
+ mutex_spin_wait_count++;
+ mutex->count_spin_loop++;
+
+ while (mutex_get_lock_word(mutex) != 0 && i < SYNC_SPIN_ROUNDS)
+ {
+ if (srv_spin_wait_delay)
+ {
+ ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
+ }
+
+ i++;
+ }
+
+ if (i == SYNC_SPIN_ROUNDS)
+ {
+ mutex->count_os_yield++;
+ if (timed_mutexes == 1 && timer_started==0)
+ {
+ ut_usectime(&sec, &ms);
+ lstart_time= (ib_longlong)sec * 1000000 + ms;
+ timer_started = 1;
+ }
+ os_thread_yield();
+ }
+
+#ifdef UNIV_SRV_PRINT_LATCH_WAITS
+ fprintf(stderr,
+ "Thread %lu spin wait mutex at %p cfile %s cline %lu rnds %lu\n",
+ (ulong) os_thread_pf(os_thread_get_curr_id()), mutex,
+ mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
+#endif
- if (srv_print_latch_waits) {
- fprintf(stderr,
- "Thread %lu spin wait mutex at %p cfile %s cline %lu rnds %lu\n",
- (ulong) os_thread_pf(os_thread_get_curr_id()), mutex,
- mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
- }
+ mutex_spin_round_count += i;
- mutex_spin_round_count += i;
+ mutex->count_spin_rounds += i;
- if (mutex_test_and_set(mutex) == 0) {
- /* Succeeded! */
+ if (mutex_test_and_set(mutex) == 0)
+ {
+ /* Succeeded! */
#ifdef UNIV_SYNC_DEBUG
- mutex_set_debug_info(mutex, file_name, line);
+ mutex_set_debug_info(mutex, file_name, line);
#endif
- return;
- }
+ goto finish_timing;
+ }
- /* We may end up with a situation where lock_word is
- 0 but the OS fast mutex is still reserved. On FreeBSD
- the OS does not seem to schedule a thread which is constantly
- calling pthread_mutex_trylock (in mutex_test_and_set
- implementation). Then we could end up spinning here indefinitely.
- The following 'i++' stops this infinite spin. */
+ /* We may end up with a situation where lock_word is
+ 0 but the OS fast mutex is still reserved. On FreeBSD
+ the OS does not seem to schedule a thread which is constantly
+ calling pthread_mutex_trylock (in mutex_test_and_set
+ implementation). Then we could end up spinning here indefinitely.
+ The following 'i++' stops this infinite spin. */
- i++;
-
- if (i < SYNC_SPIN_ROUNDS) {
+ i++;
- goto spin_loop;
- }
+ if (i < SYNC_SPIN_ROUNDS)
+ {
+ goto spin_loop;
+ }
- sync_array_reserve_cell(sync_primary_wait_array, mutex,
- SYNC_MUTEX,
- file_name, line,
- &index);
+ sync_array_reserve_cell(sync_primary_wait_array, mutex,
+ SYNC_MUTEX, file_name, line, &index);
- mutex_system_call_count++;
+ mutex_system_call_count++;
- /* The memory order of the array reservation and the change in the
- waiters field is important: when we suspend a thread, we first
- reserve the cell and then set waiters field to 1. When threads are
- released in mutex_exit, the waiters field is first set to zero and
- then the event is set to the signaled state. */
-
- mutex_set_waiters(mutex, 1);
+ /* The memory order of the array reservation and the change in the
+ waiters field is important: when we suspend a thread, we first
+ reserve the cell and then set waiters field to 1. When threads are
+ released in mutex_exit, the waiters field is first set to zero and
+ then the event is set to the signaled state. */
+
+ mutex_set_waiters(mutex, 1);
- /* Try to reserve still a few times */
- for (i = 0; i < 4; i++) {
- if (mutex_test_and_set(mutex) == 0) {
+ /* Try to reserve still a few times */
+ for (i = 0; i < 4; i++)
+ {
+ if (mutex_test_and_set(mutex) == 0)
+ {
+ /* Succeeded! Free the reserved wait cell */
- /* Succeeded! Free the reserved wait cell */
+ sync_array_free_cell(sync_primary_wait_array, index);
- sync_array_free_cell(sync_primary_wait_array, index);
-
#ifdef UNIV_SYNC_DEBUG
- mutex_set_debug_info(mutex, file_name, line);
+ mutex_set_debug_info(mutex, file_name, line);
#endif
- if (srv_print_latch_waits) {
- fprintf(stderr,
- "Thread %lu spin wait succeeds at 2:"
- " mutex at %p\n",
- (ulong) os_thread_pf(os_thread_get_curr_id()),
- mutex);
- }
-
- return;
+#ifdef UNIV_SRV_PRINT_LATCH_WAITS
+ fprintf(stderr, "Thread %lu spin wait succeeds at 2:"
+ " mutex at %p\n",
+ (ulong) os_thread_pf(os_thread_get_curr_id()),
+ mutex);
+#endif
- /* Note that in this case we leave the waiters field
- set to 1. We cannot reset it to zero, as we do not know
- if there are other waiters. */
- }
- }
+ goto finish_timing;
- /* Now we know that there has been some thread holding the mutex
- after the change in the wait array and the waiters field was made.
- Now there is no risk of infinite wait on the event. */
+ /* Note that in this case we leave the waiters field
+ set to 1. We cannot reset it to zero, as we do not know
+ if there are other waiters. */
+ }
+ }
- if (srv_print_latch_waits) {
- fprintf(stderr,
- "Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n",
- (ulong) os_thread_pf(os_thread_get_curr_id()), mutex,
- mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
- }
-
- mutex_system_call_count++;
- mutex_os_wait_count++;
+ /* Now we know that there has been some thread holding the mutex
+ after the change in the wait array and the waiters field was made.
+Now there is no risk of infinite wait on the event. */
- sync_array_wait_event(sync_primary_wait_array, index);
+#ifdef UNIV_SRV_PRINT_LATCH_WAITS
+ fprintf(stderr,
+ "Thread %lu OS wait mutex at %p cfile %s cline %lu rnds %lu\n",
+ (ulong) os_thread_pf(os_thread_get_curr_id()), mutex,
+ mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
+#endif
- goto mutex_loop;
+ mutex_system_call_count++;
+ mutex_os_wait_count++;
+
+ mutex->count_os_wait++;
+
+ /*
+ !!!!! Sometimes os_wait can be called without os_thread_yield
+ */
+
+ if (timed_mutexes == 1 && timer_started==0)
+ {
+ ut_usectime(&sec, &ms);
+ lstart_time= (ib_longlong)sec * 1000000 + ms;
+ timer_started = 1;
+ }
+
+
+ sync_array_wait_event(sync_primary_wait_array, index);
+ goto mutex_loop;
+
+finish_timing:
+ if (timed_mutexes == 1 && timer_started==1)
+ {
+ ut_usectime(&sec, &ms);
+ lfinish_time= (ib_longlong)sec * 1000000 + ms;
+
+ ltime_diff= lfinish_time - lstart_time;
+ mutex->lspent_time += ltime_diff;
+ if (mutex->lmax_spent_time < ltime_diff)
+ {
+ mutex->lmax_spent_time= ltime_diff;
+ }
+ }
+ return;
}
/**********************************************************************
@@ -555,6 +606,7 @@ mutex_set_level(
mutex->level = level;
}
+
#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
Checks that the current thread owns the mutex. Works only in the debug
diff --git a/innobase/ut/ut0ut.c b/innobase/ut/ut0ut.c
index 732380bcb1f..21c2833b6d6 100644
--- a/innobase/ut/ut0ut.c
+++ b/innobase/ut/ut0ut.c
@@ -74,6 +74,21 @@ ut_time(void)
}
/**************************************************************
+Returns system time. We do not specify the format of the time returned:
+the only way to manipulate it is to use the function ut_difftime. */
+
+void
+ut_usectime(ulint* sec, ulint* ms)
+/*=========*/
+{
+ struct timeval tv;
+ gettimeofday(&tv,NULL);
+ *sec = (ulint) tv.tv_sec;
+ *ms = (ulint) tv.tv_usec;
+ return;
+}
+
+/**************************************************************
Returns the difference of two times in seconds. */
double