Below is the list of changes that have just been committed into a local
5.1 repository of tsmith. When tsmith does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-01-17 17:18:10-07:00, tsmith@stripped +14 -0
Merge siva.hindu.god:/home/tsmith/m/bk/mrg-jan17/50
into siva.hindu.god:/home/tsmith/m/bk/mrg-jan17/51
MERGE: 1.1810.2368.66
configure.in@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +0 -0
Auto merged
MERGE: 1.245.1.175
storage/innobase/buf/buf0buf.c@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +0 -2
Auto merged
MERGE: 1.45.15.2
storage/innobase/buf/buf0buf.c@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +0 -0
Merge rename: innobase/buf/buf0buf.c -> storage/innobase/buf/buf0buf.c
storage/innobase/buf/buf0flu.c@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +3 -2
Auto merged
MERGE: 1.28.4.2
storage/innobase/buf/buf0flu.c@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +0 -0
Merge rename: innobase/buf/buf0flu.c -> storage/innobase/buf/buf0flu.c
storage/innobase/buf/buf0lru.c@stripped, 2007-01-17 17:18:03-07:00, tsmith@stripped +0 -0
Auto merged
MERGE: 1.24.4.2
storage/innobase/buf/buf0lru.c@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +0 -0
Merge rename: innobase/buf/buf0lru.c -> storage/innobase/buf/buf0lru.c
storage/innobase/include/buf0buf.h@stripped, 2007-01-17 17:18:03-07:00, tsmith@stripped +0 -0
Auto merged
MERGE: 1.28.5.2
storage/innobase/include/buf0buf.h@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +0 -0
Merge rename: innobase/include/buf0buf.h -> storage/innobase/include/buf0buf.h
storage/innobase/include/buf0buf.ic@stripped, 2007-01-17 17:18:03-07:00, tsmith@stripped +0 -4
Auto merged
MERGE: 1.17.8.2
storage/innobase/include/buf0buf.ic@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +0 -0
Merge rename: innobase/include/buf0buf.ic -> storage/innobase/include/buf0buf.ic
storage/innobase/include/sync0arr.h@stripped, 2007-01-17 17:18:03-07:00, tsmith@stripped +0 -0
Auto merged
MERGE: 1.7.3.2
storage/innobase/include/sync0arr.h@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +0 -0
Merge rename: innobase/include/sync0arr.h -> storage/innobase/include/sync0arr.h
storage/innobase/include/sync0rw.h@stripped, 2007-01-17 17:18:03-07:00, tsmith@stripped +0 -0
Auto merged
MERGE: 1.11.3.2
storage/innobase/include/sync0rw.h@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +0 -0
Merge rename: innobase/include/sync0rw.h -> storage/innobase/include/sync0rw.h
storage/innobase/include/sync0rw.ic@stripped, 2007-01-17 17:18:03-07:00, tsmith@stripped +0 -0
Auto merged
MERGE: 1.9.5.2
storage/innobase/include/sync0rw.ic@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +0 -0
Merge rename: innobase/include/sync0rw.ic -> storage/innobase/include/sync0rw.ic
storage/innobase/include/sync0sync.h@stripped, 2007-01-17 17:18:03-07:00, tsmith@stripped +0 -0
Auto merged
MERGE: 1.22.4.2
storage/innobase/include/sync0sync.h@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +0 -0
Merge rename: innobase/include/sync0sync.h -> storage/innobase/include/sync0sync.h
storage/innobase/os/os0sync.c@stripped, 2007-01-17 17:18:03-07:00, tsmith@stripped +0 -0
Auto merged
MERGE: 1.24.6.2
storage/innobase/os/os0sync.c@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +0 -0
Merge rename: innobase/os/os0sync.c -> storage/innobase/os/os0sync.c
storage/innobase/sync/sync0arr.c@stripped, 2007-01-17 17:18:03-07:00, tsmith@stripped +0 -0
Auto merged
MERGE: 1.20.3.2
storage/innobase/sync/sync0arr.c@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +0 -0
Merge rename: innobase/sync/sync0arr.c -> storage/innobase/sync/sync0arr.c
storage/innobase/sync/sync0rw.c@stripped, 2007-01-17 17:18:03-07:00, tsmith@stripped +0 -0
Auto merged
MERGE: 1.19.3.2
storage/innobase/sync/sync0rw.c@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +0 -0
Merge rename: innobase/sync/sync0rw.c -> storage/innobase/sync/sync0rw.c
storage/innobase/sync/sync0sync.c@stripped, 2007-01-17 17:18:03-07:00, tsmith@stripped +0 -0
Auto merged
MERGE: 1.34.5.2
storage/innobase/sync/sync0sync.c@stripped, 2007-01-17 17:18:02-07:00, tsmith@stripped +0 -0
Merge rename: innobase/sync/sync0sync.c -> storage/innobase/sync/sync0sync.c
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: tsmith
# Host: siva.hindu.god
# Root: /home/tsmith/m/bk/mrg-jan17/51/RESYNC
--- 1.45.15.1/innobase/buf/buf0buf.c 2007-01-17 16:44:04 -07:00
+++ 1.68/storage/innobase/buf/buf0buf.c 2007-01-17 17:18:02 -07:00
@@ -1,14 +1,14 @@
/* Innobase relational database engine; Copyright (C) 2001 Innobase Oy
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License 2
as published by the Free Software Foundation in June 1991.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License 2
along with this program (in file COPYING); if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
@@ -42,7 +42,7 @@
IMPLEMENTATION OF THE BUFFER POOL
=================================
-Performance improvement:
+Performance improvement:
------------------------
Thread scheduling in NT may be so slow that the OS wait mechanism should
not be used even in waiting for disk reads to complete.
@@ -160,8 +160,8 @@
releases the X-lock on the frame and resets the io_fix field
when the io operation completes.
-A thread may request the above operation using the buf_page_get-
-function. It may then continue to request a lock on the frame.
+A thread may request the above operation using the function
+buf_page_get(). It may then continue to request a lock on the frame.
The lock is granted when the io-handler releases the x-lock.
Read-ahead
@@ -242,33 +242,33 @@
ulint
buf_calc_page_new_checksum(
/*=======================*/
- /* out: checksum */
- byte* page) /* in: buffer page */
+ /* out: checksum */
+ byte* page) /* in: buffer page */
{
- ulint checksum;
+ ulint checksum;
- /* Since the field FIL_PAGE_FILE_FLUSH_LSN, and in versions <= 4.1.x
- ..._ARCH_LOG_NO, are written outside the buffer pool to the first
- pages of data files, we have to skip them in the page checksum
- calculation.
+ /* Since the field FIL_PAGE_FILE_FLUSH_LSN, and in versions <= 4.1.x
+ ..._ARCH_LOG_NO, are written outside the buffer pool to the first
+ pages of data files, we have to skip them in the page checksum
+ calculation.
We must also skip the field FIL_PAGE_SPACE_OR_CHKSUM where the
checksum is stored, and also the last 8 bytes of page because
there we store the old formula checksum. */
-
- checksum = ut_fold_binary(page + FIL_PAGE_OFFSET,
- FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
- + ut_fold_binary(page + FIL_PAGE_DATA,
- UNIV_PAGE_SIZE - FIL_PAGE_DATA
- - FIL_PAGE_END_LSN_OLD_CHKSUM);
- checksum = checksum & 0xFFFFFFFFUL;
- return(checksum);
+ checksum = ut_fold_binary(page + FIL_PAGE_OFFSET,
+ FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
+ + ut_fold_binary(page + FIL_PAGE_DATA,
+ UNIV_PAGE_SIZE - FIL_PAGE_DATA
+ - FIL_PAGE_END_LSN_OLD_CHKSUM);
+ checksum = checksum & 0xFFFFFFFFUL;
+
+ return(checksum);
}
/************************************************************************
In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only
looked at the first few bytes of the page. This calculates that old
-checksum.
+checksum.
NOTE: we must first store the new formula checksum to
FIL_PAGE_SPACE_OR_CHKSUM before calculating and storing this old checksum
because this takes that field as an input! */
@@ -276,16 +276,16 @@
ulint
buf_calc_page_old_checksum(
/*=======================*/
- /* out: checksum */
- byte* page) /* in: buffer page */
+ /* out: checksum */
+ byte* page) /* in: buffer page */
{
- ulint checksum;
-
- checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
+ ulint checksum;
+
+ checksum = ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
- checksum = checksum & 0xFFFFFFFFUL;
+ checksum = checksum & 0xFFFFFFFFUL;
- return(checksum);
+ return(checksum);
}
/************************************************************************
@@ -305,7 +305,7 @@
dulint current_lsn;
#endif
if (mach_read_from_4(read_buf + FIL_PAGE_LSN + 4)
- != mach_read_from_4(read_buf + UNIV_PAGE_SIZE
+ != mach_read_from_4(read_buf + UNIV_PAGE_SIZE
- FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
/* Stored log sequence numbers at the start and the end
@@ -318,63 +318,75 @@
if (recv_lsn_checks_on && log_peek_lsn(¤t_lsn)) {
if (ut_dulint_cmp(current_lsn,
mach_read_from_8(read_buf + FIL_PAGE_LSN))
- < 0) {
+ < 0) {
ut_print_timestamp(stderr);
fprintf(stderr,
-" InnoDB: Error: page %lu log sequence number %lu %lu\n"
-"InnoDB: is in the future! Current system log sequence number %lu %lu.\n"
-"InnoDB: Your database may be corrupt or you may have copied the InnoDB\n"
-"InnoDB: tablespace but not the InnoDB log files. See\n"
-"InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html\n"
-"InnoDB: for more information.\n",
- (ulong) mach_read_from_4(read_buf + FIL_PAGE_OFFSET),
- (ulong) ut_dulint_get_high(
- mach_read_from_8(read_buf + FIL_PAGE_LSN)),
- (ulong) ut_dulint_get_low(
- mach_read_from_8(read_buf + FIL_PAGE_LSN)),
- (ulong) ut_dulint_get_high(current_lsn),
- (ulong) ut_dulint_get_low(current_lsn));
+ " InnoDB: Error: page %lu log sequence number"
+ " %lu %lu\n"
+ "InnoDB: is in the future! Current system "
+ "log sequence number %lu %lu.\n"
+ "InnoDB: Your database may be corrupt or "
+ "you may have copied the InnoDB\n"
+ "InnoDB: tablespace but not the InnoDB "
+ "log files. See\n"
+ "InnoDB: http://dev.mysql.com/doc/refman/"
+ "5.1/en/forcing-recovery.html\n"
+ "InnoDB: for more information.\n",
+ (ulong) mach_read_from_4(read_buf
+ + FIL_PAGE_OFFSET),
+ (ulong) ut_dulint_get_high
+ (mach_read_from_8(read_buf + FIL_PAGE_LSN)),
+ (ulong) ut_dulint_get_low
+ (mach_read_from_8(read_buf + FIL_PAGE_LSN)),
+ (ulong) ut_dulint_get_high(current_lsn),
+ (ulong) ut_dulint_get_low(current_lsn));
}
}
#endif
-
- /* If we use checksums validation, make additional check before returning
- TRUE to ensure that the checksum is not equal to BUF_NO_CHECKSUM_MAGIC which
- might be stored by InnoDB with checksums disabled.
- Otherwise, skip checksum calculation and return FALSE */
-
- if (srv_use_checksums) {
- old_checksum = buf_calc_page_old_checksum(read_buf);
-
- old_checksum_field = mach_read_from_4(read_buf + UNIV_PAGE_SIZE
- - FIL_PAGE_END_LSN_OLD_CHKSUM);
-
- /* There are 2 valid formulas for old_checksum_field:
- 1. Very old versions of InnoDB only stored 8 byte lsn to the start
- and the end of the page.
- 2. Newer InnoDB versions store the old formula checksum there. */
-
- if (old_checksum_field != mach_read_from_4(read_buf + FIL_PAGE_LSN)
- && old_checksum_field != old_checksum
- && old_checksum_field != BUF_NO_CHECKSUM_MAGIC) {
-
- return(TRUE);
- }
-
- checksum = buf_calc_page_new_checksum(read_buf);
- checksum_field = mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM);
-
- /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
- (always equal to 0), to FIL_PAGE_SPACE_SPACE_OR_CHKSUM */
-
- if (checksum_field != 0 && checksum_field != checksum
- && checksum_field != BUF_NO_CHECKSUM_MAGIC) {
-
- return(TRUE);
- }
- }
-
+
+ /* If we use checksums validation, make additional check before
+ returning TRUE to ensure that the checksum is not equal to
+ BUF_NO_CHECKSUM_MAGIC which might be stored by InnoDB with checksums
+ disabled. Otherwise, skip checksum calculation and return FALSE */
+
+ if (srv_use_checksums) {
+ old_checksum = buf_calc_page_old_checksum(read_buf);
+
+ old_checksum_field = mach_read_from_4(
+ read_buf + UNIV_PAGE_SIZE
+ - FIL_PAGE_END_LSN_OLD_CHKSUM);
+
+ /* There are 2 valid formulas for old_checksum_field:
+
+ 1. Very old versions of InnoDB only stored 8 byte lsn to the
+ start and the end of the page.
+
+ 2. Newer InnoDB versions store the old formula checksum
+ there. */
+
+ if (old_checksum_field != mach_read_from_4(read_buf
+ + FIL_PAGE_LSN)
+ && old_checksum_field != old_checksum
+ && old_checksum_field != BUF_NO_CHECKSUM_MAGIC) {
+
+ return(TRUE);
+ }
+
+ checksum = buf_calc_page_new_checksum(read_buf);
+ checksum_field = mach_read_from_4(read_buf
+ + FIL_PAGE_SPACE_OR_CHKSUM);
+
+ /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
+ (always equal to 0), to FIL_PAGE_SPACE_SPACE_OR_CHKSUM */
+
+ if (checksum_field != 0 && checksum_field != checksum
+ && checksum_field != BUF_NO_CHECKSUM_MAGIC) {
+
+ return(TRUE);
+ }
+ }
+
return(FALSE);
}
@@ -396,65 +408,104 @@
ut_print_buf(stderr, read_buf, UNIV_PAGE_SIZE);
fputs("InnoDB: End of page dump\n", stderr);
- checksum = srv_use_checksums ?
- buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
- old_checksum = srv_use_checksums ?
- buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
+ checksum = srv_use_checksums
+ ? buf_calc_page_new_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
+ old_checksum = srv_use_checksums
+ ? buf_calc_page_old_checksum(read_buf) : BUF_NO_CHECKSUM_MAGIC;
ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Page checksum %lu, prior-to-4.0.14-form checksum %lu\n"
-"InnoDB: stored checksum %lu, prior-to-4.0.14-form stored checksum %lu\n",
- (ulong) checksum, (ulong) old_checksum,
- (ulong) mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM),
- (ulong) mach_read_from_4(read_buf + UNIV_PAGE_SIZE
- - FIL_PAGE_END_LSN_OLD_CHKSUM));
fprintf(stderr,
-"InnoDB: Page lsn %lu %lu, low 4 bytes of lsn at page end %lu\n"
-"InnoDB: Page number (if stored to page already) %lu,\n"
-"InnoDB: space id (if created with >= MySQL-4.1.1 and stored already) %lu\n",
+ " InnoDB: Page checksum %lu, prior-to-4.0.14-form"
+ " checksum %lu\n"
+ "InnoDB: stored checksum %lu, prior-to-4.0.14-form"
+ " stored checksum %lu\n"
+ "InnoDB: Page lsn %lu %lu, low 4 bytes of lsn"
+ " at page end %lu\n"
+ "InnoDB: Page number (if stored to page already) %lu,\n"
+ "InnoDB: space id (if created with >= MySQL-4.1.1"
+ " and stored already) %lu\n",
+ (ulong) checksum, (ulong) old_checksum,
+ (ulong) mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM),
+ (ulong) mach_read_from_4(read_buf + UNIV_PAGE_SIZE
+ - FIL_PAGE_END_LSN_OLD_CHKSUM),
(ulong) mach_read_from_4(read_buf + FIL_PAGE_LSN),
(ulong) mach_read_from_4(read_buf + FIL_PAGE_LSN + 4),
(ulong) mach_read_from_4(read_buf + UNIV_PAGE_SIZE
- - FIL_PAGE_END_LSN_OLD_CHKSUM + 4),
+ - FIL_PAGE_END_LSN_OLD_CHKSUM + 4),
(ulong) mach_read_from_4(read_buf + FIL_PAGE_OFFSET),
- (ulong) mach_read_from_4(read_buf + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
+ (ulong) mach_read_from_4(read_buf
+ + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID));
if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE)
== TRX_UNDO_INSERT) {
- fprintf(stderr,
+ fprintf(stderr,
"InnoDB: Page may be an insert undo log page\n");
} else if (mach_read_from_2(read_buf + TRX_UNDO_PAGE_HDR
- + TRX_UNDO_PAGE_TYPE)
- == TRX_UNDO_UPDATE) {
- fprintf(stderr,
+ + TRX_UNDO_PAGE_TYPE)
+ == TRX_UNDO_UPDATE) {
+ fprintf(stderr,
"InnoDB: Page may be an update undo log page\n");
}
- if (fil_page_get_type(read_buf) == FIL_PAGE_INDEX) {
- fprintf(stderr,
-"InnoDB: Page may be an index page where index id is %lu %lu\n",
- (ulong) ut_dulint_get_high(btr_page_get_index_id(read_buf)),
- (ulong) ut_dulint_get_low(btr_page_get_index_id(read_buf)));
+ switch (fil_page_get_type(read_buf)) {
+ case FIL_PAGE_INDEX:
+ fprintf(stderr,
+ "InnoDB: Page may be an index page where"
+ " index id is %lu %lu\n",
+ (ulong) ut_dulint_get_high
+ (btr_page_get_index_id(read_buf)),
+ (ulong) ut_dulint_get_low
+ (btr_page_get_index_id(read_buf)));
/* If the code is in ibbackup, dict_sys may be uninitialized,
i.e., NULL */
if (dict_sys != NULL) {
- index = dict_index_find_on_id_low(
- btr_page_get_index_id(read_buf));
- if (index) {
+ index = dict_index_find_on_id_low(
+ btr_page_get_index_id(read_buf));
+ if (index) {
fputs("InnoDB: (", stderr);
dict_index_name_print(stderr, NULL, index);
fputs(")\n", stderr);
}
}
- } else if (fil_page_get_type(read_buf) == FIL_PAGE_INODE) {
+ break;
+ case FIL_PAGE_INODE:
fputs("InnoDB: Page may be an 'inode' page\n", stderr);
- } else if (fil_page_get_type(read_buf) == FIL_PAGE_IBUF_FREE_LIST) {
+ break;
+ case FIL_PAGE_IBUF_FREE_LIST:
fputs("InnoDB: Page may be an insert buffer free list page\n",
- stderr);
+ stderr);
+ break;
+ case FIL_PAGE_TYPE_ALLOCATED:
+ fputs("InnoDB: Page may be a freshly allocated page\n",
+ stderr);
+ break;
+ case FIL_PAGE_IBUF_BITMAP:
+ fputs("InnoDB: Page may be an insert buffer bitmap page\n",
+ stderr);
+ break;
+ case FIL_PAGE_TYPE_SYS:
+ fputs("InnoDB: Page may be a system page\n",
+ stderr);
+ break;
+ case FIL_PAGE_TYPE_TRX_SYS:
+ fputs("InnoDB: Page may be a transaction system page\n",
+ stderr);
+ break;
+ case FIL_PAGE_TYPE_FSP_HDR:
+ fputs("InnoDB: Page may be a file space header page\n",
+ stderr);
+ break;
+ case FIL_PAGE_TYPE_XDES:
+ fputs("InnoDB: Page may be an extent descriptor page\n",
+ stderr);
+ break;
+ case FIL_PAGE_TYPE_BLOB:
+ fputs("InnoDB: Page may be a BLOB page\n",
+ stderr);
+ break;
}
}
@@ -471,7 +522,7 @@
block->magic_n = 0;
block->state = BUF_BLOCK_NOT_USED;
-
+
block->frame = frame;
block->awe_info = NULL;
@@ -480,7 +531,7 @@
block->io_fix = 0;
block->modify_clock = ut_dulint_zero;
-
+
block->file_page_was_freed = FALSE;
block->check_index_page_at_flush = FALSE;
@@ -491,15 +542,13 @@
block->n_pointers = 0;
- mutex_create(&block->mutex);
- mutex_set_level(&block->mutex, SYNC_BUF_BLOCK);
+ mutex_create(&block->mutex, SYNC_BUF_BLOCK);
- rw_lock_create(&(block->lock));
+ rw_lock_create(&block->lock, SYNC_LEVEL_VARYING);
ut_ad(rw_lock_validate(&(block->lock)));
#ifdef UNIV_SYNC_DEBUG
- rw_lock_create(&(block->debug_latch));
- rw_lock_set_level(&(block->debug_latch), SYNC_NO_ORDER_CHECK);
+ rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK);
#endif /* UNIV_SYNC_DEBUG */
}
@@ -525,15 +574,18 @@
byte* frame;
ulint i;
buf_block_t* block;
-
+
ut_a(max_size == curr_size);
ut_a(srv_use_awe || n_frames == max_size);
-
+
if (n_frames > curr_size) {
- fprintf(stderr,
-"InnoDB: AWE: Error: you must specify in my.cnf .._awe_mem_mb larger\n"
-"InnoDB: than .._buffer_pool_size. Now the former is %lu pages,\n"
-"InnoDB: the latter %lu pages.\n", (ulong) curr_size, (ulong) n_frames);
+ fprintf(stderr,
+ "InnoDB: AWE: Error: you must specify in my.cnf"
+ " .._awe_mem_mb larger\n"
+ "InnoDB: than .._buffer_pool_size. Now the former"
+ " is %lu pages,\n"
+ "InnoDB: the latter %lu pages.\n",
+ (ulong) curr_size, (ulong) n_frames);
return(NULL);
}
@@ -541,9 +593,8 @@
buf_pool = mem_alloc(sizeof(buf_pool_t));
/* 1. Initialize general fields
- ---------------------------- */
- mutex_create(&(buf_pool->mutex));
- mutex_set_level(&(buf_pool->mutex), SYNC_BUF_POOL);
+ ---------------------------- */
+ mutex_create(&buf_pool->mutex, SYNC_BUF_POOL);
mutex_enter(&(buf_pool->mutex));
@@ -553,31 +604,34 @@
buffer pool frames */
buf_pool->frame_mem = os_awe_allocate_virtual_mem_window(
- UNIV_PAGE_SIZE * (n_frames + 1));
-
+ UNIV_PAGE_SIZE * (n_frames + 1));
+
/* Allocate the physical memory for AWE and the AWE info array
for buf_pool */
if ((curr_size % ((1024 * 1024) / UNIV_PAGE_SIZE)) != 0) {
- fprintf(stderr,
-"InnoDB: AWE: Error: physical memory must be allocated in full megabytes.\n"
-"InnoDB: Trying to allocate %lu database pages.\n",
- (ulong) curr_size);
+ fprintf(stderr,
+ "InnoDB: AWE: Error: physical memory must be"
+ " allocated in full megabytes.\n"
+ "InnoDB: Trying to allocate %lu"
+ " database pages.\n",
+ (ulong) curr_size);
- return(NULL);
+ return(NULL);
}
if (!os_awe_allocate_physical_mem(&(buf_pool->awe_info),
- curr_size / ((1024 * 1024) / UNIV_PAGE_SIZE))) {
+ curr_size
+ / ((1024 * 1024)
+ / UNIV_PAGE_SIZE))) {
return(NULL);
}
/*----------------------------------------*/
} else {
buf_pool->frame_mem = os_mem_alloc_large(
- UNIV_PAGE_SIZE * (n_frames + 1),
- TRUE, FALSE);
+ UNIV_PAGE_SIZE * (n_frames + 1), TRUE, FALSE);
}
if (buf_pool->frame_mem == NULL) {
@@ -610,14 +664,15 @@
the window */
os_awe_map_physical_mem_to_window(buf_pool->frame_zero,
- n_frames *
- (UNIV_PAGE_SIZE / OS_AWE_X86_PAGE_SIZE),
- buf_pool->awe_info);
+ n_frames
+ * (UNIV_PAGE_SIZE
+ / OS_AWE_X86_PAGE_SIZE),
+ buf_pool->awe_info);
/*----------------------------------------*/
}
buf_pool->blocks_of_frames = ut_malloc(sizeof(void*) * n_frames);
-
+
if (buf_pool->blocks_of_frames == NULL) {
return(NULL);
@@ -638,7 +693,7 @@
} else {
frame = NULL;
}
-
+
buf_block_init(block, frame);
if (srv_use_awe) {
@@ -659,16 +714,16 @@
buf_pool->n_pages_written = 0;
buf_pool->n_pages_created = 0;
buf_pool->n_pages_awe_remapped = 0;
-
+
buf_pool->n_page_gets = 0;
buf_pool->n_page_gets_old = 0;
buf_pool->n_pages_read_old = 0;
buf_pool->n_pages_written_old = 0;
buf_pool->n_pages_created_old = 0;
buf_pool->n_pages_awe_remapped_old = 0;
-
+
/* 2. Initialize flushing fields
- ---------------------------- */
+ ---------------------------- */
UT_LIST_INIT(buf_pool->flush_list);
for (i = BUF_FLUSH_LRU; i <= BUF_FLUSH_LIST; i++) {
@@ -681,9 +736,9 @@
buf_pool->ulint_clock = 1;
buf_pool->freed_page_clock = 0;
-
+
/* 3. Initialize LRU fields
- ---------------------------- */
+ ---------------------------- */
UT_LIST_INIT(buf_pool->LRU);
buf_pool->LRU_old = NULL;
@@ -707,9 +762,10 @@
if (srv_use_awe) {
/* Add to the list of blocks mapped to
frames */
-
+
UT_LIST_ADD_LAST(awe_LRU_free_mapped,
- buf_pool->awe_LRU_free_mapped, block);
+ buf_pool->awe_LRU_free_mapped,
+ block);
}
}
@@ -720,15 +776,15 @@
mutex_exit(&(buf_pool->mutex));
if (srv_use_adaptive_hash_indexes) {
- btr_search_sys_create(
- curr_size * UNIV_PAGE_SIZE / sizeof(void*) / 64);
+ btr_search_sys_create(curr_size * UNIV_PAGE_SIZE
+ / sizeof(void*) / 64);
} else {
- /* Create only a small dummy system */
- btr_search_sys_create(1000);
+ /* Create only a small dummy system */
+ btr_search_sys_create(1000);
}
return(buf_pool);
-}
+}
/************************************************************************
Maps the page of block to a frame, if not mapped yet. Unmaps some page
@@ -761,7 +817,7 @@
bck = UT_LIST_GET_LAST(buf_pool->awe_LRU_free_mapped);
- while (bck) {
+ while (bck) {
ibool skip;
mutex_enter(&bck->mutex);
@@ -785,24 +841,25 @@
block->frame = bck->frame;
*(buf_pool->blocks_of_frames
- + (((ulint)(block->frame
- - buf_pool->frame_zero))
- >> UNIV_PAGE_SIZE_SHIFT))
+ + (((ulint)(block->frame
+ - buf_pool->frame_zero))
+ >> UNIV_PAGE_SIZE_SHIFT))
= block;
-
+
bck->frame = NULL;
UT_LIST_REMOVE(awe_LRU_free_mapped,
- buf_pool->awe_LRU_free_mapped,
- bck);
+ buf_pool->awe_LRU_free_mapped,
+ bck);
if (add_to_mapped_list) {
- UT_LIST_ADD_FIRST(awe_LRU_free_mapped,
+ UT_LIST_ADD_FIRST(
+ awe_LRU_free_mapped,
buf_pool->awe_LRU_free_mapped,
block);
}
buf_pool->n_pages_awe_remapped++;
-
+
mutex_exit(&bck->mutex);
return;
@@ -810,8 +867,8 @@
}
fprintf(stderr,
-"InnoDB: AWE: Fatal error: cannot find a page to unmap\n"
-"InnoDB: awe_LRU_free_mapped list length %lu\n",
+ "InnoDB: AWE: Fatal error: cannot find a page to unmap\n"
+ "InnoDB: awe_LRU_free_mapped list length %lu\n",
(ulong) UT_LIST_GET_LEN(buf_pool->awe_LRU_free_mapped));
ut_a(0);
@@ -850,7 +907,7 @@
/* Note that we read freed_page_clock's without holding any mutex:
this is allowed since the result is used only in heuristics */
- if (buf_pool->freed_page_clock >= block->freed_page_clock
+ if (buf_pool->freed_page_clock >= block->freed_page_clock
+ 1 + (buf_pool->curr_size / 4)) {
mutex_enter(&buf_pool->mutex);
@@ -869,11 +926,11 @@
void
buf_page_make_young(
-/*=================*/
+/*================*/
buf_frame_t* frame) /* in: buffer frame of a file page */
{
buf_block_t* block;
-
+
mutex_enter(&(buf_pool->mutex));
block = buf_block_align(frame);
@@ -927,7 +984,7 @@
{
buf_block_free(buf_block_align(frame));
}
-
+
/************************************************************************
Returns the buffer control block if the page can be found in the buffer
pool. NOTE that it is possible that the page is not yet read
@@ -972,7 +1029,7 @@
if (block) {
block->check_index_page_at_flush = FALSE;
}
-
+
mutex_exit(&(buf_pool->mutex));
}
@@ -1108,7 +1165,7 @@
ulint fix_type;
ibool success;
ibool must_read;
-
+
ut_ad(mtr);
ut_ad((rw_latch == RW_S_LATCH)
|| (rw_latch == RW_X_LATCH)
@@ -1123,12 +1180,12 @@
loop:
block = NULL;
mutex_enter_fast(&(buf_pool->mutex));
-
+
if (guess) {
block = buf_block_align(guess);
if ((offset != block->offset) || (space != block->space)
- || (block->state != BUF_BLOCK_FILE_PAGE)) {
+ || (block->state != BUF_BLOCK_FILE_PAGE)) {
block = NULL;
}
@@ -1165,7 +1222,7 @@
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
must_read = FALSE;
-
+
if (block->io_fix == BUF_IO_READ) {
must_read = TRUE;
@@ -1177,7 +1234,7 @@
return(NULL);
}
- }
+ }
/* If AWE is enabled and the page is not mapped to a frame, then
map it */
@@ -1188,10 +1245,10 @@
/* We set second parameter TRUE because the block is in the
LRU list and we must put it to awe_LRU_free_mapped list once
mapped to a frame */
-
+
buf_awe_map_page_to_frame(block, TRUE);
}
-
+
#ifdef UNIV_SYNC_DEBUG
buf_block_buf_fix_inc_debug(block, file, line);
#else
@@ -1211,7 +1268,7 @@
#ifdef UNIV_DEBUG_FILE_ACCESSES
ut_a(block->file_page_was_freed == FALSE);
-#endif
+#endif
#ifdef UNIV_DEBUG
buf_dbg_counter++;
@@ -1226,12 +1283,12 @@
if (mode == BUF_GET_NOWAIT) {
if (rw_latch == RW_S_LATCH) {
success = rw_lock_s_lock_func_nowait(&(block->lock),
- file, line);
+ file, line);
fix_type = MTR_MEMO_PAGE_S_FIX;
} else {
ut_ad(rw_latch == RW_X_LATCH);
success = rw_lock_x_lock_func_nowait(&(block->lock),
- file, line);
+ file, line);
fix_type = MTR_MEMO_PAGE_X_FIX;
}
@@ -1243,29 +1300,29 @@
mutex_exit(&block->mutex);
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
-#endif
+#endif
return(NULL);
}
} else if (rw_latch == RW_NO_LATCH) {
if (must_read) {
- /* Let us wait until the read operation
+ /* Let us wait until the read operation
completes */
- for (;;) {
+ for (;;) {
mutex_enter(&block->mutex);
- if (block->io_fix == BUF_IO_READ) {
+ if (block->io_fix == BUF_IO_READ) {
mutex_exit(&block->mutex);
-
+
os_thread_sleep(WAIT_FOR_READ);
} else {
-
+
mutex_exit(&block->mutex);
- break;
+ break;
}
}
}
@@ -1294,7 +1351,7 @@
#ifdef UNIV_IBUF_DEBUG
ut_a(ibuf_count_get(block->space, block->offset) == 0);
#endif
- return(block->frame);
+ return(block->frame);
}
/************************************************************************
@@ -1352,17 +1409,17 @@
if (rw_latch == RW_S_LATCH) {
success = rw_lock_s_lock_func_nowait(&(block->lock),
- file, line);
+ file, line);
fix_type = MTR_MEMO_PAGE_S_FIX;
} else {
success = rw_lock_x_lock_func_nowait(&(block->lock),
- file, line);
+ file, line);
fix_type = MTR_MEMO_PAGE_X_FIX;
}
if (UNIV_UNLIKELY(!success)) {
mutex_enter(&block->mutex);
-
+
block->buf_fix_count--;
mutex_exit(&block->mutex);
@@ -1384,7 +1441,7 @@
}
mutex_enter(&block->mutex);
-
+
block->buf_fix_count--;
mutex_exit(&block->mutex);
@@ -1415,7 +1472,7 @@
read-ahead */
buf_read_ahead_linear(buf_frame_get_space_id(guess),
- buf_frame_get_page_no(guess));
+ buf_frame_get_page_no(guess));
}
#ifdef UNIV_IBUF_DEBUG
@@ -1448,14 +1505,14 @@
ut_ad(mtr);
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
-
+
block = buf_block_align(guess);
mutex_enter(&block->mutex);
if (block->state == BUF_BLOCK_REMOVE_HASH) {
- /* Another thread is just freeing the block from the LRU list
- of the buffer pool: do not try to access this page; this
+ /* Another thread is just freeing the block from the LRU list
+ of the buffer pool: do not try to access this page; this
attempt to access the page can only come through the hash
index because when the buffer block state is ..._REMOVE_HASH,
we have already removed it from the page address hash table
@@ -1483,24 +1540,24 @@
if (rw_latch == RW_S_LATCH) {
success = rw_lock_s_lock_func_nowait(&(block->lock),
- file, line);
+ file, line);
fix_type = MTR_MEMO_PAGE_S_FIX;
} else {
success = rw_lock_x_lock_func_nowait(&(block->lock),
- file, line);
+ file, line);
fix_type = MTR_MEMO_PAGE_X_FIX;
}
-
+
if (!success) {
mutex_enter(&block->mutex);
-
+
block->buf_fix_count--;
mutex_exit(&block->mutex);
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
-#endif
+#endif
return(FALSE);
}
@@ -1522,7 +1579,7 @@
#ifdef UNIV_IBUF_DEBUG
ut_a((mode == BUF_KEEP_OLD)
- || (ibuf_count_get(block->space, block->offset) == 0));
+ || (ibuf_count_get(block->space, block->offset) == 0));
#endif
buf_pool->n_page_gets++;
@@ -1543,9 +1600,9 @@
/* Set the state of the block */
block->magic_n = BUF_BLOCK_MAGIC_N;
- block->state = BUF_BLOCK_FILE_PAGE;
- block->space = space;
- block->offset = offset;
+ block->state = BUF_BLOCK_FILE_PAGE;
+ block->space = space;
+ block->offset = offset;
block->lock_hash_val = 0;
@@ -1553,16 +1610,16 @@
block->newest_modification = ut_dulint_zero;
block->oldest_modification = ut_dulint_zero;
-
+
block->accessed = FALSE;
- block->buf_fix_count = 0;
+ block->buf_fix_count = 0;
block->io_fix = 0;
block->n_hash_helps = 0;
block->is_hashed = FALSE;
- block->n_fields = 1;
- block->n_bytes = 0;
- block->side = BTR_SEARCH_LEFT_SIDE;
+ block->n_fields = 1;
+ block->n_bytes = 0;
+ block->left_side = TRUE;
block->file_page_was_freed = FALSE;
}
@@ -1587,48 +1644,49 @@
/* Set the state of the block */
block->magic_n = BUF_BLOCK_MAGIC_N;
- block->state = BUF_BLOCK_FILE_PAGE;
- block->space = space;
- block->offset = offset;
+ block->state = BUF_BLOCK_FILE_PAGE;
+ block->space = space;
+ block->offset = offset;
block->check_index_page_at_flush = FALSE;
block->index = NULL;
-
+
block->lock_hash_val = lock_rec_hash(space, offset);
/* Insert into the hash table of file pages */
- if (buf_page_hash_get(space, offset)) {
- fprintf(stderr,
-"InnoDB: Error: page %lu %lu already found from the hash table\n",
+ if (buf_page_hash_get(space, offset)) {
+ fprintf(stderr,
+ "InnoDB: Error: page %lu %lu already found"
+ " in the hash table\n",
(ulong) space,
(ulong) offset);
#ifdef UNIV_DEBUG
- buf_print();
- buf_LRU_print();
- buf_validate();
- buf_LRU_validate();
+ buf_print();
+ buf_LRU_print();
+ buf_validate();
+ buf_LRU_validate();
#endif /* UNIV_DEBUG */
- ut_a(0);
- }
+ ut_a(0);
+ }
HASH_INSERT(buf_block_t, hash, buf_pool->page_hash,
- buf_page_address_fold(space, offset), block);
+ buf_page_address_fold(space, offset), block);
block->freed_page_clock = 0;
block->newest_modification = ut_dulint_zero;
block->oldest_modification = ut_dulint_zero;
-
+
block->accessed = FALSE;
- block->buf_fix_count = 0;
+ block->buf_fix_count = 0;
block->io_fix = 0;
block->n_hash_helps = 0;
block->is_hashed = FALSE;
- block->n_fields = 1;
- block->n_bytes = 0;
- block->side = BTR_SEARCH_LEFT_SIDE;
+ block->n_fields = 1;
+ block->n_bytes = 0;
+ block->left_side = TRUE;
block->file_page_was_freed = FALSE;
}
@@ -1643,7 +1701,7 @@
on the buffer frame. The io-handler must take care that the flag is cleared
and the lock released later. This is one of the functions which perform the
state transition NOT_USED => FILE_PAGE to a block (the other is
-buf_page_create). */
+buf_page_create). */
buf_block_t*
buf_page_init_for_read(
@@ -1669,9 +1727,9 @@
ut_ad(!ibuf_bitmap_page(offset));
ut_ad(ibuf_inside());
-
+
mtr_start(&mtr);
-
+
if (!ibuf_page_low(space, offset, &mtr)) {
mtr_commit(&mtr);
@@ -1681,7 +1739,7 @@
} else {
ut_ad(mode == BUF_READ_ANY_PAGE);
}
-
+
block = buf_block_alloc();
ut_a(block);
@@ -1689,16 +1747,17 @@
mutex_enter(&(buf_pool->mutex));
mutex_enter(&block->mutex);
- if (fil_tablespace_deleted_or_being_deleted_in_mem(space,
- tablespace_version)) {
+ if (fil_tablespace_deleted_or_being_deleted_in_mem(
+ space, tablespace_version)) {
*err = DB_TABLESPACE_DELETED;
}
if (*err == DB_TABLESPACE_DELETED
|| NULL != buf_page_hash_get(space, offset)) {
- /* The page belongs to a space which has been deleted or is
- being deleted, or the page is already in buf_pool, return */
+ /* The page belongs to a space which has been
+ deleted or is being deleted, or the page is
+ already in buf_pool, return */
mutex_exit(&block->mutex);
mutex_exit(&(buf_pool->mutex));
@@ -1714,28 +1773,28 @@
}
ut_ad(block);
-
+
buf_page_init(space, offset, block);
/* The block must be put to the LRU list, to the old blocks */
- buf_LRU_add_block(block, TRUE); /* TRUE == to old blocks */
-
+ buf_LRU_add_block(block, TRUE); /* TRUE == to old blocks */
+
block->io_fix = BUF_IO_READ;
buf_pool->n_pend_reads++;
-
+
/* We set a pass-type x-lock on the frame because then the same
thread which called for the read operation (and is running now at
this point of code) can wait for the read to complete by waiting
for the x-lock on the frame; if the x-lock were recursive, the
same thread would illegally get the x-lock before the page read
is completed. The x-lock is cleared by the io-handler thread. */
-
+
rw_lock_x_lock_gen(&(block->lock), BUF_IO_READ);
-
+
mutex_exit(&block->mutex);
- mutex_exit(&(buf_pool->mutex));
+ mutex_exit(&(buf_pool->mutex));
if (mode == BUF_READ_IBUF_PAGES_ONLY) {
@@ -1743,7 +1802,7 @@
}
return(block);
-}
+}
/************************************************************************
Initializes a page to the buffer buf_pool. The page is usually not read
@@ -1763,11 +1822,11 @@
buf_frame_t* frame;
buf_block_t* block;
buf_block_t* free_block = NULL;
-
+
ut_ad(mtr);
free_block = buf_LRU_get_free_block();
-
+
mutex_enter(&(buf_pool->mutex));
block = buf_page_hash_get(space, offset);
@@ -1798,14 +1857,14 @@
#endif /* UNIV_DEBUG */
block = free_block;
-
+
mutex_enter(&block->mutex);
buf_page_init(space, offset, block);
/* The block must be put to the LRU list */
buf_LRU_add_block(block, FALSE);
-
+
#ifdef UNIV_SYNC_DEBUG
buf_block_buf_fix_inc_debug(block, __FILE__, __LINE__);
#else
@@ -1818,7 +1877,7 @@
mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
block->accessed = TRUE;
-
+
mutex_exit(&block->mutex);
/* Delete possible entries for the page from the insert buffer:
@@ -1831,6 +1890,10 @@
frame = block->frame;
+ memset(frame + FIL_PAGE_PREV, 0xff, 4);
+ memset(frame + FIL_PAGE_NEXT, 0xff, 4);
+ mach_write_to_2(frame + FIL_PAGE_TYPE, FIL_PAGE_TYPE_ALLOCATED);
+
/* Reset to zero the file flush lsn field in the page; if the first
page of an ibdata file is 'created' in this function into the buffer
pool then we lose the original contents of the file flush lsn stamp.
@@ -1862,8 +1925,7 @@
buf_block_t* block) /* in: pointer to the block in question */
{
ulint io_type;
- ulint read_page_no;
-
+
ut_ad(block);
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
@@ -1878,70 +1940,103 @@
if (io_type == BUF_IO_READ) {
/* If this page is not uninitialized and not in the
- doublewrite buffer, then the page number should be the
- same as in block */
+ doublewrite buffer, then the page number and space id
+ should be the same as in block. */
+ ulint read_page_no = mach_read_from_4(
+ block->frame + FIL_PAGE_OFFSET);
+ ulint read_space_id = mach_read_from_4(
+ block->frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
- read_page_no = mach_read_from_4((block->frame)
- + FIL_PAGE_OFFSET);
- if (read_page_no != 0
- && !trx_doublewrite_page_inside(read_page_no)
- && read_page_no != block->offset) {
+ if (!block->space
+ && trx_doublewrite_page_inside(block->offset)) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Error: reading page %lu\n"
+ "InnoDB: which is in the"
+ " doublewrite buffer!\n",
+ (ulong) block->offset);
+ } else if (!read_space_id && !read_page_no) {
+ /* This is likely an uninitialized page. */
+ } else if ((block->space && block->space != read_space_id)
+ || block->offset != read_page_no) {
+ /* We did not compare space_id to read_space_id
+ if block->space == 0, because the field on the
+ page may contain garbage in MySQL < 4.1.1,
+ which only supported block->space == 0. */
+
+ ut_print_timestamp(stderr);
fprintf(stderr,
-"InnoDB: Error: page n:o stored in the page read in is %lu, should be %lu!\n",
- (ulong) read_page_no, (ulong) block->offset);
+ " InnoDB: Error: space id and page n:o"
+ " stored in the page\n"
+ "InnoDB: read in are %lu:%lu,"
+ " should be %lu:%lu!\n",
+ (ulong) read_space_id, (ulong) read_page_no,
+ (ulong) block->space, (ulong) block->offset);
}
/* From version 3.23.38 up we store the page checksum
- to the 4 first bytes of the page end lsn field */
+ to the 4 first bytes of the page end lsn field */
if (buf_page_is_corrupted(block->frame)) {
- fprintf(stderr,
- "InnoDB: Database page corruption on disk or a failed\n"
- "InnoDB: file read of page %lu.\n", (ulong) block->offset);
-
- fputs(
- "InnoDB: You may have to recover from a backup.\n", stderr);
+ fprintf(stderr,
+ "InnoDB: Database page corruption on disk"
+ " or a failed\n"
+ "InnoDB: file read of page %lu.\n",
+ (ulong) block->offset);
+
+ fputs("InnoDB: You may have to recover"
+ " from a backup.\n", stderr);
buf_page_print(block->frame);
- fprintf(stderr,
- "InnoDB: Database page corruption on disk or a failed\n"
- "InnoDB: file read of page %lu.\n", (ulong) block->offset);
- fputs(
- "InnoDB: You may have to recover from a backup.\n", stderr);
- fputs(
- "InnoDB: It is also possible that your operating\n"
- "InnoDB: system has corrupted its own file cache\n"
- "InnoDB: and rebooting your computer removes the\n"
- "InnoDB: error.\n"
- "InnoDB: If the corrupt page is an index page\n"
- "InnoDB: you can also try to fix the corruption\n"
- "InnoDB: by dumping, dropping, and reimporting\n"
- "InnoDB: the corrupt table. You can use CHECK\n"
- "InnoDB: TABLE to scan your table for corruption.\n"
- "InnoDB: See also "
-"InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html\n"
- "InnoDB: about forcing recovery.\n", stderr);
-
+ fprintf(stderr,
+ "InnoDB: Database page corruption on disk"
+ " or a failed\n"
+ "InnoDB: file read of page %lu.\n",
+ (ulong) block->offset);
+ fputs("InnoDB: You may have to recover"
+ " from a backup.\n", stderr);
+ fputs("InnoDB: It is also possible that"
+ " your operating\n"
+ "InnoDB: system has corrupted its"
+ " own file cache\n"
+ "InnoDB: and rebooting your computer"
+ " removes the\n"
+ "InnoDB: error.\n"
+ "InnoDB: If the corrupt page is an index page\n"
+ "InnoDB: you can also try to"
+ " fix the corruption\n"
+ "InnoDB: by dumping, dropping,"
+ " and reimporting\n"
+ "InnoDB: the corrupt table."
+ " You can use CHECK\n"
+ "InnoDB: TABLE to scan your"
+ " table for corruption.\n"
+ "InnoDB: See also"
+ " http://dev.mysql.com/doc/refman/5.1/en/"
+ "forcing-recovery.html\n"
+ "InnoDB: about forcing recovery.\n", stderr);
+
if (srv_force_recovery < SRV_FORCE_IGNORE_CORRUPT) {
- fputs(
- "InnoDB: Ending processing because of a corrupt database page.\n",
- stderr);
- exit(1);
- }
+ fputs("InnoDB: Ending processing because of"
+ " a corrupt database page.\n",
+ stderr);
+ exit(1);
+ }
}
if (recv_recovery_is_on()) {
recv_recover_page(FALSE, TRUE, block->frame,
- block->space, block->offset);
+ block->space, block->offset);
}
if (!recv_no_ibuf_operations) {
- ibuf_merge_or_delete_for_page(block->frame,
- block->space, block->offset, TRUE);
+ ibuf_merge_or_delete_for_page(
+ block->frame, block->space, block->offset,
+ TRUE);
}
}
-
+
mutex_enter(&(buf_pool->mutex));
mutex_enter(&block->mutex);
@@ -1954,12 +2049,12 @@
id. */
block->io_fix = 0;
-
+
if (io_type == BUF_IO_READ) {
/* NOTE that the call to ibuf may have moved the ownership of
the x-latch to this OS thread: do not let this confuse you in
- debugging! */
-
+ debugging! */
+
ut_ad(buf_pool->n_pend_reads > 0);
buf_pool->n_pend_reads--;
buf_pool->n_pages_read++;
@@ -1989,7 +2084,7 @@
}
#endif /* UNIV_DEBUG */
}
-
+
mutex_exit(&block->mutex);
mutex_exit(&(buf_pool->mutex));
@@ -2013,13 +2108,13 @@
ibool freed;
ut_ad(buf_all_freed());
-
+
freed = TRUE;
while (freed) {
freed = buf_LRU_search_and_free_block(100);
}
-
+
mutex_enter(&(buf_pool->mutex));
ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
@@ -2044,7 +2139,7 @@
ulint n_flush = 0;
ulint n_free = 0;
ulint n_page = 0;
-
+
ut_ad(buf_pool);
mutex_enter(&(buf_pool->mutex));
@@ -2058,25 +2153,26 @@
if (block->state == BUF_BLOCK_FILE_PAGE) {
ut_a(buf_page_hash_get(block->space,
- block->offset) == block);
+ block->offset) == block);
n_page++;
#ifdef UNIV_IBUF_DEBUG
ut_a((block->io_fix == BUF_IO_READ)
|| ibuf_count_get(block->space, block->offset)
- == 0);
+ == 0);
#endif
if (block->io_fix == BUF_IO_WRITE) {
if (block->flush_type == BUF_FLUSH_LRU) {
n_lru_flush++;
- ut_a(rw_lock_is_locked(&(block->lock),
- RW_LOCK_SHARED));
- } else if (block->flush_type ==
- BUF_FLUSH_LIST) {
+ ut_a(rw_lock_is_locked(
+ &block->lock,
+ RW_LOCK_SHARED));
+ } else if (block->flush_type
+ == BUF_FLUSH_LIST) {
n_list_flush++;
- } else if (block->flush_type ==
- BUF_FLUSH_SINGLE_PAGE) {
+ } else if (block->flush_type
+ == BUF_FLUSH_SINGLE_PAGE) {
n_single_flush++;
} else {
ut_error;
@@ -2085,32 +2181,34 @@
} else if (block->io_fix == BUF_IO_READ) {
ut_a(rw_lock_is_locked(&(block->lock),
- RW_LOCK_EX));
+ RW_LOCK_EX));
}
-
+
n_lru++;
if (ut_dulint_cmp(block->oldest_modification,
- ut_dulint_zero) > 0) {
- n_flush++;
- }
-
+ ut_dulint_zero) > 0) {
+ n_flush++;
+ }
+
} else if (block->state == BUF_BLOCK_NOT_USED) {
n_free++;
}
mutex_exit(&block->mutex);
- }
+ }
if (n_lru + n_free > buf_pool->curr_size) {
- fprintf(stderr, "n LRU %lu, n free %lu\n", (ulong) n_lru, (ulong) n_free);
+ fprintf(stderr, "n LRU %lu, n free %lu\n",
+ (ulong) n_lru, (ulong) n_free);
ut_error;
}
ut_a(UT_LIST_GET_LEN(buf_pool->LRU) == n_lru);
if (UT_LIST_GET_LEN(buf_pool->free) != n_free) {
fprintf(stderr, "Free list len %lu, free blocks %lu\n",
- (ulong) UT_LIST_GET_LEN(buf_pool->free), (ulong) n_free);
+ (ulong) UT_LIST_GET_LEN(buf_pool->free),
+ (ulong) n_free);
ut_error;
}
ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
@@ -2118,14 +2216,14 @@
ut_a(buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE] == n_single_flush);
ut_a(buf_pool->n_flush[BUF_FLUSH_LIST] == n_list_flush);
ut_a(buf_pool->n_flush[BUF_FLUSH_LRU] == n_lru_flush);
-
+
mutex_exit(&(buf_pool->mutex));
ut_a(buf_LRU_validate());
ut_a(buf_flush_validate());
return(TRUE);
-}
+}
/*************************************************************************
Prints info of the buffer buf_pool data structure. */
@@ -2141,9 +2239,9 @@
ulint j;
dulint id;
ulint n_found;
- buf_frame_t* frame;
+ buf_frame_t* frame;
dict_index_t* index;
-
+
ut_ad(buf_pool);
size = buf_pool->curr_size;
@@ -2152,7 +2250,7 @@
counts = mem_alloc(sizeof(ulint) * size);
mutex_enter(&(buf_pool->mutex));
-
+
fprintf(stderr,
"buf_pool size %lu\n"
"database pages %lu\n"
@@ -2173,7 +2271,7 @@
(ulong) buf_pool->n_pages_written);
/* Count the number of blocks belonging to each index in the buffer */
-
+
n_found = 0;
for (i = 0; i < size; i++) {
@@ -2211,8 +2309,8 @@
fprintf(stderr,
"Block count for index %lu in buffer is about %lu",
- (ulong) ut_dulint_get_low(index_ids[i]),
- (ulong) counts[i]);
+ (ulong) ut_dulint_get_low(index_ids[i]),
+ (ulong) counts[i]);
if (index) {
putc(' ', stderr);
@@ -2221,12 +2319,12 @@
putc('\n', stderr);
}
-
+
mem_free(index_ids);
mem_free(counts);
ut_a(buf_validate());
-}
+}
#endif /* UNIV_DEBUG */
/*************************************************************************
@@ -2235,13 +2333,13 @@
ulint
buf_get_latched_pages_number(void)
{
- buf_block_t* block;
- ulint i;
- ulint fixed_pages_number = 0;
+ buf_block_t* block;
+ ulint i;
+ ulint fixed_pages_number = 0;
- mutex_enter(&(buf_pool->mutex));
+ mutex_enter(&(buf_pool->mutex));
- for (i = 0; i < buf_pool->curr_size; i++) {
+ for (i = 0; i < buf_pool->curr_size; i++) {
block = buf_pool_get_nth_block(buf_pool, i);
@@ -2254,10 +2352,11 @@
mutex_exit(&block->mutex);
}
- }
+ }
+
+ mutex_exit(&(buf_pool->mutex));
- mutex_exit(&(buf_pool->mutex));
- return fixed_pages_number;
+ return(fixed_pages_number);
}
/*************************************************************************
@@ -2268,9 +2367,9 @@
/*=======================*/
{
return(buf_pool->n_pend_reads
- + buf_pool->n_flush[BUF_FLUSH_LRU]
- + buf_pool->n_flush[BUF_FLUSH_LIST]
- + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
+ + buf_pool->n_flush[BUF_FLUSH_LRU]
+ + buf_pool->n_flush[BUF_FLUSH_LIST]
+ + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
}
/*************************************************************************
@@ -2286,10 +2385,10 @@
mutex_enter(&(buf_pool->mutex));
ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list))
- / (1 + UT_LIST_GET_LEN(buf_pool->LRU)
- + UT_LIST_GET_LEN(buf_pool->free));
+ / (1 + UT_LIST_GET_LEN(buf_pool->LRU)
+ + UT_LIST_GET_LEN(buf_pool->free));
- /* 1 + is there to avoid division by zero */
+ /* 1 + is there to avoid division by zero */
mutex_exit(&(buf_pool->mutex));
@@ -2307,20 +2406,22 @@
time_t current_time;
double time_elapsed;
ulint size;
-
+
ut_ad(buf_pool);
size = buf_pool->curr_size;
mutex_enter(&(buf_pool->mutex));
-
+
if (srv_use_awe) {
fprintf(stderr,
- "AWE: Buffer pool memory frames %lu\n",
- (ulong) buf_pool->n_frames);
-
+ "AWE: Buffer pool memory frames %lu\n",
+ (ulong) buf_pool->n_frames);
+
fprintf(stderr,
- "AWE: Database pages and free buffers mapped in frames %lu\n",
- (ulong) UT_LIST_GET_LEN(buf_pool->awe_LRU_free_mapped));
+ "AWE: Database pages and free buffers"
+ " mapped in frames %lu\n",
+ (ulong)
+ UT_LIST_GET_LEN(buf_pool->awe_LRU_free_mapped));
}
fprintf(file,
"Buffer pool size %lu\n"
@@ -2335,14 +2436,14 @@
(ulong) UT_LIST_GET_LEN(buf_pool->flush_list),
(ulong) buf_pool->n_pend_reads,
(ulong) buf_pool->n_flush[BUF_FLUSH_LRU]
- + buf_pool->init_flush[BUF_FLUSH_LRU],
+ + buf_pool->init_flush[BUF_FLUSH_LRU],
(ulong) buf_pool->n_flush[BUF_FLUSH_LIST]
- + buf_pool->init_flush[BUF_FLUSH_LIST],
+ + buf_pool->init_flush[BUF_FLUSH_LIST],
(ulong) buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
current_time = time(NULL);
time_elapsed = 0.001 + difftime(current_time,
- buf_pool->last_printout_time);
+ buf_pool->last_printout_time);
buf_pool->last_printout_time = current_time;
fprintf(file,
@@ -2360,20 +2461,21 @@
if (srv_use_awe) {
fprintf(file, "AWE: %.2f page remaps/s\n",
- (buf_pool->n_pages_awe_remapped
- - buf_pool->n_pages_awe_remapped_old)
+ (buf_pool->n_pages_awe_remapped
+ - buf_pool->n_pages_awe_remapped_old)
/ time_elapsed);
}
-
+
if (buf_pool->n_page_gets > buf_pool->n_page_gets_old) {
fprintf(file, "Buffer pool hit rate %lu / 1000\n",
- (ulong) (1000
- - ((1000 *
- (buf_pool->n_pages_read - buf_pool->n_pages_read_old))
- / (buf_pool->n_page_gets - buf_pool->n_page_gets_old))));
+ (ulong)
+ (1000 - ((1000 * (buf_pool->n_pages_read
+ - buf_pool->n_pages_read_old))
+ / (buf_pool->n_page_gets
+ - buf_pool->n_page_gets_old))));
} else {
fputs("No buffer pool page gets since the last printout\n",
- file);
+ file);
}
buf_pool->n_page_gets_old = buf_pool->n_page_gets;
@@ -2392,12 +2494,12 @@
buf_refresh_io_stats(void)
/*======================*/
{
- buf_pool->last_printout_time = time(NULL);
+ buf_pool->last_printout_time = time(NULL);
buf_pool->n_page_gets_old = buf_pool->n_page_gets;
buf_pool->n_pages_read_old = buf_pool->n_pages_read;
buf_pool->n_pages_created_old = buf_pool->n_pages_created;
buf_pool->n_pages_written_old = buf_pool->n_pages_written;
- buf_pool->n_pages_awe_remapped_old = buf_pool->n_pages_awe_remapped;
+ buf_pool->n_pages_awe_remapped_old = buf_pool->n_pages_awe_remapped;
}
/*************************************************************************
@@ -2409,7 +2511,7 @@
{
buf_block_t* block;
ulint i;
-
+
ut_ad(buf_pool);
mutex_enter(&(buf_pool->mutex));
@@ -2428,17 +2530,17 @@
"Page %lu %lu still fixed or dirty\n",
(ulong) block->space,
(ulong) block->offset);
- ut_error;
+ ut_error;
}
}
mutex_exit(&block->mutex);
- }
+ }
mutex_exit(&(buf_pool->mutex));
return(TRUE);
-}
+}
/*************************************************************************
Checks that there currently are no pending i/o-operations for the buffer
@@ -2454,8 +2556,8 @@
mutex_enter(&(buf_pool->mutex));
if (buf_pool->n_pend_reads + buf_pool->n_flush[BUF_FLUSH_LRU]
- + buf_pool->n_flush[BUF_FLUSH_LIST]
- + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
+ + buf_pool->n_flush[BUF_FLUSH_LIST]
+ + buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
ret = FALSE;
} else {
ret = TRUE;
--- 1.28.4.1/innobase/buf/buf0flu.c 2007-01-17 16:44:04 -07:00
+++ 1.39/storage/innobase/buf/buf0flu.c 2007-01-17 17:18:02 -07:00
@@ -26,11 +26,11 @@
#include "trx0sys.h"
#include "srv0srv.h"
-/* When flushed, dirty blocks are searched in neigborhoods of this size, and
+/* When flushed, dirty blocks are searched in neighborhoods of this size, and
flushed along with the original page. */
#define BUF_FLUSH_AREA ut_min(BUF_READ_AHEAD_AREA,\
- buf_pool->curr_size / 16)
+ buf_pool->curr_size / 16)
/**********************************************************************
Validates the flush list. */
@@ -55,10 +55,9 @@
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_ad((UT_LIST_GET_FIRST(buf_pool->flush_list) == NULL)
- || (ut_dulint_cmp(
- (UT_LIST_GET_FIRST(buf_pool->flush_list))
- ->oldest_modification,
- block->oldest_modification) <= 0));
+ || (ut_dulint_cmp((UT_LIST_GET_FIRST(buf_pool->flush_list))
+ ->oldest_modification,
+ block->oldest_modification) <= 0));
UT_LIST_ADD_FIRST(flush_list, buf_pool->flush_list, block);
@@ -77,7 +76,7 @@
{
buf_block_t* prev_b;
buf_block_t* b;
-
+
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
#endif /* UNIV_SYNC_DEBUG */
@@ -86,7 +85,7 @@
b = UT_LIST_GET_FIRST(buf_pool->flush_list);
while (b && (ut_dulint_cmp(b->oldest_modification,
- block->oldest_modification) > 0)) {
+ block->oldest_modification) > 0)) {
prev_b = b;
b = UT_LIST_GET_NEXT(flush_list, b);
}
@@ -95,7 +94,7 @@
UT_LIST_ADD_FIRST(flush_list, buf_pool->flush_list, block);
} else {
UT_LIST_INSERT_AFTER(flush_list, buf_pool->flush_list, prev_b,
- block);
+ block);
}
ut_ad(buf_flush_validate_low());
@@ -119,9 +118,10 @@
if (block->state != BUF_BLOCK_FILE_PAGE) {
ut_print_timestamp(stderr);
fprintf(stderr,
-" InnoDB: Error: buffer block state %lu in the LRU list!\n",
+ " InnoDB: Error: buffer block state %lu"
+ " in the LRU list!\n",
(ulong)block->state);
- ut_print_buf(stderr, (byte*)block, sizeof(buf_block_t));
+ ut_print_buf(stderr, block, sizeof(buf_block_t));
return(FALSE);
}
@@ -132,7 +132,7 @@
return(FALSE);
}
-
+
return(TRUE);
}
@@ -154,13 +154,13 @@
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0)
- && (block->io_fix == 0)) {
- if (flush_type != BUF_FLUSH_LRU) {
+ && (block->io_fix == 0)) {
+ if (flush_type != BUF_FLUSH_LRU) {
return(TRUE);
} else if (block->buf_fix_count == 0) {
-
+
/* If we are flushing the LRU list, to avoid deadlocks
we require the block not to be bufferfixed, and hence
not latched. */
@@ -168,7 +168,7 @@
return(TRUE);
}
}
-
+
return(FALSE);
}
@@ -204,7 +204,7 @@
}
/* fprintf(stderr, "n pending flush %lu\n",
- buf_pool->n_flush[block->flush_type]); */
+ buf_pool->n_flush[block->flush_type]); */
if ((buf_pool->n_flush[block->flush_type] == 0)
&& (buf_pool->init_flush[block->flush_type] == FALSE)) {
@@ -237,7 +237,7 @@
return;
}
-
+
mutex_enter(&(trx_doublewrite->mutex));
/* Write first to doublewrite buffer blocks. We use synchronous
@@ -254,87 +254,100 @@
for (i = 0; i < trx_doublewrite->first_free; i++) {
block = trx_doublewrite->buf_block_arr[i];
- ut_a(block->state == BUF_BLOCK_FILE_PAGE);
+ ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if (mach_read_from_4(block->frame + FIL_PAGE_LSN + 4)
- != mach_read_from_4(block->frame + UNIV_PAGE_SIZE
- - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: ERROR: The page to be written seems corrupt!\n"
-"InnoDB: The lsn fields do not match! Noticed in the buffer pool\n"
-"InnoDB: before posting to the doublewrite buffer.\n");
- }
+ != mach_read_from_4(block->frame + UNIV_PAGE_SIZE
+ - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: ERROR: The page to be written"
+ " seems corrupt!\n"
+ "InnoDB: The lsn fields do not match!"
+ " Noticed in the buffer pool\n"
+ "InnoDB: before posting to the"
+ " doublewrite buffer.\n");
+ }
if (block->check_index_page_at_flush
- && !page_simple_validate(block->frame)) {
+ && !page_simple_validate(block->frame)) {
buf_page_print(block->frame);
ut_print_timestamp(stderr);
fprintf(stderr,
- " InnoDB: Apparent corruption of an index page n:o %lu in space %lu\n"
- "InnoDB: to be written to data file. We intentionally crash server\n"
- "InnoDB: to prevent corrupt data from ending up in data\n"
- "InnoDB: files.\n",
- (ulong) block->offset, (ulong) block->space);
+ " InnoDB: Apparent corruption of an"
+ " index page n:o %lu in space %lu\n"
+ "InnoDB: to be written to data file."
+ " We intentionally crash server\n"
+ "InnoDB: to prevent corrupt data"
+ " from ending up in data\n"
+ "InnoDB: files.\n",
+ (ulong) block->offset, (ulong) block->space);
ut_error;
}
}
- /* increment the doublewrite flushed pages counter */
- srv_dblwr_pages_written+= trx_doublewrite->first_free;
- srv_dblwr_writes++;
-
+ /* increment the doublewrite flushed pages counter */
+ srv_dblwr_pages_written+= trx_doublewrite->first_free;
+ srv_dblwr_writes++;
+
if (trx_doublewrite->first_free > TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
len = TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE;
} else {
len = trx_doublewrite->first_free * UNIV_PAGE_SIZE;
}
-
+
fil_io(OS_FILE_WRITE,
- TRUE, TRX_SYS_SPACE,
- trx_doublewrite->block1, 0, len,
- (void*)trx_doublewrite->write_buf, NULL);
-
+ TRUE, TRX_SYS_SPACE,
+ trx_doublewrite->block1, 0, len,
+ (void*)trx_doublewrite->write_buf, NULL);
+
write_buf = trx_doublewrite->write_buf;
- for (len2 = 0; len2 + UNIV_PAGE_SIZE <= len; len2 += UNIV_PAGE_SIZE) {
- if (mach_read_from_4(write_buf + len2 + FIL_PAGE_LSN + 4)
- != mach_read_from_4(write_buf + len2 + UNIV_PAGE_SIZE
- - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
+ for (len2 = 0; len2 + UNIV_PAGE_SIZE <= len; len2 += UNIV_PAGE_SIZE) {
+ if (mach_read_from_4(write_buf + len2 + FIL_PAGE_LSN + 4)
+ != mach_read_from_4(write_buf + len2 + UNIV_PAGE_SIZE
+ - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
ut_print_timestamp(stderr);
fprintf(stderr,
-" InnoDB: ERROR: The page to be written seems corrupt!\n"
-"InnoDB: The lsn fields do not match! Noticed in the doublewrite block1.\n");
+ " InnoDB: ERROR: The page to be written"
+ " seems corrupt!\n"
+ "InnoDB: The lsn fields do not match!"
+ " Noticed in the doublewrite block1.\n");
}
}
if (trx_doublewrite->first_free > TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
len = (trx_doublewrite->first_free
- - TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) * UNIV_PAGE_SIZE;
-
+ - TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) * UNIV_PAGE_SIZE;
+
fil_io(OS_FILE_WRITE,
- TRUE, TRX_SYS_SPACE,
- trx_doublewrite->block2, 0, len,
- (void*)(trx_doublewrite->write_buf
- + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE),
- NULL);
+ TRUE, TRX_SYS_SPACE,
+ trx_doublewrite->block2, 0, len,
+ (void*)(trx_doublewrite->write_buf
+ + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
+ * UNIV_PAGE_SIZE),
+ NULL);
write_buf = trx_doublewrite->write_buf
- + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE;
+ + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE;
for (len2 = 0; len2 + UNIV_PAGE_SIZE <= len;
- len2 += UNIV_PAGE_SIZE) {
- if (mach_read_from_4(write_buf + len2
- + FIL_PAGE_LSN + 4)
- != mach_read_from_4(write_buf + len2
- + UNIV_PAGE_SIZE
- - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
+ len2 += UNIV_PAGE_SIZE) {
+ if (mach_read_from_4(write_buf + len2
+ + FIL_PAGE_LSN + 4)
+ != mach_read_from_4(write_buf + len2
+ + UNIV_PAGE_SIZE
+ - FIL_PAGE_END_LSN_OLD_CHKSUM
+ + 4)) {
ut_print_timestamp(stderr);
fprintf(stderr,
-" InnoDB: ERROR: The page to be written seems corrupt!\n"
-"InnoDB: The lsn fields do not match! Noticed in the doublewrite block2.\n");
+ " InnoDB: ERROR: The page to be"
+ " written seems corrupt!\n"
+ "InnoDB: The lsn fields do not match!"
+ " Noticed in"
+ " the doublewrite block2.\n");
}
}
}
@@ -351,32 +364,37 @@
block = trx_doublewrite->buf_block_arr[i];
if (mach_read_from_4(block->frame + FIL_PAGE_LSN + 4)
- != mach_read_from_4(block->frame + UNIV_PAGE_SIZE
- - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: ERROR: The page to be written seems corrupt!\n"
-"InnoDB: The lsn fields do not match! Noticed in the buffer pool\n"
-"InnoDB: after posting and flushing the doublewrite buffer.\n"
-"InnoDB: Page buf fix count %lu, io fix %lu, state %lu\n",
- (ulong)block->buf_fix_count, (ulong)block->io_fix,
- (ulong)block->state);
- }
+ != mach_read_from_4(block->frame + UNIV_PAGE_SIZE
+ - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: ERROR: The page to be written"
+ " seems corrupt!\n"
+ "InnoDB: The lsn fields do not match!"
+ " Noticed in the buffer pool\n"
+ "InnoDB: after posting and flushing"
+ " the doublewrite buffer.\n"
+ "InnoDB: Page buf fix count %lu,"
+ " io fix %lu, state %lu\n",
+ (ulong)block->buf_fix_count,
+ (ulong)block->io_fix,
+ (ulong)block->state);
+ }
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER,
- FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE,
- (void*)block->frame, (void*)block);
+ FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE,
+ (void*)block->frame, (void*)block);
}
-
+
/* Wake possible simulated aio thread to actually post the
writes to the operating system */
os_aio_simulated_wake_handler_threads();
/* Wait that all async writes to tablespaces have been posted to
- the OS */
-
+ the OS */
+
os_aio_wait_until_no_pending_writes();
/* Now we flush the data to disk (for example, with fsync) */
@@ -387,7 +405,7 @@
trx_doublewrite->first_free = 0;
- mutex_exit(&(trx_doublewrite->mutex));
+ mutex_exit(&(trx_doublewrite->mutex));
}
/************************************************************************
@@ -406,7 +424,7 @@
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if (trx_doublewrite->first_free
- >= 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
+ >= 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
mutex_exit(&(trx_doublewrite->mutex));
buf_flush_buffered_writes();
@@ -415,15 +433,15 @@
}
ut_memcpy(trx_doublewrite->write_buf
- + UNIV_PAGE_SIZE * trx_doublewrite->first_free,
- block->frame, UNIV_PAGE_SIZE);
+ + UNIV_PAGE_SIZE * trx_doublewrite->first_free,
+ block->frame, UNIV_PAGE_SIZE);
trx_doublewrite->buf_block_arr[trx_doublewrite->first_free] = block;
trx_doublewrite->first_free++;
if (trx_doublewrite->first_free
- >= 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
+ >= 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
mutex_exit(&(trx_doublewrite->mutex));
buf_flush_buffered_writes();
@@ -444,22 +462,23 @@
dulint newest_lsn, /* in: newest modification lsn to the page */
ulint space, /* in: space id */
ulint page_no) /* in: page number */
-{
+{
/* Write the newest modification lsn to the page header and trailer */
mach_write_to_8(page + FIL_PAGE_LSN, newest_lsn);
mach_write_to_8(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
- newest_lsn);
+ newest_lsn);
/* Write the page number and the space id */
mach_write_to_4(page + FIL_PAGE_OFFSET, page_no);
- mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space);
+ mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, space);
/* Store the new formula checksum */
mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM,
- srv_use_checksums ?
- buf_calc_page_new_checksum(page) : BUF_NO_CHECKSUM_MAGIC);
+ srv_use_checksums
+ ? buf_calc_page_new_checksum(page)
+ : BUF_NO_CHECKSUM_MAGIC);
/* We overwrite the first 4 bytes of the end lsn field to store
the old formula checksum. Since it depends also on the field
@@ -467,8 +486,9 @@
new formula checksum. */
mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
- srv_use_checksums ?
- buf_calc_page_old_checksum(page) : BUF_NO_CHECKSUM_MAGIC);
+ srv_use_checksums
+ ? buf_calc_page_old_checksum(page)
+ : BUF_NO_CHECKSUM_MAGIC);
}
/************************************************************************
@@ -494,21 +514,21 @@
#ifdef UNIV_LOG_DEBUG
if (!univ_log_debug_warned) {
univ_log_debug_warned = TRUE;
- fputs(
- "Warning: cannot force log to disk if UNIV_LOG_DEBUG is defined!\n"
- "Crash recovery will not work!\n",
- stderr);
+ fputs("Warning: cannot force log to disk if"
+ " UNIV_LOG_DEBUG is defined!\n"
+ "Crash recovery will not work!\n",
+ stderr);
}
#else
/* Force the log to the disk before writing the modified block */
log_write_up_to(block->newest_modification, LOG_WAIT_ALL_GROUPS, TRUE);
-#endif
+#endif
buf_flush_init_for_writing(block->frame, block->newest_modification,
- block->space, block->offset);
+ block->space, block->offset);
if (!srv_use_doublewrite_buf || !trx_doublewrite) {
fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER,
- FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE,
- (void*)block->frame, (void*)block);
+ FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE,
+ (void*)block->frame, (void*)block);
} else {
buf_flush_post_to_doublewrite_buf(block);
}
@@ -531,9 +551,9 @@
{
buf_block_t* block;
ibool locked;
-
+
ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST
- || flush_type == BUF_FLUSH_SINGLE_PAGE);
+ || flush_type == BUF_FLUSH_SINGLE_PAGE);
mutex_enter(&(buf_pool->mutex));
@@ -550,7 +570,7 @@
if (flush_type == BUF_FLUSH_LIST
&& buf_flush_ready_for_flush(block, flush_type)) {
-
+
block->io_fix = BUF_IO_WRITE;
/* If AWE is enabled and the page is not mapped to a frame,
@@ -562,7 +582,7 @@
/* We set second parameter TRUE because the block is
in the LRU list and we must put it to
awe_LRU_free_mapped list once mapped to a frame */
-
+
buf_awe_map_page_to_frame(block, TRUE);
}
@@ -576,7 +596,7 @@
(buf_pool->n_flush[flush_type])++;
locked = FALSE;
-
+
/* If the simulated aio thread is not running, we must
not wait for any latch, as we may end up in a deadlock:
if buf_fix_count == 0, then we know we need not wait */
@@ -605,7 +625,7 @@
#endif /* UNIV_DEBUG */
buf_flush_write_block_low(block);
-
+
return(1);
} else if (flush_type == BUF_FLUSH_LRU
@@ -630,7 +650,7 @@
/* We set second parameter TRUE because the block is
in the LRU list and we must put it to
awe_LRU_free_mapped list once mapped to a frame */
-
+
buf_awe_map_page_to_frame(block, TRUE);
}
@@ -648,7 +668,7 @@
/* Note that the s-latch is acquired before releasing the
buf_pool mutex: this ensures that the latch is acquired
immediately. */
-
+
mutex_exit(&block->mutex);
mutex_exit(&(buf_pool->mutex));
@@ -658,7 +678,7 @@
} else if (flush_type == BUF_FLUSH_SINGLE_PAGE
&& buf_flush_ready_for_flush(block, flush_type)) {
-
+
block->io_fix = BUF_IO_WRITE;
/* If AWE is enabled and the page is not mapped to a frame,
@@ -670,7 +690,7 @@
/* We set second parameter TRUE because the block is
in the LRU list and we must put it to
awe_LRU_free_mapped list once mapped to a frame */
-
+
buf_awe_map_page_to_frame(block, TRUE);
}
@@ -691,14 +711,15 @@
#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr,
- "Flushing single page space %lu, page no %lu \n",
- (ulong) block->space,
- (ulong) block->offset);
+ "Flushing single page space %lu,"
+ " page no %lu \n",
+ (ulong) block->space,
+ (ulong) block->offset);
}
#endif /* UNIV_DEBUG */
buf_flush_write_block_low(block);
-
+
return(1);
}
@@ -732,13 +753,13 @@
if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN) {
/* If there is little space, it is better not to flush any
block except from the end of the LRU list */
-
+
low = offset;
high = offset + 1;
}
/* fprintf(stderr, "Flush area: low %lu high %lu\n", low, high); */
-
+
if (high > fil_space_get_size(space)) {
high = fil_space_get_size(space);
}
@@ -757,10 +778,10 @@
} else if (flush_type == BUF_FLUSH_LRU && i != offset
&& !block->old) {
- /* We avoid flushing 'non-old' blocks in an LRU flush,
- because the flushed blocks are soon freed */
+ /* We avoid flushing 'non-old' blocks in an LRU flush,
+ because the flushed blocks are soon freed */
- continue;
+ continue;
} else {
mutex_enter(&block->mutex);
@@ -794,7 +815,7 @@
}
}
}
-
+
mutex_exit(&(buf_pool->mutex));
return(count);
@@ -825,64 +846,66 @@
exceed min_n), otherwise ignored */
{
buf_block_t* block;
- ulint page_count = 0;
+ ulint page_count = 0;
ulint old_page_count;
ulint space;
ulint offset;
ibool found;
-
+
ut_ad((flush_type == BUF_FLUSH_LRU)
- || (flush_type == BUF_FLUSH_LIST));
+ || (flush_type == BUF_FLUSH_LIST));
+#ifdef UNIV_SYNC_DEBUG
ut_ad((flush_type != BUF_FLUSH_LIST)
- || sync_thread_levels_empty_gen(TRUE));
+ || sync_thread_levels_empty_gen(TRUE));
+#endif /* UNIV_SYNC_DEBUG */
mutex_enter(&(buf_pool->mutex));
if ((buf_pool->n_flush[flush_type] > 0)
|| (buf_pool->init_flush[flush_type] == TRUE)) {
/* There is already a flush batch of the same type running */
-
+
mutex_exit(&(buf_pool->mutex));
return(ULINT_UNDEFINED);
}
(buf_pool->init_flush)[flush_type] = TRUE;
-
+
for (;;) {
/* If we have flushed enough, leave the loop */
if (page_count >= min_n) {
break;
}
-
+
/* Start from the end of the list looking for a suitable
block to be flushed. */
-
- if (flush_type == BUF_FLUSH_LRU) {
+
+ if (flush_type == BUF_FLUSH_LRU) {
block = UT_LIST_GET_LAST(buf_pool->LRU);
- } else {
+ } else {
ut_ad(flush_type == BUF_FLUSH_LIST);
block = UT_LIST_GET_LAST(buf_pool->flush_list);
if (!block
|| (ut_dulint_cmp(block->oldest_modification,
- lsn_limit) >= 0)) {
+ lsn_limit) >= 0)) {
/* We have flushed enough */
break;
}
- }
-
- found = FALSE;
-
+ }
+
+ found = FALSE;
+
/* Note that after finding a single flushable page, we try to
flush also all its neighbors, and after that start from the
END of the LRU list or flush list again: the list may change
during the flushing and we cannot safely preserve within this
function a pointer to a block in the list! */
- while ((block != NULL) && !found) {
+ while ((block != NULL) && !found) {
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
mutex_enter(&block->mutex);
@@ -892,16 +915,15 @@
found = TRUE;
space = block->space;
offset = block->offset;
-
+
mutex_exit(&block->mutex);
mutex_exit(&(buf_pool->mutex));
old_page_count = page_count;
-
+
/* Try to flush also all the neighbors */
- page_count +=
- buf_flush_try_neighbors(space, offset,
- flush_type);
+ page_count += buf_flush_try_neighbors(
+ space, offset, flush_type);
/* fprintf(stderr,
"Flush type %lu, page no %lu, neighb %lu\n",
flush_type, offset,
@@ -921,13 +943,13 @@
block = UT_LIST_GET_PREV(flush_list, block);
}
- }
+ }
- /* If we could not find anything to flush, leave the loop */
+ /* If we could not find anything to flush, leave the loop */
- if (!found) {
- break;
- }
+ if (!found) {
+ break;
+ }
}
(buf_pool->init_flush)[flush_type] = FALSE;
@@ -947,16 +969,16 @@
#ifdef UNIV_DEBUG
if (buf_debug_prints && page_count > 0) {
ut_a(flush_type == BUF_FLUSH_LRU
- || flush_type == BUF_FLUSH_LIST);
+ || flush_type == BUF_FLUSH_LIST);
fprintf(stderr, flush_type == BUF_FLUSH_LRU
? "Flushed %lu pages in LRU flush\n"
: "Flushed %lu pages in flush list flush\n",
(ulong) page_count);
}
#endif /* UNIV_DEBUG */
-
- if (page_count != ULINT_UNDEFINED)
- srv_buf_pool_flushed+= page_count;
+
+ if (page_count != ULINT_UNDEFINED)
+ srv_buf_pool_flushed+= page_count;
return(page_count);
}
@@ -970,9 +992,9 @@
ulint type) /* in: BUF_FLUSH_LRU or BUF_FLUSH_LIST */
{
ut_ad((type == BUF_FLUSH_LRU) || (type == BUF_FLUSH_LIST));
-
+
os_event_wait(buf_pool->no_flush[type]);
-}
+}
/**********************************************************************
Gives a recommendation of how many blocks should be flushed to establish
@@ -988,7 +1010,7 @@
buf_block_t* block;
ulint n_replaceable;
ulint distance = 0;
-
+
mutex_enter(&(buf_pool->mutex));
n_replaceable = UT_LIST_GET_LEN(buf_pool->free);
@@ -997,7 +1019,7 @@
while ((block != NULL)
&& (n_replaceable < BUF_FLUSH_FREE_BLOCK_MARGIN
- + BUF_FLUSH_EXTRA_MARGIN)
+ + BUF_FLUSH_EXTRA_MARGIN)
&& (distance < BUF_LRU_FREE_SEARCH_LEN)) {
mutex_enter(&block->mutex);
@@ -1009,19 +1031,19 @@
mutex_exit(&block->mutex);
distance++;
-
+
block = UT_LIST_GET_PREV(LRU, block);
}
-
+
mutex_exit(&(buf_pool->mutex));
if (n_replaceable >= BUF_FLUSH_FREE_BLOCK_MARGIN) {
return(0);
}
-
+
return(BUF_FLUSH_FREE_BLOCK_MARGIN + BUF_FLUSH_EXTRA_MARGIN
- - n_replaceable);
+ - n_replaceable);
}
/*************************************************************************
@@ -1029,7 +1051,7 @@
of replaceable pages there or in the free list. VERY IMPORTANT: this function
is called also by threads which have locks on pages. To avoid deadlocks, we
flush only pages such that the s-lock required for flushing can be acquired
-immediately, without waiting. */
+immediately, without waiting. */
void
buf_flush_free_margin(void)
@@ -1039,15 +1061,15 @@
ulint n_flushed;
n_to_flush = buf_flush_LRU_recommendation();
-
+
if (n_to_flush > 0) {
n_flushed = buf_flush_batch(BUF_FLUSH_LRU, n_to_flush,
- ut_dulint_zero);
+ ut_dulint_zero);
if (n_flushed == ULINT_UNDEFINED) {
/* There was an LRU type flush batch already running;
let us wait for it to end */
-
- buf_flush_wait_batch_end(BUF_FLUSH_LRU);
+
+ buf_flush_wait_batch_end(BUF_FLUSH_LRU);
}
}
}
@@ -1062,7 +1084,7 @@
{
buf_block_t* block;
dulint om;
-
+
UT_LIST_VALIDATE(flush_list, buf_block_t, buf_pool->flush_list);
block = UT_LIST_GET_FIRST(buf_pool->flush_list);
@@ -1071,12 +1093,12 @@
om = block->oldest_modification;
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_a(ut_dulint_cmp(om, ut_dulint_zero) > 0);
-
+
block = UT_LIST_GET_NEXT(flush_list, block);
if (block) {
ut_a(ut_dulint_cmp(om, block->oldest_modification)
- >= 0);
+ >= 0);
}
}
@@ -1092,11 +1114,11 @@
/* out: TRUE if ok */
{
ibool ret;
-
+
mutex_enter(&(buf_pool->mutex));
ret = buf_flush_validate_low();
-
+
mutex_exit(&(buf_pool->mutex));
return(ret);
--- 1.24.4.1/innobase/buf/buf0lru.c 2007-01-17 16:44:04 -07:00
+++ 1.34/storage/innobase/buf/buf0lru.c 2007-01-17 17:18:03 -07:00
@@ -80,16 +80,18 @@
scan_again:
mutex_enter(&(buf_pool->mutex));
-
+
all_freed = TRUE;
-
+
block = UT_LIST_GET_LAST(buf_pool->LRU);
while (block != NULL) {
+ buf_block_t* prev_block;
mutex_enter(&block->mutex);
+ prev_block = UT_LIST_GET_PREV(LRU, block);
- ut_a(block->state == BUF_BLOCK_FILE_PAGE);
+ ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if (block->space == id
&& (block->buf_fix_count > 0 || block->io_fix != 0)) {
@@ -97,7 +99,7 @@
/* We cannot remove this page during this scan yet;
maybe the system is currently reading it in, or
flushing the modifications to the file */
-
+
all_freed = FALSE;
goto next_page;
@@ -106,15 +108,15 @@
if (block->space == id) {
#ifdef UNIV_DEBUG
if (buf_debug_prints) {
- printf(
- "Dropping space %lu page %lu\n",
+ fprintf(stderr,
+ "Dropping space %lu page %lu\n",
(ulong) block->space,
- (ulong) block->offset);
+ (ulong) block->offset);
}
#endif
if (block->is_hashed) {
page_no = block->offset;
-
+
mutex_exit(&block->mutex);
mutex_exit(&(buf_pool->mutex));
@@ -123,19 +125,19 @@
an S-latch on the page */
btr_search_drop_page_hash_when_freed(id,
- page_no);
+ page_no);
goto scan_again;
}
if (0 != ut_dulint_cmp(block->oldest_modification,
- ut_dulint_zero)) {
+ ut_dulint_zero)) {
/* Remove from the flush list of modified
blocks */
block->oldest_modification = ut_dulint_zero;
- UT_LIST_REMOVE(flush_list,
- buf_pool->flush_list, block);
+ UT_LIST_REMOVE(flush_list,
+ buf_pool->flush_list, block);
}
/* Remove from the LRU list */
@@ -144,15 +146,15 @@
}
next_page:
mutex_exit(&block->mutex);
- block = UT_LIST_GET_PREV(LRU, block);
+ block = prev_block;
}
mutex_exit(&(buf_pool->mutex));
-
+
if (!all_freed) {
os_thread_sleep(20000);
- goto scan_again;
+ goto scan_again;
}
}
@@ -199,7 +201,7 @@
buf_LRU_search_and_free_block(
/*==========================*/
/* out: TRUE if freed */
- ulint n_iterations) /* in: how many times this has been called
+ ulint n_iterations) /* in: how many times this has been called
repeatedly without result: a high value means
that we should search farther; if value is
k < 10, then we only search k/10 * [number
@@ -211,12 +213,12 @@
ibool freed;
mutex_enter(&(buf_pool->mutex));
-
+
freed = FALSE;
block = UT_LIST_GET_LAST(buf_pool->LRU);
while (block != NULL) {
- ut_a(block->in_LRU_list);
+ ut_a(block->in_LRU_list);
mutex_enter(&block->mutex);
@@ -225,9 +227,10 @@
#ifdef UNIV_DEBUG
if (buf_debug_prints) {
fprintf(stderr,
- "Putting space %lu page %lu to free list\n",
+ "Putting space %lu page %lu"
+ " to free list\n",
(ulong) block->space,
- (ulong) block->offset);
+ (ulong) block->offset);
}
#endif /* UNIV_DEBUG */
@@ -239,7 +242,7 @@
/* Remove possible adaptive hash index built on the
page; in the case of AWE the block may not have a
frame at all */
-
+
if (block->frame) {
btr_search_drop_page_hash_index(block->frame);
}
@@ -263,25 +266,25 @@
if (!freed && n_iterations <= 10
&& distance > 100 + (n_iterations * buf_pool->curr_size)
- / 10) {
+ / 10) {
buf_pool->LRU_flush_ended = 0;
mutex_exit(&(buf_pool->mutex));
-
+
return(FALSE);
}
}
if (buf_pool->LRU_flush_ended > 0) {
buf_pool->LRU_flush_ended--;
}
- if (!freed) {
+ if (!freed) {
buf_pool->LRU_flush_ended = 0;
}
mutex_exit(&(buf_pool->mutex));
-
+
return(freed);
}
-
+
/**********************************************************************
Tries to remove LRU flushed blocks from the end of the LRU list and put them
to the free list. This is beneficial for the efficiency of the insert buffer
@@ -302,12 +305,12 @@
mutex_exit(&(buf_pool->mutex));
buf_LRU_search_and_free_block(1);
-
+
mutex_enter(&(buf_pool->mutex));
}
mutex_exit(&(buf_pool->mutex));
-}
+}
/**********************************************************************
Returns TRUE if less than 25 % of the buffer pool is available. This can be
@@ -325,8 +328,8 @@
mutex_enter(&(buf_pool->mutex));
if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
- + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) {
-
+ + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) {
+
ret = TRUE;
}
@@ -350,29 +353,34 @@
buf_block_t* block = NULL;
ibool freed;
ulint n_iterations = 1;
- ibool mon_value_was = FALSE;
+ ibool mon_value_was = FALSE;
ibool started_monitor = FALSE;
loop:
mutex_enter(&(buf_pool->mutex));
if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
- + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 20) {
- ut_print_timestamp(stderr);
+ + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 20) {
+ ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: ERROR: over 95 percent of the buffer pool is occupied by\n"
-"InnoDB: lock heaps or the adaptive hash index! Check that your\n"
-"InnoDB: transactions do not set too many row locks.\n"
-"InnoDB: Your buffer pool size is %lu MB. Maybe you should make\n"
-"InnoDB: the buffer pool bigger?\n"
-"InnoDB: We intentionally generate a seg fault to print a stack trace\n"
-"InnoDB: on Linux!\n",
- (ulong)(buf_pool->curr_size / (1024 * 1024 / UNIV_PAGE_SIZE)));
+ fprintf(stderr,
+ " InnoDB: ERROR: over 95 percent of the buffer pool"
+ " is occupied by\n"
+ "InnoDB: lock heaps or the adaptive hash index!"
+ " Check that your\n"
+ "InnoDB: transactions do not set too many row locks.\n"
+ "InnoDB: Your buffer pool size is %lu MB."
+ " Maybe you should make\n"
+ "InnoDB: the buffer pool bigger?\n"
+ "InnoDB: We intentionally generate a seg fault"
+ " to print a stack trace\n"
+ "InnoDB: on Linux!\n",
+ (ulong) (buf_pool->curr_size
+ / (1024 * 1024 / UNIV_PAGE_SIZE)));
ut_error;
-
+
} else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
- + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 3) {
+ + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 3) {
if (!buf_lru_switched_on_innodb_mon) {
@@ -380,16 +388,22 @@
heaps or the adaptive hash index. This may be a memory
leak! */
- ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: WARNING: over 67 percent of the buffer pool is occupied by\n"
-"InnoDB: lock heaps or the adaptive hash index! Check that your\n"
-"InnoDB: transactions do not set too many row locks.\n"
-"InnoDB: Your buffer pool size is %lu MB. Maybe you should make\n"
-"InnoDB: the buffer pool bigger?\n"
-"InnoDB: Starting the InnoDB Monitor to print diagnostics, including\n"
-"InnoDB: lock heap and hash index sizes.\n",
- (ulong) (buf_pool->curr_size / (1024 * 1024 / UNIV_PAGE_SIZE)));
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: WARNING: over 67 percent of"
+ " the buffer pool is occupied by\n"
+ "InnoDB: lock heaps or the adaptive"
+ " hash index! Check that your\n"
+ "InnoDB: transactions do not set too many"
+ " row locks.\n"
+ "InnoDB: Your buffer pool size is %lu MB."
+ " Maybe you should make\n"
+ "InnoDB: the buffer pool bigger?\n"
+ "InnoDB: Starting the InnoDB Monitor to print"
+ " diagnostics, including\n"
+ "InnoDB: lock heap and hash index sizes.\n",
+ (ulong) (buf_pool->curr_size
+ / (1024 * 1024 / UNIV_PAGE_SIZE)));
buf_lru_switched_on_innodb_mon = TRUE;
srv_print_innodb_monitor = TRUE;
@@ -405,23 +419,24 @@
buf_lru_switched_on_innodb_mon = FALSE;
srv_print_innodb_monitor = FALSE;
}
-
+
/* If there is a block in the free list, take it */
if (UT_LIST_GET_LEN(buf_pool->free) > 0) {
-
+
block = UT_LIST_GET_FIRST(buf_pool->free);
ut_a(block->in_free_list);
UT_LIST_REMOVE(free, buf_pool->free, block);
block->in_free_list = FALSE;
ut_a(block->state != BUF_BLOCK_FILE_PAGE);
- ut_a(!block->in_LRU_list);
+ ut_a(!block->in_LRU_list);
if (srv_use_awe) {
if (block->frame) {
/* Remove from the list of mapped pages */
-
+
UT_LIST_REMOVE(awe_LRU_free_mapped,
- buf_pool->awe_LRU_free_mapped, block);
+ buf_pool->awe_LRU_free_mapped,
+ block);
} else {
/* We map the page to a frame; second param
FALSE below because we do not want it to be
@@ -430,7 +445,7 @@
buf_awe_map_page_to_frame(block, FALSE);
}
}
-
+
mutex_enter(&block->mutex);
block->state = BUF_BLOCK_READY_FOR_USE;
@@ -441,11 +456,11 @@
if (started_monitor) {
srv_print_innodb_monitor = mon_value_was;
- }
+ }
return(block);
}
-
+
/* If no block was in the free list, search from the end of the LRU
list and try to free a block there */
@@ -460,23 +475,30 @@
if (n_iterations > 30) {
ut_print_timestamp(stderr);
fprintf(stderr,
- "InnoDB: Warning: difficult to find free blocks from\n"
- "InnoDB: the buffer pool (%lu search iterations)! Consider\n"
- "InnoDB: increasing the buffer pool size.\n"
- "InnoDB: It is also possible that in your Unix version\n"
- "InnoDB: fsync is very slow, or completely frozen inside\n"
- "InnoDB: the OS kernel. Then upgrading to a newer version\n"
- "InnoDB: of your operating system may help. Look at the\n"
- "InnoDB: number of fsyncs in diagnostic info below.\n"
- "InnoDB: Pending flushes (fsync) log: %lu; buffer pool: %lu\n"
- "InnoDB: %lu OS file reads, %lu OS file writes, %lu OS fsyncs\n"
- "InnoDB: Starting InnoDB Monitor to print further\n"
- "InnoDB: diagnostics to the standard output.\n",
+ "InnoDB: Warning: difficult to find free blocks from\n"
+ "InnoDB: the buffer pool (%lu search iterations)!"
+ " Consider\n"
+ "InnoDB: increasing the buffer pool size.\n"
+ "InnoDB: It is also possible that"
+ " in your Unix version\n"
+ "InnoDB: fsync is very slow, or"
+ " completely frozen inside\n"
+ "InnoDB: the OS kernel. Then upgrading to"
+ " a newer version\n"
+ "InnoDB: of your operating system may help."
+ " Look at the\n"
+ "InnoDB: number of fsyncs in diagnostic info below.\n"
+ "InnoDB: Pending flushes (fsync) log: %lu;"
+ " buffer pool: %lu\n"
+ "InnoDB: %lu OS file reads, %lu OS file writes,"
+ " %lu OS fsyncs\n"
+ "InnoDB: Starting InnoDB Monitor to print further\n"
+ "InnoDB: diagnostics to the standard output.\n",
(ulong) n_iterations,
(ulong) fil_n_pending_log_flushes,
(ulong) fil_n_pending_tablespace_flushes,
(ulong) os_n_file_reads, (ulong) os_n_file_writes,
- (ulong) os_n_fsyncs);
+ (ulong) os_n_fsyncs);
mon_value_was = srv_print_innodb_monitor;
started_monitor = TRUE;
@@ -487,7 +509,7 @@
/* No free block was found: try to flush the LRU list */
buf_flush_free_margin();
- ++srv_buf_pool_wait_free;
+ ++srv_buf_pool_wait_free;
os_aio_simulated_wake_handler_threads();
@@ -512,8 +534,8 @@
n_iterations++;
- goto loop;
-}
+ goto loop;
+}
/***********************************************************************
Moves the LRU_old pointer so that the length of the old blocks list
@@ -539,23 +561,23 @@
ut_a(buf_pool->LRU_old->in_LRU_list);
/* Update the LRU_old pointer if necessary */
-
+
if (old_len < new_len - BUF_LRU_OLD_TOLERANCE) {
-
- buf_pool->LRU_old = UT_LIST_GET_PREV(LRU,
- buf_pool->LRU_old);
+
+ buf_pool->LRU_old = UT_LIST_GET_PREV(
+ LRU, buf_pool->LRU_old);
(buf_pool->LRU_old)->old = TRUE;
buf_pool->LRU_old_len++;
} else if (old_len > new_len + BUF_LRU_OLD_TOLERANCE) {
(buf_pool->LRU_old)->old = FALSE;
- buf_pool->LRU_old = UT_LIST_GET_NEXT(LRU,
- buf_pool->LRU_old);
+ buf_pool->LRU_old = UT_LIST_GET_NEXT(
+ LRU, buf_pool->LRU_old);
buf_pool->LRU_old_len--;
} else {
ut_a(buf_pool->LRU_old); /* Check that we did not
- fall out of the LRU list */
+ fall out of the LRU list */
return;
}
}
@@ -581,16 +603,16 @@
while (block != NULL) {
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
- ut_a(block->in_LRU_list);
+ ut_a(block->in_LRU_list);
block->old = TRUE;
block = UT_LIST_GET_NEXT(LRU, block);
}
buf_pool->LRU_old = UT_LIST_GET_FIRST(buf_pool->LRU);
buf_pool->LRU_old_len = UT_LIST_GET_LEN(buf_pool->LRU);
-
+
buf_LRU_old_adjust_len();
-}
+}
/**********************************************************************
Removes a block from the LRU list. */
@@ -605,7 +627,7 @@
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
#endif /* UNIV_SYNC_DEBUG */
-
+
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_a(block->in_LRU_list);
@@ -631,10 +653,10 @@
if (srv_use_awe && block->frame) {
/* Remove from the list of mapped pages */
-
+
UT_LIST_REMOVE(awe_LRU_free_mapped,
- buf_pool->awe_LRU_free_mapped, block);
- }
+ buf_pool->awe_LRU_free_mapped, block);
+ }
/* If the LRU list is so short that LRU_old not defined, return */
if (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN) {
@@ -644,7 +666,7 @@
return;
}
- ut_ad(buf_pool->LRU_old);
+ ut_ad(buf_pool->LRU_old);
/* Update the LRU_old_len field if necessary */
if (block->old) {
@@ -654,7 +676,7 @@
/* Adjust the length of the old block list if necessary */
buf_LRU_old_adjust_len();
-}
+}
/**********************************************************************
Adds a block to the LRU list end. */
@@ -665,7 +687,7 @@
buf_block_t* block) /* in: control block */
{
buf_block_t* last_block;
-
+
ut_ad(buf_pool);
ut_ad(block);
#ifdef UNIV_SYNC_DEBUG
@@ -682,7 +704,7 @@
block->LRU_position = last_block->LRU_position;
} else {
block->LRU_position = buf_pool_clock_tic();
- }
+ }
ut_a(!block->in_LRU_list);
UT_LIST_ADD_LAST(LRU, buf_pool->LRU, block);
@@ -690,11 +712,11 @@
if (srv_use_awe && block->frame) {
/* Add to the list of mapped pages */
-
+
UT_LIST_ADD_LAST(awe_LRU_free_mapped,
- buf_pool->awe_LRU_free_mapped, block);
+ buf_pool->awe_LRU_free_mapped, block);
}
-
+
if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {
buf_pool->LRU_old_len++;
@@ -715,7 +737,7 @@
buf_LRU_old_init();
}
-}
+}
/**********************************************************************
Adds a block to the LRU list. */
@@ -730,7 +752,7 @@
the start, regardless of this parameter */
{
ulint cl;
-
+
ut_ad(buf_pool);
ut_ad(block);
#ifdef UNIV_SYNC_DEBUG
@@ -747,20 +769,20 @@
/* Add to the list of mapped pages; for simplicity we always
add to the start, even if the user would have set 'old'
TRUE */
-
+
UT_LIST_ADD_FIRST(awe_LRU_free_mapped,
- buf_pool->awe_LRU_free_mapped, block);
+ buf_pool->awe_LRU_free_mapped, block);
}
if (!old || (UT_LIST_GET_LEN(buf_pool->LRU) < BUF_LRU_OLD_MIN_LEN)) {
UT_LIST_ADD_FIRST(LRU, buf_pool->LRU, block);
- block->LRU_position = cl;
+ block->LRU_position = cl;
block->freed_page_clock = buf_pool->freed_page_clock;
} else {
UT_LIST_INSERT_AFTER(LRU, buf_pool->LRU, buf_pool->LRU_old,
- block);
+ block);
buf_pool->LRU_old_len++;
/* We copy the LRU position field of the previous block
@@ -785,8 +807,8 @@
defined: init it */
buf_LRU_old_init();
- }
-}
+ }
+}
/**********************************************************************
Adds a block to the LRU list. */
@@ -841,27 +863,27 @@
ut_ad(mutex_own(&block->mutex));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(block);
-
+
ut_a((block->state == BUF_BLOCK_MEMORY)
- || (block->state == BUF_BLOCK_READY_FOR_USE));
+ || (block->state == BUF_BLOCK_READY_FOR_USE));
ut_a(block->n_pointers == 0);
ut_a(!block->in_free_list);
block->state = BUF_BLOCK_NOT_USED;
-#ifdef UNIV_DEBUG
+#ifdef UNIV_DEBUG
/* Wipe contents of page to reveal possible stale pointers to it */
memset(block->frame, '\0', UNIV_PAGE_SIZE);
-#endif
+#endif
UT_LIST_ADD_FIRST(free, buf_pool->free, block);
block->in_free_list = TRUE;
if (srv_use_awe && block->frame) {
/* Add to the list of mapped pages */
-
+
UT_LIST_ADD_FIRST(awe_LRU_free_mapped,
- buf_pool->awe_LRU_free_mapped, block);
+ buf_pool->awe_LRU_free_mapped, block);
}
}
@@ -881,7 +903,7 @@
ut_ad(mutex_own(&block->mutex));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(block);
-
+
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_a(block->io_fix == 0);
ut_a(block->buf_fix_count == 0);
@@ -892,35 +914,40 @@
buf_pool->freed_page_clock += 1;
/* Note that if AWE is enabled the block may not have a frame at all */
-
- buf_block_modify_clock_inc(block);
-
- if (block != buf_page_hash_get(block->space, block->offset)) {
- fprintf(stderr,
-"InnoDB: Error: page %lu %lu not found from the hash table\n",
+
+ buf_block_modify_clock_inc(block);
+
+ if (block != buf_page_hash_get(block->space, block->offset)) {
+ fprintf(stderr,
+ "InnoDB: Error: page %lu %lu not found"
+ " in the hash table\n",
(ulong) block->space,
(ulong) block->offset);
- if (buf_page_hash_get(block->space, block->offset)) {
- fprintf(stderr,
-"InnoDB: From hash table we find block %p of %lu %lu which is not %p\n",
- buf_page_hash_get(block->space, block->offset),
- (ulong) buf_page_hash_get(block->space, block->offset)->space,
- (ulong) buf_page_hash_get(block->space, block->offset)->offset,
- block);
- }
+ if (buf_page_hash_get(block->space, block->offset)) {
+ fprintf(stderr,
+ "InnoDB: In hash table we find block"
+ " %p of %lu %lu which is not %p\n",
+ (void*) buf_page_hash_get
+ (block->space, block->offset),
+ (ulong) buf_page_hash_get
+ (block->space, block->offset)->space,
+ (ulong) buf_page_hash_get
+ (block->space, block->offset)->offset,
+ (void*) block);
+ }
#ifdef UNIV_DEBUG
- buf_print();
- buf_LRU_print();
- buf_validate();
- buf_LRU_validate();
+ buf_print();
+ buf_LRU_print();
+ buf_validate();
+ buf_LRU_validate();
#endif
- ut_a(0);
- }
+ ut_a(0);
+ }
HASH_DELETE(buf_block_t, hash, buf_pool->page_hash,
- buf_page_address_fold(block->space, block->offset),
- block);
+ buf_page_address_fold(block->space, block->offset),
+ block);
block->state = BUF_BLOCK_REMOVE_HASH;
}
@@ -957,7 +984,7 @@
ulint old_len;
ulint new_len;
ulint LRU_pos;
-
+
ut_ad(buf_pool);
mutex_enter(&(buf_pool->mutex));
@@ -969,7 +996,7 @@
ut_a(old_len >= new_len - BUF_LRU_OLD_TOLERANCE);
ut_a(old_len <= new_len + BUF_LRU_OLD_TOLERANCE);
}
-
+
UT_LIST_VALIDATE(LRU, buf_block_t, buf_pool->LRU);
block = UT_LIST_GET_FIRST(buf_pool->LRU);
@@ -1002,7 +1029,7 @@
if (buf_pool->LRU_old) {
ut_a(buf_pool->LRU_old_len == old_len);
- }
+ }
UT_LIST_VALIDATE(free, buf_block_t, buf_pool->free);
@@ -1028,11 +1055,12 @@
buf_block_t* block;
buf_frame_t* frame;
ulint len;
-
+
ut_ad(buf_pool);
mutex_enter(&(buf_pool->mutex));
- fprintf(stderr, "Pool ulint clock %lu\n", (ulong) buf_pool->ulint_clock);
+ fprintf(stderr, "Pool ulint clock %lu\n",
+ (ulong) buf_pool->ulint_clock);
block = UT_LIST_GET_FIRST(buf_pool->LRU);
@@ -1056,7 +1084,7 @@
}
if (ut_dulint_cmp(block->oldest_modification,
- ut_dulint_zero) > 0) {
+ ut_dulint_zero) > 0) {
fputs("modif. ", stderr);
}
@@ -1065,7 +1093,8 @@
fprintf(stderr, "LRU pos %lu type %lu index id %lu ",
(ulong) block->LRU_position,
(ulong) fil_page_get_type(frame),
- (ulong) ut_dulint_get_low(btr_page_get_index_id(frame)));
+ (ulong) ut_dulint_get_low
+ (btr_page_get_index_id(frame)));
block = UT_LIST_GET_NEXT(LRU, block);
if (++len == 10) {
--- 1.28.5.1/innobase/include/buf0buf.h 2007-01-17 16:44:04 -07:00
+++ 1.39/storage/innobase/include/buf0buf.h 2007-01-17 17:18:03 -07:00
@@ -1,14 +1,14 @@
/* Innobase relational database engine; Copyright (C) 2001 Innobase Oy
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License 2
as published by the Free Software Foundation in June 1991.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License 2
along with this program (in file COPYING); if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
@@ -55,14 +55,14 @@
/* Magic value to use instead of checksums when they are disabled */
#define BUF_NO_CHECKSUM_MAGIC 0xDEADBEEFUL
-extern buf_pool_t* buf_pool; /* The buffer pool of the database */
+extern buf_pool_t* buf_pool; /* The buffer pool of the database */
#ifdef UNIV_DEBUG
extern ibool buf_debug_prints;/* If this is set TRUE, the program
prints info whenever read or flush
occurs */
#endif /* UNIV_DEBUG */
extern ulint srv_buf_pool_write_requests; /* variable to count write request
- issued */
+ issued */
/************************************************************************
Creates the buffer pool. */
@@ -134,7 +134,7 @@
NOTE! The following macros should be used instead of buf_page_get_gen,
to improve debugging. Only values RW_S_LATCH and RW_X_LATCH are allowed
in LA! */
-#define buf_page_get(SP, OF, LA, MTR) buf_page_get_gen(\
+#define buf_page_get(SP, OF, LA, MTR) buf_page_get_gen(\
SP, OF, LA, NULL,\
BUF_GET, __FILE__, __LINE__, MTR)
/******************************************************************
@@ -143,21 +143,21 @@
the contents of the page! We have separated this case, because it is
error-prone programming not to set a latch, and it should be used
with care. */
-#define buf_page_get_with_no_latch(SP, OF, MTR) buf_page_get_gen(\
+#define buf_page_get_with_no_latch(SP, OF, MTR) buf_page_get_gen(\
SP, OF, RW_NO_LATCH, NULL,\
BUF_GET_NO_LATCH, __FILE__, __LINE__, MTR)
/******************************************************************
NOTE! The following macros should be used instead of buf_page_get_gen, to
improve debugging. Only values RW_S_LATCH and RW_X_LATCH are allowed as LA! */
-#define buf_page_get_nowait(SP, OF, LA, MTR) buf_page_get_gen(\
+#define buf_page_get_nowait(SP, OF, LA, MTR) buf_page_get_gen(\
SP, OF, LA, NULL,\
BUF_GET_NOWAIT, __FILE__, __LINE__, MTR)
/******************************************************************
NOTE! The following macros should be used instead of
buf_page_optimistic_get_func, to improve debugging. Only values RW_S_LATCH and
RW_X_LATCH are allowed as LA! */
-#define buf_page_optimistic_get(LA, BL, G, MC, MTR) buf_page_optimistic_get_func(\
- LA, BL, G, MC, __FILE__, __LINE__, MTR)
+#define buf_page_optimistic_get(LA, BL, G, MC, MTR) \
+ buf_page_optimistic_get_func(LA, BL, G, MC, __FILE__, __LINE__, MTR)
/************************************************************************
This is the general function used to get optimistic access to a database
page. */
@@ -266,7 +266,7 @@
void
buf_page_make_young(
-/*=================*/
+/*================*/
buf_frame_t* frame); /* in: buffer frame of a file page */
/************************************************************************
Returns TRUE if the page can be found in the buffer pool hash table. NOTE
@@ -380,7 +380,7 @@
/* out: new value */
buf_block_t* block); /* in: block */
/************************************************************************
-Returns the value of the modify clock. The caller must have an s-lock
+Returns the value of the modify clock. The caller must have an s-lock
or x-lock on the block. */
UNIV_INLINE
dulint
@@ -396,12 +396,12 @@
ulint
buf_calc_page_new_checksum(
/*=======================*/
- /* out: checksum */
- byte* page); /* in: buffer page */
+ /* out: checksum */
+ byte* page); /* in: buffer page */
/************************************************************************
In versions < 4.0.14 and < 4.1.1 there was a bug that the checksum only
looked at the first few bytes of the page. This calculates that old
-checksum.
+checksum.
NOTE: we must first store the new formula checksum to
FIL_PAGE_SPACE_OR_CHKSUM before calculating and storing this old checksum
because this takes that field as an input! */
@@ -409,8 +409,8 @@
ulint
buf_calc_page_old_checksum(
/*=======================*/
- /* out: checksum */
- byte* page); /* in: buffer page */
+ /* out: checksum */
+ byte* page); /* in: buffer page */
/************************************************************************
Checks if a page is corrupt. */
@@ -648,7 +648,7 @@
on the buffer frame. The io-handler must take care that the flag is cleared
and the lock released later. This is one of the functions which perform the
state transition NOT_USED => FILE_PAGE to a block (the other is
-buf_page_create). */
+buf_page_create). */
buf_block_t*
buf_page_init_for_read(
@@ -704,7 +704,7 @@
/*=======================*/
-
+
/* The buffer control block structure */
struct buf_block_struct{
@@ -832,19 +832,18 @@
/* 5. Hash search fields: NOTE that the first 4 fields are NOT
protected by any semaphore! */
-
+
ulint n_hash_helps; /* counter which controls building
of a new hash index for the page */
ulint n_fields; /* recommended prefix length for hash
search: number of full fields */
ulint n_bytes; /* recommended prefix: number of bytes
in an incomplete field */
- ulint side; /* BTR_SEARCH_LEFT_SIDE or
- BTR_SEARCH_RIGHT_SIDE, depending on
+ ibool left_side; /* TRUE or FALSE, depending on
whether the leftmost record of several
records with the same prefix should be
indexed in the hash index */
-
+
/* These 6 fields may only be modified when we have
an x-latch on btr_search_latch AND
a) we are holding an s-latch or x-latch on block->lock or
@@ -865,9 +864,7 @@
ulint curr_n_fields; /* prefix length for hash indexing:
number of full fields */
ulint curr_n_bytes; /* number of bytes in hash indexing */
- ulint curr_side; /* BTR_SEARCH_LEFT_SIDE or
- BTR_SEARCH_RIGHT_SIDE in hash
- indexing */
+ ibool curr_left_side; /* TRUE or FALSE in hash indexing */
dict_index_t* index; /* Index for which the adaptive
hash index has been created. */
/* 6. Debug fields */
@@ -877,9 +874,9 @@
an s-latch here; so we can use the
debug utilities in sync0rw */
#endif
- ibool file_page_was_freed;
- /* this is set to TRUE when fsp
- frees a page in buffer pool */
+ ibool file_page_was_freed;
+ /* this is set to TRUE when fsp
+ frees a page in buffer pool */
};
#define BUF_BLOCK_MAGIC_N 41526563
@@ -993,7 +990,7 @@
physical memory is mapped to a frame */
UT_LIST_BASE_NODE_T(buf_block_t) LRU;
/* base node of the LRU list */
- buf_block_t* LRU_old; /* pointer to the about 3/8 oldest
+ buf_block_t* LRU_old; /* pointer to the about 3/8 oldest
blocks in the LRU list; NULL if LRU
length less than BUF_LRU_OLD_MIN_LEN */
ulint LRU_old_len; /* length of the LRU list from
@@ -1035,8 +1032,8 @@
FILE_PAGE: space and offset are defined, is in page hash table
if io_fix == BUF_IO_WRITE,
pool: no_flush[block->flush_type] is in reset state,
- pool: n_flush[block->flush_type] > 0
-
+ pool: n_flush[block->flush_type] > 0
+
(1) if buf_fix_count == 0, then
is in LRU list, not in free list
is in flush list,
@@ -1045,23 +1042,23 @@
if and only if io_fix == BUF_IO_READ
is s-locked,
if and only if io_fix == BUF_IO_WRITE
-
+
(2) if buf_fix_count > 0, then
is not in LRU list, not in free list
is in flush list,
if and only if oldest_modification > 0
- if io_fix == BUF_IO_READ,
+ if io_fix == BUF_IO_READ,
is x-locked
if io_fix == BUF_IO_WRITE,
is s-locked
-
+
State transitions:
NOT_USED => READY_FOR_USE
READY_FOR_USE => MEMORY
READY_FOR_USE => FILE_PAGE
MEMORY => NOT_USED
-FILE_PAGE => NOT_USED NOTE: This transition is allowed if and only if
+FILE_PAGE => NOT_USED NOTE: This transition is allowed if and only if
(1) buf_fix_count == 0,
(2) oldest_modification == 0, and
(3) io_fix == 0.
--- 1.17.8.1/innobase/include/buf0buf.ic 2007-01-17 16:44:04 -07:00
+++ 1.30/storage/innobase/include/buf0buf.ic 2007-01-17 17:18:03 -07:00
@@ -28,7 +28,7 @@
buf_block_t* block) /* in: block to make younger */
{
return(buf_pool->freed_page_clock >= block->freed_page_clock
- + 1 + (buf_pool->curr_size / 1024));
+ + 1 + (buf_pool->curr_size / 1024));
}
/*************************************************************************
@@ -41,7 +41,7 @@
/* out: size in bytes */
{
return((buf_pool->n_frames) * UNIV_PAGE_SIZE);
-}
+}
/*************************************************************************
Gets the maximum size of buffer buf_pool in bytes. In the case of AWE, the
@@ -53,7 +53,7 @@
/* out: size in bytes */
{
return((buf_pool->n_frames) * UNIV_PAGE_SIZE);
-}
+}
/***********************************************************************
Accessor function for block array. */
@@ -69,7 +69,7 @@
ut_ad(i < buf_pool->max_size);
return(i + buf_pool->blocks);
-}
+}
/***********************************************************************
Checks if a pointer points to the block array of the buffer pool (blocks, not
@@ -82,13 +82,14 @@
void* ptr) /* in: pointer to memory */
{
if ((buf_pool->blocks <= (buf_block_t*)ptr)
- && ((buf_block_t*)ptr < buf_pool->blocks + buf_pool->max_size)) {
+ && ((buf_block_t*)ptr < buf_pool->blocks
+ + buf_pool->max_size)) {
return(TRUE);
}
return(FALSE);
-}
+}
/************************************************************************
Gets the smallest oldest_modification lsn for any page in the pool. Returns
@@ -102,7 +103,7 @@
{
buf_block_t* block;
dulint lsn;
-
+
mutex_enter(&(buf_pool->mutex));
block = UT_LIST_GET_LAST(buf_pool->flush_list);
@@ -130,7 +131,7 @@
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
#endif /* UNIV_SYNC_DEBUG */
-
+
buf_pool->ulint_clock++;
return(buf_pool->ulint_clock);
@@ -148,12 +149,12 @@
ut_ad(block);
ut_ad(block >= buf_pool->blocks);
ut_ad(block < buf_pool->blocks + buf_pool->max_size);
- ut_ad(block->state != BUF_BLOCK_NOT_USED);
- ut_ad((block->state != BUF_BLOCK_FILE_PAGE)
+ ut_ad(block->state != BUF_BLOCK_NOT_USED);
+ ut_ad((block->state != BUF_BLOCK_FILE_PAGE)
|| (block->buf_fix_count > 0));
-
+
return(block->frame);
-}
+}
/*************************************************************************
Gets the space id of a block. */
@@ -169,9 +170,9 @@
ut_ad(block < buf_pool->blocks + buf_pool->max_size);
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_ad(block->buf_fix_count > 0);
-
+
return(block->space);
-}
+}
/*************************************************************************
Gets the page number of a block. */
@@ -187,9 +188,9 @@
ut_ad(block < buf_pool->blocks + buf_pool->max_size);
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
ut_ad(block->buf_fix_count > 0);
-
+
return(block->offset);
-}
+}
/***********************************************************************
Gets the block to whose frame the pointer is pointing to. */
@@ -210,23 +211,26 @@
if (UNIV_UNLIKELY((ulint)ptr < (ulint)frame_zero)
|| UNIV_UNLIKELY((ulint)ptr > (ulint)(buf_pool->high_end))) {
- ut_print_timestamp(stderr);
+ ut_print_timestamp(stderr);
fprintf(stderr,
-"InnoDB: Error: trying to access a stray pointer %p\n"
-"InnoDB: buf pool start is at %p, end at %p\n"
-"InnoDB: Probable reason is database corruption or memory\n"
-"InnoDB: corruption. If this happens in an InnoDB database recovery, see\n"
-"InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html\n"
-"InnoDB: how to force recovery.\n",
- ptr, frame_zero,
+ "InnoDB: Error: trying to access a stray pointer %p\n"
+ "InnoDB: buf pool start is at %p, end at %p\n"
+ "InnoDB: Probable reason is database corruption"
+ " or memory\n"
+ "InnoDB: corruption. If this happens in an"
+ " InnoDB database recovery, see\n"
+ "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
+ "forcing-recovery.html\n"
+ "InnoDB: how to force recovery.\n",
+ ptr, frame_zero,
buf_pool->high_end);
ut_error;
}
-
+
block = *(buf_pool->blocks_of_frames + (((ulint)(ptr - frame_zero))
>> UNIV_PAGE_SIZE_SHIFT));
return(block);
-}
+}
/***********************************************************************
Gets the frame the pointer is pointing to. */
@@ -246,15 +250,18 @@
if (UNIV_UNLIKELY((ulint)frame < (ulint)(buf_pool->frame_zero))
|| UNIV_UNLIKELY((ulint)frame >= (ulint)(buf_pool->high_end))) {
- ut_print_timestamp(stderr);
+ ut_print_timestamp(stderr);
fprintf(stderr,
-"InnoDB: Error: trying to access a stray pointer %p\n"
-"InnoDB: buf pool start is at %p, end at %p\n"
-"InnoDB: Probable reason is database corruption or memory\n"
-"InnoDB: corruption. If this happens in an InnoDB database recovery, see\n"
-"InnoDB: http://dev.mysql.com/doc/refman/5.0/en/forcing-recovery.html\n"
-"InnoDB: how to force recovery.\n",
- ptr, buf_pool->frame_zero,
+ "InnoDB: Error: trying to access a stray pointer %p\n"
+ "InnoDB: buf pool start is at %p, end at %p\n"
+ "InnoDB: Probable reason is database corruption"
+ " or memory\n"
+ "InnoDB: corruption. If this happens in an"
+ " InnoDB database recovery, see\n"
+ "InnoDB: http://dev.mysql.com/doc/refman/5.1/en/"
+ "forcing-recovery.html\n"
+ "InnoDB: how to force recovery.\n",
+ ptr, buf_pool->frame_zero,
buf_pool->high_end);
ut_error;
}
@@ -371,7 +378,7 @@
ulint offset) /* in: offset of the page within space */
{
return((space << 20) + space + offset);
-}
+}
/************************************************************************
This function is used to get info if there is an io operation
@@ -411,7 +418,7 @@
{
buf_block_t* block;
dulint lsn;
-
+
ut_ad(frame);
block = buf_block_align(frame);
@@ -478,7 +485,7 @@
}
/************************************************************************
-Returns the value of the modify clock. The caller must have an s-lock
+Returns the value of the modify clock. The caller must have an s-lock
or x-lock on the block. */
UNIV_INLINE
dulint
@@ -506,7 +513,7 @@
const char* file __attribute__ ((unused)), /* in: file name */
ulint line __attribute__ ((unused))) /* in: line */
{
-#ifdef UNIV_SYNC_DEBUG
+#ifdef UNIV_SYNC_DEBUG
ibool ret;
ret = rw_lock_s_lock_func_nowait(&(block->debug_latch), file, line);
@@ -543,7 +550,7 @@
{
buf_block_t* block;
ulint fold;
-
+
ut_ad(buf_pool);
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(buf_pool->mutex)));
@@ -554,9 +561,9 @@
fold = buf_page_address_fold(space, offset);
HASH_SEARCH(hash, buf_pool->page_hash, fold, block,
- (block->space == space) && (block->offset == offset));
+ (block->space == space) && (block->offset == offset));
ut_a(block == NULL || block->state == BUF_BLOCK_FILE_PAGE);
-
+
return(block);
}
@@ -583,9 +590,9 @@
buf_frame_t* frame;
frame = buf_page_get_gen(space, offset, rw_latch, guess,
- BUF_GET_IF_IN_POOL,
- __FILE__, __LINE__,
- mtr);
+ BUF_GET_IF_IN_POOL,
+ __FILE__, __LINE__,
+ mtr);
if (frame != NULL) {
return(frame);
@@ -593,16 +600,16 @@
/* The page was not in the buffer buf_pool: release the latches
down to the savepoint */
-
+
mtr_rollback_to_savepoint(mtr, savepoint);
-
+
buf_page_get(space, offset, RW_S_LATCH, mtr);
-
+
/* When we get here, the page is in buffer, but we release
the latches again down to the savepoint, before returning */
mtr_rollback_to_savepoint(mtr, savepoint);
-
+
return(NULL);
}
@@ -618,8 +625,6 @@
RW_NO_LATCH */
mtr_t* mtr) /* in: mtr */
{
- ulint buf_fix_count;
-
ut_ad(block);
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
@@ -636,8 +641,7 @@
#ifdef UNIV_SYNC_DEBUG
rw_lock_s_unlock(&(block->debug_latch));
#endif
- buf_fix_count = block->buf_fix_count;
- block->buf_fix_count = buf_fix_count - 1;
+ block->buf_fix_count--;
mutex_exit(&block->mutex);
@@ -659,9 +663,9 @@
buf_page_dbg_add_level(
/*===================*/
buf_frame_t* frame __attribute__((unused)), /* in: buffer page
- where we have acquired latch */
+ where we have acquired latch */
ulint level __attribute__((unused))) /* in: latching order
- level */
+ level */
{
sync_thread_add_level(&(buf_block_align(frame)->lock), level);
}
--- 1.7.3.1/innobase/include/sync0arr.h 2007-01-17 16:44:04 -07:00
+++ 1.11/storage/innobase/include/sync0arr.h 2007-01-17 17:18:03 -07:00
@@ -14,7 +14,7 @@
#include "ut0mem.h"
#include "os0thread.h"
-typedef struct sync_cell_struct sync_cell_t;
+typedef struct sync_cell_struct sync_cell_t;
typedef struct sync_array_struct sync_array_t;
#define SYNC_ARRAY_OS_MUTEX 1
@@ -48,12 +48,12 @@
void
sync_array_reserve_cell(
/*====================*/
- sync_array_t* arr, /* in: wait array */
- void* object, /* in: pointer to the object to wait for */
- ulint type, /* in: lock request type */
+ sync_array_t* arr, /* in: wait array */
+ void* object, /* in: pointer to the object to wait for */
+ ulint type, /* in: lock request type */
const char* file, /* in: file where requested */
- ulint line, /* in: line where requested */
- ulint* index); /* out: index of the reserved cell */
+ ulint line, /* in: line where requested */
+ ulint* index); /* out: index of the reserved cell */
/**********************************************************************
This function should be called when a thread starts to wait on
a wait array cell. In the debug version this function checks
@@ -63,24 +63,29 @@
void
sync_array_wait_event(
/*==================*/
- sync_array_t* arr, /* in: wait array */
- ulint index); /* in: index of the reserved cell */
+ sync_array_t* arr, /* in: wait array */
+ ulint index); /* in: index of the reserved cell */
/**********************************************************************
-Frees the cell. NOTE! sync_array_wait_event frees the cell
-automatically! */
+Frees the cell safely by reserving the sync array mutex and decrementing
+n_reserved if necessary. Should only be called from mutex_spin_wait. */
void
-sync_array_free_cell(
-/*=================*/
+sync_array_free_cell_protected(
+/*===========================*/
sync_array_t* arr, /* in: wait array */
- ulint index); /* in: index of the cell in array */
+ ulint index); /* in: index of the cell in array */
/**************************************************************************
-Note that one of the wait objects was signalled. */
+Looks for the cells in the wait array which refer
+to the wait object specified,
+and sets their corresponding events to the signaled state. In this
+way releases the threads waiting for the object to contend for the object.
+It is possible that no such cell is found, in which case does nothing. */
void
-sync_array_object_signalled(
-/*========================*/
- sync_array_t* arr); /* in: wait array */
+sync_array_signal_object(
+/*=====================*/
+ sync_array_t* arr, /* in: wait array */
+ void* object);/* in: wait object */
/**************************************************************************
If the wakeup algorithm does not work perfectly at semaphore relases,
this function will do the waking (see the comment in mutex_exit). This
--- 1.11.3.1/innobase/include/sync0rw.h 2007-01-17 16:44:04 -07:00
+++ 1.21/storage/innobase/include/sync0rw.h 2007-01-17 17:18:03 -07:00
@@ -31,7 +31,7 @@
typedef UT_LIST_BASE_NODE_T(rw_lock_t) rw_lock_list_t;
-extern rw_lock_list_t rw_lock_list;
+extern rw_lock_list_t rw_lock_list;
extern mutex_t rw_lock_list_mutex;
#ifdef UNIV_SYNC_DEBUG
@@ -62,12 +62,18 @@
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. */
#ifdef UNIV_DEBUG
-# define rw_lock_create(L) rw_lock_create_func((L), #L, __FILE__, __LINE__)
+# ifdef UNIV_SYNC_DEBUG
+# define rw_lock_create(L, level) \
+ rw_lock_create_func((L), (level), #L, __FILE__, __LINE__)
+# else /* UNIV_SYNC_DEBUG */
+# define rw_lock_create(L, level) \
+ rw_lock_create_func((L), #L, __FILE__, __LINE__)
+# endif /* UNIV_SYNC_DEBUG */
#else /* UNIV_DEBUG */
-# define rw_lock_create(L) rw_lock_create_func((L), __FILE__, __LINE__)
+# define rw_lock_create(L, level) \
+ rw_lock_create_func((L), __FILE__, __LINE__)
#endif /* UNIV_DEBUG */
-/*=====================*/
/**********************************************************************
Creates, or rather, initializes an rw-lock object in a specified memory
location (which must be appropriately aligned). The rw-lock is initialized
@@ -79,10 +85,13 @@
/*================*/
rw_lock_t* lock, /* in: pointer to memory */
#ifdef UNIV_DEBUG
+# ifdef UNIV_SYNC_DEBUG
+ ulint level, /* in: level */
+# endif /* UNIV_SYNC_DEBUG */
const char* cmutex_name, /* in: mutex name */
#endif /* UNIV_DEBUG */
const char* cfile_name, /* in: file name where created */
- ulint cline); /* in: file line where created */
+ ulint cline); /* in: file line where created */
/**********************************************************************
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
@@ -104,20 +113,20 @@
NOTE! The following macros should be used in rw s-locking, not the
corresponding function. */
-#define rw_lock_s_lock(M) rw_lock_s_lock_func(\
- (M), 0, __FILE__, __LINE__)
+#define rw_lock_s_lock(M) rw_lock_s_lock_func(\
+ (M), 0, __FILE__, __LINE__)
/******************************************************************
NOTE! The following macros should be used in rw s-locking, not the
corresponding function. */
-#define rw_lock_s_lock_gen(M, P) rw_lock_s_lock_func(\
- (M), (P), __FILE__, __LINE__)
+#define rw_lock_s_lock_gen(M, P) rw_lock_s_lock_func(\
+ (M), (P), __FILE__, __LINE__)
/******************************************************************
NOTE! The following macros should be used in rw s-locking, not the
corresponding function. */
-#define rw_lock_s_lock_nowait(M) rw_lock_s_lock_func_nowait(\
- (M), __FILE__, __LINE__)
+#define rw_lock_s_lock_nowait(M) rw_lock_s_lock_func_nowait(\
+ (M), __FILE__, __LINE__)
/**********************************************************************
NOTE! Use the corresponding macro, not directly this function, except if
you supply the file name and line number. Lock an rw-lock in shared mode
@@ -129,7 +138,7 @@
void
rw_lock_s_lock_func(
/*================*/
- rw_lock_t* lock, /* in: pointer to rw-lock */
+ rw_lock_t* lock, /* in: pointer to rw-lock */
ulint pass, /* in: pass value; != 0, if the lock will
be passed to another thread to unlock */
const char* file_name,/* in: file name where lock requested */
@@ -143,7 +152,7 @@
rw_lock_s_lock_func_nowait(
/*=======================*/
/* out: TRUE if success */
- rw_lock_t* lock, /* in: pointer to rw-lock */
+ rw_lock_t* lock, /* in: pointer to rw-lock */
const char* file_name,/* in: file name where lock requested */
ulint line); /* in: line where requested */
/**********************************************************************
@@ -155,7 +164,7 @@
rw_lock_x_lock_func_nowait(
/*=======================*/
/* out: TRUE if success */
- rw_lock_t* lock, /* in: pointer to rw-lock */
+ rw_lock_t* lock, /* in: pointer to rw-lock */
const char* file_name,/* in: file name where lock requested */
ulint line); /* in: line where requested */
/**********************************************************************
@@ -174,36 +183,36 @@
Releases a shared mode lock. */
#ifdef UNIV_SYNC_DEBUG
-#define rw_lock_s_unlock(L) rw_lock_s_unlock_func(L, 0)
+#define rw_lock_s_unlock(L) rw_lock_s_unlock_func(L, 0)
#else
-#define rw_lock_s_unlock(L) rw_lock_s_unlock_func(L)
+#define rw_lock_s_unlock(L) rw_lock_s_unlock_func(L)
#endif
/***********************************************************************
Releases a shared mode lock. */
#ifdef UNIV_SYNC_DEBUG
-#define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L, P)
+#define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L, P)
#else
-#define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L)
+#define rw_lock_s_unlock_gen(L, P) rw_lock_s_unlock_func(L)
#endif
/******************************************************************
NOTE! The following macro should be used in rw x-locking, not the
corresponding function. */
-#define rw_lock_x_lock(M) rw_lock_x_lock_func(\
- (M), 0, __FILE__, __LINE__)
+#define rw_lock_x_lock(M) rw_lock_x_lock_func(\
+ (M), 0, __FILE__, __LINE__)
/******************************************************************
NOTE! The following macro should be used in rw x-locking, not the
corresponding function. */
-#define rw_lock_x_lock_gen(M, P) rw_lock_x_lock_func(\
- (M), (P), __FILE__, __LINE__)
+#define rw_lock_x_lock_gen(M, P) rw_lock_x_lock_func(\
+ (M), (P), __FILE__, __LINE__)
/******************************************************************
NOTE! The following macros should be used in rw x-locking, not the
corresponding function. */
-#define rw_lock_x_lock_nowait(M) rw_lock_x_lock_func_nowait(\
- (M), __FILE__, __LINE__)
+#define rw_lock_x_lock_nowait(M) rw_lock_x_lock_func_nowait(\
+ (M), __FILE__, __LINE__)
/**********************************************************************
NOTE! Use the corresponding macro, not directly this function! Lock an
rw-lock in exclusive mode for the current thread. If the rw-lock is locked
@@ -217,7 +226,7 @@
void
rw_lock_x_lock_func(
/*================*/
- rw_lock_t* lock, /* in: pointer to rw-lock */
+ rw_lock_t* lock, /* in: pointer to rw-lock */
ulint pass, /* in: pass value; != 0, if the lock will
be passed to another thread to unlock */
const char* file_name,/* in: file name where lock requested */
@@ -238,17 +247,17 @@
Releases an exclusive mode lock. */
#ifdef UNIV_SYNC_DEBUG
-#define rw_lock_x_unlock(L) rw_lock_x_unlock_func(L, 0)
+#define rw_lock_x_unlock(L) rw_lock_x_unlock_func(L, 0)
#else
-#define rw_lock_x_unlock(L) rw_lock_x_unlock_func(L)
+#define rw_lock_x_unlock(L) rw_lock_x_unlock_func(L)
#endif
/***********************************************************************
Releases an exclusive mode lock. */
#ifdef UNIV_SYNC_DEBUG
-#define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L, P)
+#define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L, P)
#else
-#define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L)
+#define rw_lock_x_unlock_gen(L, P) rw_lock_x_unlock_func(L)
#endif
/**********************************************************************
Low-level function which locks an rw-lock in s-mode when we know that it
@@ -305,14 +314,6 @@
/*====================*/
rw_lock_t* lock); /* in: rw-lock */
/**********************************************************************
-Sets the rw-lock latching level field. */
-
-void
-rw_lock_set_level(
-/*==============*/
- rw_lock_t* lock, /* in: rw-lock */
- ulint level); /* in: level */
-/**********************************************************************
Returns the value of writer_count for the lock. Does not reserve the lock
mutex, so the caller must be sure it is not changed during the call. */
UNIV_INLINE
@@ -371,8 +372,9 @@
Prints debug info of currently locked rw-locks. */
void
-rw_lock_list_print_info(void);
-/*=========================*/
+rw_lock_list_print_info(
+/*====================*/
+ FILE* file); /* in: file where to print */
/*******************************************************************
Returns the number of currently locked rw-locks.
Works only in the debug version. */
@@ -417,10 +419,9 @@
field. Then no new readers are allowed in. */
struct rw_lock_struct {
- os_event_t event; /* Used by sync0arr.c for thread queueing */
ulint reader_count; /* Number of readers who have locked this
lock in the shared mode */
- ulint writer; /* This field is set to RW_LOCK_EX if there
+ ulint writer; /* This field is set to RW_LOCK_EX if there
is a writer owning the lock (in exclusive
mode), RW_LOCK_WAIT_EX if a writer is
queueing for the lock, and
@@ -431,7 +432,7 @@
recursively locked the lock in the exclusive
mode */
mutex_t mutex; /* The mutex protecting rw_lock_struct */
- ulint pass; /* Default value 0. This is set to some
+ ulint pass; /* Default value 0. This is set to some
value != 0 given by the caller of an x-lock
operation, if the x-lock is to be passed to
another thread to unlock (which happens in
@@ -440,13 +441,6 @@
waiters (readers or writers) in the global
wait array, waiting for this rw_lock.
Otherwise, == 0. */
- ibool writer_is_wait_ex;
- /* This is TRUE if the writer field is
- RW_LOCK_WAIT_EX; this field is located far
- from the memory update hotspot fields which
- are at the start of this struct, thus we can
- peek this field without causing much memory
- bus traffic */
UT_LIST_NODE_T(rw_lock_t) list;
/* All allocated rw locks are put into a
list */
@@ -454,15 +448,21 @@
UT_LIST_BASE_NODE_T(rw_lock_debug_t) debug_list;
/* In the debug version: pointer to the debug
info list of the lock */
+ ulint level; /* Level in the global latching order. */
#endif /* UNIV_SYNC_DEBUG */
- ulint level; /* Level in the global latching
- order; default SYNC_LEVEL_NONE */
const char* cfile_name;/* File name where lock created */
- ulint cline; /* Line where created */
const char* last_s_file_name;/* File name where last s-locked */
const char* last_x_file_name;/* File name where last x-locked */
- ulint last_s_line; /* Line number where last time s-locked */
- ulint last_x_line; /* Line number where last time x-locked */
+ ibool writer_is_wait_ex;
+ /* This is TRUE if the writer field is
+ RW_LOCK_WAIT_EX; this field is located far
+ from the memory update hotspot fields which
+ are at the start of this struct, thus we can
+ peek this field without causing much memory
+ bus traffic */
+ unsigned cline:14; /* Line where created */
+ unsigned last_s_line:14; /* Line number where last time s-locked */
+ unsigned last_x_line:14; /* Line number where last time x-locked */
ulint magic_n;
};
--- 1.9.5.1/innobase/include/sync0rw.ic 2007-01-17 16:44:04 -07:00
+++ 1.17/storage/innobase/include/sync0rw.ic 2007-01-17 17:18:03 -07:00
@@ -15,7 +15,7 @@
void
rw_lock_s_lock_spin(
/*================*/
- rw_lock_t* lock, /* in: pointer to rw-lock */
+ rw_lock_t* lock, /* in: pointer to rw-lock */
ulint pass, /* in: pass value; != 0, if the lock will
be passed to another thread to unlock */
const char* file_name,/* in: file name where lock requested */
@@ -126,9 +126,9 @@
rw_lock_s_lock_low(
/*===============*/
/* out: TRUE if success */
- rw_lock_t* lock, /* in: pointer to rw-lock */
+ rw_lock_t* lock, /* in: pointer to rw-lock */
ulint pass __attribute__((unused)),
- /* in: pass value; != 0, if the lock will be
+ /* in: pass value; != 0, if the lock will be
passed to another thread to unlock */
const char* file_name, /* in: file name where lock requested */
ulint line) /* in: line where requested */
@@ -144,7 +144,7 @@
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info(lock, pass, RW_LOCK_SHARED, file_name,
- line);
+ line);
#endif
lock->last_s_file_name = file_name;
lock->last_s_line = line;
@@ -169,7 +169,7 @@
{
ut_ad(lock->writer == RW_LOCK_NOT_LOCKED);
ut_ad(rw_lock_get_reader_count(lock) == 0);
-
+
/* Set the shared lock by incrementing the reader count */
lock->reader_count++;
@@ -193,7 +193,7 @@
const char* file_name, /* in: file name where requested */
ulint line) /* in: line where lock requested */
{
- ut_ad(rw_lock_validate(lock));
+ ut_ad(rw_lock_validate(lock));
ut_ad(rw_lock_get_reader_count(lock) == 0);
ut_ad(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
@@ -201,7 +201,7 @@
lock->writer_thread = os_thread_get_curr_id();
lock->writer_count++;
lock->pass = 0;
-
+
lock->last_x_file_name = file_name;
lock->last_x_line = line;
@@ -220,7 +220,7 @@
void
rw_lock_s_lock_func(
/*================*/
- rw_lock_t* lock, /* in: pointer to rw-lock */
+ rw_lock_t* lock, /* in: pointer to rw-lock */
ulint pass, /* in: pass value; != 0, if the lock will
be passed to another thread to unlock */
const char* file_name,/* in: file name where lock requested */
@@ -236,7 +236,7 @@
safe recursive s-locking, we should keep in a list the thread ids of
the threads which have s-locked a latch. This would use some CPU
time. */
-
+
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
#endif /* UNIV_SYNC_DEBUG */
@@ -266,7 +266,7 @@
rw_lock_s_lock_func_nowait(
/*=======================*/
/* out: TRUE if success */
- rw_lock_t* lock, /* in: pointer to rw-lock */
+ rw_lock_t* lock, /* in: pointer to rw-lock */
const char* file_name,/* in: file name where lock requested */
ulint line) /* in: line where requested */
{
@@ -280,12 +280,12 @@
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info(lock, 0, RW_LOCK_SHARED, file_name,
- line);
+ line);
#endif
lock->last_s_file_name = file_name;
lock->last_s_line = line;
-
+
success = TRUE;
}
@@ -303,7 +303,7 @@
rw_lock_x_lock_func_nowait(
/*=======================*/
/* out: TRUE if success */
- rw_lock_t* lock, /* in: pointer to rw-lock */
+ rw_lock_t* lock, /* in: pointer to rw-lock */
const char* file_name,/* in: file name where lock requested */
ulint line) /* in: line where requested */
{
@@ -317,9 +317,9 @@
rw_lock_set_writer(lock, RW_LOCK_EX);
lock->writer_thread = curr_thread;
lock->pass = 0;
- relock:
+relock:
lock->writer_count++;
-
+
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
#endif
@@ -329,14 +329,14 @@
success = TRUE;
} else if (rw_lock_get_writer(lock) == RW_LOCK_EX
- && lock->pass == 0
- && os_thread_eq(lock->writer_thread, curr_thread)) {
+ && lock->pass == 0
+ && os_thread_eq(lock->writer_thread, curr_thread)) {
goto relock;
}
mutex_exit(rw_lock_get_mutex(lock));
- ut_ad(rw_lock_validate(lock));
+ ut_ad(rw_lock_validate(lock));
return(success);
}
@@ -355,9 +355,9 @@
)
{
mutex_t* mutex = &(lock->mutex);
- ibool sg = FALSE;
+ ibool sg = FALSE;
- /* Acquire the mutex protecting the rw-lock fields */
+ /* Acquire the mutex protecting the rw-lock fields */
mutex_enter(mutex);
/* Reset the shared lock by decrementing the reader count */
@@ -368,25 +368,24 @@
#ifdef UNIV_SYNC_DEBUG
rw_lock_remove_debug_info(lock, pass, RW_LOCK_SHARED);
#endif
-
+
/* If there may be waiters and this was the last s-lock,
signal the object */
if (UNIV_UNLIKELY(lock->waiters)
- && lock->reader_count == 0) {
- sg = TRUE;
+ && lock->reader_count == 0) {
+ sg = TRUE;
rw_lock_set_waiters(lock, 0);
}
-
+
mutex_exit(mutex);
if (UNIV_UNLIKELY(sg)) {
- os_event_set(lock->event);
- sync_array_object_signalled(sync_primary_wait_array);
+ sync_array_signal_object(sync_primary_wait_array, lock);
}
- ut_ad(rw_lock_validate(lock));
+ ut_ad(rw_lock_validate(lock));
#ifdef UNIV_SYNC_PERF_STAT
rw_s_exit_count++;
@@ -413,7 +412,7 @@
#endif
ut_ad(!lock->waiters);
- ut_ad(rw_lock_validate(lock));
+ ut_ad(rw_lock_validate(lock));
#ifdef UNIV_SYNC_PERF_STAT
rw_s_exit_count++;
#endif
@@ -432,9 +431,9 @@
#endif
)
{
- ibool sg = FALSE;
+ ibool sg = FALSE;
- /* Acquire the mutex protecting the rw-lock fields */
+ /* Acquire the mutex protecting the rw-lock fields */
mutex_enter(&(lock->mutex));
/* Reset the exclusive lock if this thread no longer has an x-mode
@@ -451,23 +450,22 @@
#ifdef UNIV_SYNC_DEBUG
rw_lock_remove_debug_info(lock, pass, RW_LOCK_EX);
#endif
-
+
/* If there may be waiters, signal the lock */
if (UNIV_UNLIKELY(lock->waiters)
- && lock->writer_count == 0) {
+ && lock->writer_count == 0) {
- sg = TRUE;
+ sg = TRUE;
rw_lock_set_waiters(lock, 0);
}
-
+
mutex_exit(&(lock->mutex));
if (UNIV_UNLIKELY(sg)) {
- os_event_set(lock->event);
- sync_array_object_signalled(sync_primary_wait_array);
+ sync_array_signal_object(sync_primary_wait_array, lock);
}
- ut_ad(rw_lock_validate(lock));
+ ut_ad(rw_lock_validate(lock));
#ifdef UNIV_SYNC_PERF_STAT
rw_x_exit_count++;
@@ -499,7 +497,7 @@
#endif
ut_ad(!lock->waiters);
- ut_ad(rw_lock_validate(lock));
+ ut_ad(rw_lock_validate(lock));
#ifdef UNIV_SYNC_PERF_STAT
rw_x_exit_count++;
--- 1.22.4.1/innobase/include/sync0sync.h 2007-01-17 16:44:04 -07:00
+++ 1.32/storage/innobase/include/sync0sync.h 2007-01-17 17:18:03 -07:00
@@ -18,7 +18,7 @@
#include "sync0arr.h"
#ifndef UNIV_HOTBACKUP
-extern my_bool timed_mutexes;
+extern my_bool timed_mutexes;
#endif /* UNIV_HOTBACKUP */
/**********************************************************************
@@ -40,11 +40,18 @@
necessary only if the memory block containing it is freed. */
#ifdef UNIV_DEBUG
-# define mutex_create(M) mutex_create_func((M), #M, __FILE__, __LINE__)
+# ifdef UNIV_SYNC_DEBUG
+# define mutex_create(M, level) \
+ mutex_create_func((M), #M, (level), __FILE__, __LINE__)
+# else
+# define mutex_create(M, level) \
+ mutex_create_func((M), #M, __FILE__, __LINE__)
+# endif
#else
-# define mutex_create(M) mutex_create_func((M), __FILE__, __LINE__)
+# define mutex_create(M, level) \
+ mutex_create_func((M), __FILE__, __LINE__)
#endif
-/*===================*/
+
/**********************************************************************
Creates, or rather, initializes a mutex object in a specified memory
location (which must be appropriately aligned). The mutex is initialized
@@ -57,6 +64,9 @@
mutex_t* mutex, /* in: pointer to memory */
#ifdef UNIV_DEBUG
const char* cmutex_name, /* in: mutex name */
+# ifdef UNIV_SYNC_DEBUG
+ ulint level, /* in: level */
+# endif /* UNIV_SYNC_DEBUG */
#endif /* UNIV_DEBUG */
const char* cfile_name, /* in: file name where created */
ulint cline); /* in: file line where created */
@@ -74,7 +84,7 @@
NOTE! The following macro should be used in mutex locking, not the
corresponding function. */
-#define mutex_enter(M) mutex_enter_func((M), __FILE__, __LINE__)
+#define mutex_enter(M) mutex_enter_func((M), __FILE__, __LINE__)
/**********************************************************************
A noninlined function that reserves a mutex. In ha_innodb.cc we have disabled
inlining of InnoDB functions, and no inlined functions should be called from
@@ -90,8 +100,8 @@
/* NOTE! currently same as mutex_enter! */
-#define mutex_enter_fast(M) mutex_enter_func((M), __FILE__, __LINE__)
-#define mutex_enter_fast_func mutex_enter_func;
+#define mutex_enter_fast(M) mutex_enter_func((M), __FILE__, __LINE__)
+#define mutex_enter_fast_func mutex_enter_func;
/**********************************************************************
NOTE! Use the corresponding macro in the header file, not this function
directly. Locks a mutex for the current thread. If the mutex is reserved
@@ -102,7 +112,7 @@
mutex_enter_func(
/*=============*/
mutex_t* mutex, /* in: pointer to mutex */
- const char* file_name, /* in: file name where locked */
+ const char* file_name, /* in: file name where locked */
ulint line); /* in: line where locked */
/************************************************************************
Tries to lock the mutex for the current thread. If the lock is not acquired
@@ -153,6 +163,7 @@
sync_print(
/*=======*/
FILE* file); /* in: file where to print */
+#ifdef UNIV_DEBUG
/**********************************************************************
Checks that the mutex has been initialized. */
@@ -160,14 +171,8 @@
mutex_validate(
/*===========*/
mutex_t* mutex);
-/**********************************************************************
-Sets the mutex latching level field. */
-
-void
-mutex_set_level(
-/*============*/
- mutex_t* mutex, /* in: mutex */
- ulint level); /* in: level */
+#endif /* UNIV_DEBUG */
+#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
Adds a latch and its level in the thread level array. Allocates the memory
for the array if called first time for this OS thread. Makes the checks
@@ -177,8 +182,8 @@
sync_thread_add_level(
/*==================*/
void* latch, /* in: pointer to a mutex or an rw-lock */
- ulint level); /* in: level in the latching order; if SYNC_LEVEL_NONE,
- nothing is done */
+ ulint level); /* in: level in the latching order; if
+ SYNC_LEVEL_VARYING, nothing is done */
/**********************************************************************
Removes a latch from the thread level array if it is found there. */
@@ -209,7 +214,6 @@
allowed to be owned by the thread,
also purge_is_running mutex is
allowed */
-#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
Checks that the current thread owns the mutex. Works only
in the debug version. */
@@ -236,12 +240,6 @@
ulint
mutex_n_reserved(void);
/*==================*/
-/**********************************************************************
-Prints debug info of currently reserved mutexes. */
-
-void
-mutex_list_print_info(void);
-/*========================*/
#endif /* UNIV_SYNC_DEBUG */
/**********************************************************************
NOT to be used outside this module except in debugging! Gets the value
@@ -259,7 +257,7 @@
ulint
mutex_get_waiters(
/*==============*/
- /* out: value to set */
+ /* out: value to set */
mutex_t* mutex); /* in: mutex */
#endif /* UNIV_SYNC_DEBUG */
@@ -275,7 +273,7 @@
Synchronization object Notes
---------------------- -----
-
+
Dictionary mutex If we have a pointer to a dictionary
| object, e.g., a table, it can be
| accessed without reserving the
@@ -287,7 +285,7 @@
V
Dictionary header
|
-V
+V
Secondary index tree latch The tree latch protects also all
| the B-tree non-leaf pages. These
V can be read with the page only
@@ -299,7 +297,7 @@
| it is allowed to latch non-leaf pages
| even after it has acquired the fsp
| latch.
-V
+V
Secondary index leaf The latch on the secondary index leaf
| can be kept while accessing the
| clustered index, to save CPU time.
@@ -307,7 +305,7 @@
Clustered index tree latch To increase concurrency, the tree
| latch is usually released when the
| leaf page latch has been acquired.
-V
+V
Clustered index non-leaf
|
V
@@ -325,7 +323,7 @@
| trx undo mutex reserved, it is allowed
| to latch the undo log pages in any
| order, and also after it has acquired
-| the fsp latch.
+| the fsp latch.
V
Rollback segment mutex The rollback segment mutex must be
| reserved, if, e.g., a new page must
@@ -389,7 +387,12 @@
#define SYNC_USER_TRX_LOCK 9999
#define SYNC_NO_ORDER_CHECK 3000 /* this can be used to suppress
latching order checking */
-#define SYNC_LEVEL_NONE 2000 /* default: level not defined */
+#define SYNC_LEVEL_VARYING 2000 /* Level is varying. Only used with
+ buffer pool page locks, which do not
+ have a fixed level, but instead have
+ their level set after the page is
+ locked; see e.g.
+ ibuf_bitmap_get_map_page(). */
#define SYNC_DICT_OPERATION 1001 /* table create, drop, etc. reserve
this in X-mode, implicit or backround
operations purge, rollback, foreign
@@ -418,7 +421,7 @@
#define SYNC_EXTERN_STORAGE 500
#define SYNC_FSP 400
#define SYNC_FSP_PAGE 395
-/*------------------------------------- Insert buffer headers */
+/*------------------------------------- Insert buffer headers */
/*------------------------------------- ibuf_mutex */
/*------------------------------------- Insert buffer tree */
#define SYNC_IBUF_BITMAP_MUTEX 351
@@ -432,6 +435,7 @@
#define SYNC_TRX_SYS_HEADER 290
#define SYNC_LOG 170
#define SYNC_RECV 168
+#define SYNC_WORK_QUEUE 161
#define SYNC_SEARCH_SYS 160 /* NOTE that if we have a memory
heap that can be extended to the
buffer pool, its logical level is
@@ -447,7 +451,7 @@
#define SYNC_MEM_POOL 130
/* Codes used to designate lock operations */
-#define RW_LOCK_NOT_LOCKED 350
+#define RW_LOCK_NOT_LOCKED 350
#define RW_LOCK_EX 351
#define RW_LOCK_EXCLUSIVE 351
#define RW_LOCK_SHARED 352
@@ -459,7 +463,6 @@
implementation of a mutual exclusion semaphore. */
struct mutex_struct {
- os_event_t event; /* Used by sync0arr.c for the wait queue */
ulint lock_word; /* This ulint is the target of the atomic
test-and-set instruction in Win32 */
#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER)
@@ -478,12 +481,14 @@
ulint line; /* Line where the mutex was locked */
os_thread_id_t thread_id; /* Debug version: The thread id of the
thread which locked the mutex. */
+ ulint level; /* Level in the global latching order */
#endif /* UNIV_SYNC_DEBUG */
- ulint level; /* Level in the global latching
- order; default SYNC_LEVEL_NONE */
const char* cfile_name;/* File name where mutex created */
- ulint cline; /* Line where created */
- ulint magic_n;
+ ulint cline; /* Line where created */
+#ifdef UNIV_DEBUG
+ ulint magic_n;
+# define MUTEX_MAGIC_N (ulint)979585
+#endif /* UNIV_DEBUG */
#ifndef UNIV_HOTBACKUP
ulong count_os_wait; /* count of os_wait */
# ifdef UNIV_DEBUG
@@ -499,8 +504,6 @@
#endif /* !UNIV_HOTBACKUP */
};
-#define MUTEX_MAGIC_N (ulint)979585
-
/* The global array of wait cells for implementation of the databases own
mutexes and read-write locks. Appears here for debugging purposes only! */
@@ -512,20 +515,16 @@
#define SYNC_SPIN_ROUNDS srv_n_spin_wait_rounds
-#define SYNC_INFINITE_TIME ((ulint)(-1))
-
-/* Means that a timeout elapsed when waiting */
-
-#define SYNC_TIME_EXCEEDED (ulint)1
-
/* The number of system calls made in this module. Intended for performance
monitoring. */
-extern ulint mutex_system_call_count;
+extern ulint mutex_system_call_count;
extern ulint mutex_exit_count;
+#ifdef UNIV_SYNC_DEBUG
/* Latching order checks start when this is set TRUE */
extern ibool sync_order_checks_on;
+#endif /* UNIV_SYNC_DEBUG */
/* This variable is set to TRUE when sync_init is called */
extern ibool sync_initialized;
--- 1.24.6.1/innobase/os/os0sync.c 2007-01-17 16:44:05 -07:00
+++ 1.33/storage/innobase/os/os0sync.c 2007-01-17 17:18:03 -07:00
@@ -20,8 +20,7 @@
#include "srv0start.h"
/* Type definition for an operating system mutex struct */
-struct os_mutex_struct{
- os_event_t event; /* Used by sync0arr.c for queing threads */
+struct os_mutex_struct{
void* handle; /* OS handle to mutex */
ulint count; /* we use this counter to check
that the same thread does not
@@ -36,7 +35,6 @@
/* Mutex protecting counts and the lists of OS mutexes and events */
os_mutex_t os_sync_mutex;
ibool os_sync_mutex_inited = FALSE;
-ibool os_sync_free_called = FALSE;
/* This is incremented by 1 in os_thread_create and decremented by 1 in
os_thread_exit */
@@ -52,10 +50,6 @@
ulint os_mutex_count = 0;
ulint os_fast_mutex_count = 0;
-/* Because a mutex is embedded inside an event and there is an
-event embedded inside a mutex, on free, this generates a recursive call.
-This version of the free event function doesn't acquire the global lock */
-static void os_event_free_internal(os_event_t event);
/*************************************************************
Initializes global event and OS 'slow' mutex lists. */
@@ -82,31 +76,29 @@
os_event_t event;
os_mutex_t mutex;
- os_sync_free_called = TRUE;
event = UT_LIST_GET_FIRST(os_event_list);
while (event) {
- os_event_free(event);
+ os_event_free(event);
- event = UT_LIST_GET_FIRST(os_event_list);
+ event = UT_LIST_GET_FIRST(os_event_list);
}
mutex = UT_LIST_GET_FIRST(os_mutex_list);
while (mutex) {
- if (mutex == os_sync_mutex) {
- /* Set the flag to FALSE so that we do not try to
- reserve os_sync_mutex any more in remaining freeing
- operations in shutdown */
- os_sync_mutex_inited = FALSE;
- }
+ if (mutex == os_sync_mutex) {
+ /* Set the flag to FALSE so that we do not try to
+ reserve os_sync_mutex any more in remaining freeing
+ operations in shutdown */
+ os_sync_mutex_inited = FALSE;
+ }
- os_mutex_free(mutex);
+ os_mutex_free(mutex);
- mutex = UT_LIST_GET_FIRST(os_mutex_list);
+ mutex = UT_LIST_GET_FIRST(os_mutex_list);
}
- os_sync_free_called = FALSE;
}
/*************************************************************
@@ -122,18 +114,19 @@
the event is created without a name */
{
#ifdef __WIN__
- os_event_t event;
+ os_event_t event;
event = ut_malloc(sizeof(struct os_event_struct));
- event->handle = CreateEvent(NULL,/* No security attributes */
- TRUE, /* Manual reset */
- FALSE, /* Initial state nonsignaled */
- (LPCTSTR) name);
+ event->handle = CreateEvent(NULL, /* No security attributes */
+ TRUE, /* Manual reset */
+ FALSE, /* Initial state nonsignaled */
+ (LPCTSTR) name);
if (!event->handle) {
- fprintf(stderr,
-"InnoDB: Could not create a Windows event semaphore; Windows error %lu\n",
- (ulong) GetLastError());
+ fprintf(stderr,
+ "InnoDB: Could not create a Windows event semaphore;"
+ " Windows error %lu\n",
+ (ulong) GetLastError());
}
#else /* Unix */
os_event_t event;
@@ -146,7 +139,7 @@
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
ut_a(0 == pthread_cond_init(&(event->cond_var),
- pthread_condattr_default));
+ pthread_condattr_default));
#else
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
#endif
@@ -154,21 +147,14 @@
event->signal_count = 0;
#endif /* __WIN__ */
- /* The os_sync_mutex can be NULL because during startup an event
- can be created [ because it's embedded in the mutex/rwlock ] before
- this module has been initialized */
- if (os_sync_mutex != NULL) {
- os_mutex_enter(os_sync_mutex);
- }
-
/* Put to the list of events */
+ os_mutex_enter(os_sync_mutex);
+
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
os_event_count++;
- if (os_sync_mutex != NULL) {
- os_mutex_exit(os_sync_mutex);
- }
+ os_mutex_exit(os_sync_mutex);
return(event);
}
@@ -185,22 +171,23 @@
const char* name) /* in: the name of the event, if NULL
the event is created without a name */
{
- os_event_t event;
+ os_event_t event;
event = ut_malloc(sizeof(struct os_event_struct));
- event->handle = CreateEvent(NULL,/* No security attributes */
- FALSE, /* Auto-reset */
- FALSE, /* Initial state nonsignaled */
- (LPCTSTR) name);
+ event->handle = CreateEvent(NULL, /* No security attributes */
+ FALSE, /* Auto-reset */
+ FALSE, /* Initial state nonsignaled */
+ (LPCTSTR) name);
if (!event->handle) {
- fprintf(stderr,
-"InnoDB: Could not create a Windows auto event semaphore; Windows error %lu\n",
- (ulong) GetLastError());
+ fprintf(stderr,
+ "InnoDB: Could not create a Windows auto"
+ " event semaphore; Windows error %lu\n",
+ (ulong) GetLastError());
}
- /* Put to the list of events */
+ /* Put to the list of events */
os_mutex_enter(os_sync_mutex);
UT_LIST_ADD_FIRST(os_event_list, os_event_list, event);
@@ -222,7 +209,7 @@
/*=========*/
os_event_t event) /* in: event to set */
{
-#ifdef __WIN__
+#ifdef __WIN__
ut_a(event);
ut_a(SetEvent(event->handle));
#else
@@ -239,7 +226,7 @@
}
os_fast_mutex_unlock(&(event->os_mutex));
-#endif
+#endif
}
/**************************************************************
@@ -271,42 +258,13 @@
}
/**************************************************************
-Frees an event object, without acquiring the global lock. */
-static
-void
-os_event_free_internal(
-/*===================*/
- os_event_t event) /* in: event to free */
-{
-#ifdef __WIN__
- ut_a(event);
-
- ut_a(CloseHandle(event->handle));
-#else
- ut_a(event);
-
- /* This is to avoid freeing the mutex twice */
- os_fast_mutex_free(&(event->os_mutex));
-
- ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
-#endif
- /* Remove from the list of events */
-
- UT_LIST_REMOVE(os_event_list, os_event_list, event);
-
- os_event_count--;
-
- ut_free(event);
-}
-
-/**************************************************************
Frees an event object. */
void
os_event_free(
/*==========*/
os_event_t event) /* in: event to free */
-
+
{
#ifdef __WIN__
ut_a(event);
@@ -318,7 +276,7 @@
os_fast_mutex_free(&(event->os_mutex));
ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
#endif
- /* Remove from the list of events */
+ /* Remove from the list of events */
os_mutex_enter(os_sync_mutex);
@@ -353,7 +311,7 @@
ut_a(err == WAIT_OBJECT_0);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
- os_thread_exit(NULL);
+ os_thread_exit(NULL);
}
#else
ib_longlong old_signal_count;
@@ -364,7 +322,7 @@
for (;;) {
if (event->is_set == TRUE
- || event->signal_count != old_signal_count) {
+ || event->signal_count != old_signal_count) {
os_fast_mutex_unlock(&(event->os_mutex));
@@ -409,7 +367,7 @@
} else {
err = WaitForSingleObject(event->handle, INFINITE);
}
-
+
if (err == WAIT_OBJECT_0) {
return(0);
@@ -422,7 +380,7 @@
}
#else
UT_NOT_USED(time);
-
+
/* In Posix this is just an ordinary, infinite wait */
os_event_wait(event);
@@ -453,14 +411,14 @@
ut_a(n > 0);
index = WaitForMultipleObjects((DWORD) n, native_event_array,
- FALSE, /* Wait for any 1 event */
- INFINITE); /* Infinite wait time
- limit */
+ FALSE, /* Wait for any 1 event */
+ INFINITE); /* Infinite wait time
+ limit */
ut_a(index >= WAIT_OBJECT_0); /* NOTE: Pointless comparision */
ut_a(index < WAIT_OBJECT_0 + n);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
- os_thread_exit(NULL);
+ os_thread_exit(NULL);
}
return(index - WAIT_OBJECT_0);
@@ -483,28 +441,27 @@
os_mutex_t mutex_str;
mutex = CreateMutex(NULL, /* No security attributes */
- FALSE, /* Initial state: no owner */
- (LPCTSTR) name);
+ FALSE, /* Initial state: no owner */
+ (LPCTSTR) name);
ut_a(mutex);
#else
os_fast_mutex_t* mutex;
os_mutex_t mutex_str;
UT_NOT_USED(name);
-
+
mutex = ut_malloc(sizeof(os_fast_mutex_t));
os_fast_mutex_init(mutex);
-#endif
+#endif
mutex_str = ut_malloc(sizeof(os_mutex_str_t));
mutex_str->handle = mutex;
mutex_str->count = 0;
- mutex_str->event = os_event_create(NULL);
if (os_sync_mutex_inited) {
/* When creating os_sync_mutex itself we cannot reserve it */
- os_mutex_enter(os_sync_mutex);
+ os_mutex_enter(os_sync_mutex);
}
UT_LIST_ADD_FIRST(os_mutex_list, os_mutex_list, mutex_str);
@@ -564,7 +521,7 @@
ut_a(ReleaseMutex(mutex->handle));
#else
os_fast_mutex_unlock(mutex->handle);
-#endif
+#endif
}
/**************************************************************
@@ -577,16 +534,12 @@
{
ut_a(mutex);
- if (!os_sync_free_called) {
- os_event_free_internal(mutex->event);
- }
-
if (os_sync_mutex_inited) {
os_mutex_enter(os_sync_mutex);
}
UT_LIST_REMOVE(os_mutex_list, os_mutex_list, mutex);
-
+
os_mutex_count--;
if (os_sync_mutex_inited) {
@@ -614,7 +567,7 @@
{
#ifdef __WIN__
ut_a(fast_mutex);
-
+
InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex);
#else
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
@@ -633,7 +586,7 @@
os_fast_mutex_count++;
if (os_sync_mutex_inited) {
- os_mutex_exit(os_sync_mutex);
+ os_mutex_exit(os_sync_mutex);
}
}
@@ -681,18 +634,18 @@
DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
#else
int ret;
-
+
ret = pthread_mutex_destroy(fast_mutex);
if (ret != 0) {
ut_print_timestamp(stderr);
fprintf(stderr,
-" InnoDB: error: return value %lu when calling\n"
-"InnoDB: pthread_mutex_destroy().\n", (ulint)ret);
+ " InnoDB: error: return value %lu when calling\n"
+ "InnoDB: pthread_mutex_destroy().\n", (ulint)ret);
fprintf(stderr,
-"InnoDB: Byte contents of the pthread mutex at %p:\n", fast_mutex);
- ut_print_buf(stderr, (const byte*)fast_mutex,
- sizeof(os_fast_mutex_t));
+ "InnoDB: Byte contents of the pthread mutex at %p:\n",
+ (void*) fast_mutex);
+ ut_print_buf(stderr, fast_mutex, sizeof(os_fast_mutex_t));
fprintf(stderr, "\n");
}
#endif
--- 1.20.3.1/innobase/sync/sync0arr.c 2007-01-17 16:44:05 -07:00
+++ 1.28/storage/innobase/sync/sync0arr.c 2007-01-17 17:18:03 -07:00
@@ -46,13 +46,22 @@
until a resource is released. The suspending is implemented
using an operating system event semaphore. */
struct sync_cell_struct {
- void* wait_object; /* pointer to the object the
- thread is waiting for; if NULL
- the cell is free for use */
+ /* State of the cell. SC_WAKING_UP means
+ sync_array_struct->n_reserved has been decremented, but the thread
+ in this cell has not waken up yet. When it does, it will set the
+ state to SC_FREE. Note that this is done without the protection of
+ any mutex. */
+ enum { SC_FREE, SC_RESERVED, SC_WAKING_UP } state;
+
+ void* wait_object; /* pointer to the object the
+ thread is waiting for; this is not
+ reseted to NULL when a cell is
+ freed. */
+
mutex_t* old_wait_mutex; /* the latest wait mutex in cell */
rw_lock_t* old_wait_rw_lock;/* the latest wait rw-lock in cell */
- ulint request_type; /* lock type requested on the
- object */
+ ulint request_type; /* lock type requested on the
+ object */
const char* file; /* in debug version file where
requested */
ulint line; /* in debug version line where
@@ -62,15 +71,13 @@
ibool waiting; /* TRUE if the thread has already
called sync_array_event_wait
on this cell */
+ ibool event_set; /* TRUE if the event is set */
+ os_event_t event; /* operating system event
+ semaphore handle */
time_t reservation_time;/* time when the thread reserved
the wait cell */
};
-/* NOTE: It is allowed for a thread to wait
-for an event allocated for the array without owning the
-protecting mutex (depending on the case: OS or database mutex), but
-all changes (set or reset) to the state of the event must be made
-while owning the mutex. */
struct sync_array_struct {
ulint n_reserved; /* number of currently reserved
cells in the wait array */
@@ -103,8 +110,8 @@
sync_array_detect_deadlock(
/*=======================*/
/* out: TRUE if deadlock detected */
- sync_array_t* arr, /* in: wait array; NOTE! the caller must
- own the mutex to array */
+ sync_array_t* arr, /* in: wait array; NOTE! the caller must
+ own the mutex to array */
sync_cell_t* start, /* in: cell where recursive search started */
sync_cell_t* cell, /* in: cell to search */
ulint depth); /* in: recursion depth */
@@ -187,7 +194,7 @@
sync_cell_t* cell_array;
sync_cell_t* cell;
ulint i;
-
+
ut_a(n_cells > 0);
/* Allocate memory for the data structures */
@@ -202,20 +209,23 @@
arr->sg_count = 0;
arr->res_count = 0;
- /* Then create the mutex to protect the wait array complex */
+ /* Then create the mutex to protect the wait array complex */
if (protection == SYNC_ARRAY_OS_MUTEX) {
arr->os_mutex = os_mutex_create(NULL);
} else if (protection == SYNC_ARRAY_MUTEX) {
- mutex_create(&(arr->mutex));
- mutex_set_level(&(arr->mutex), SYNC_NO_ORDER_CHECK);
+ mutex_create(&arr->mutex, SYNC_NO_ORDER_CHECK);
} else {
ut_error;
}
- for (i = 0; i < n_cells; i++) {
- cell = sync_array_get_nth_cell(arr, i);
- cell->wait_object = NULL;
- cell->waiting = FALSE;
+ for (i = 0; i < n_cells; i++) {
+ cell = sync_array_get_nth_cell(arr, i);
+ cell->state = SC_FREE;
+ cell->wait_object = NULL;
+
+ /* Create an operating system event semaphore with no name */
+ cell->event = os_event_create(NULL);
+ cell->event_set = FALSE; /* it is created in reset state */
}
return(arr);
@@ -229,15 +239,22 @@
/*============*/
sync_array_t* arr) /* in, own: sync wait array */
{
+ ulint i;
+ sync_cell_t* cell;
ulint protection;
- ut_a(arr->n_reserved == 0);
-
+ ut_a(arr->n_reserved == 0);
+
sync_array_validate(arr);
-
+
+ for (i = 0; i < arr->n_cells; i++) {
+ cell = sync_array_get_nth_cell(arr, i);
+ os_event_free(cell->event);
+ }
+
protection = arr->protection;
- /* Release the mutex protecting the wait array complex */
+ /* Release the mutex protecting the wait array complex */
if (protection == SYNC_ARRAY_OS_MUTEX) {
os_mutex_free(arr->os_mutex);
@@ -248,7 +265,7 @@
}
ut_free(arr->array);
- ut_free(arr);
+ ut_free(arr);
}
/************************************************************************
@@ -260,40 +277,24 @@
/*================*/
sync_array_t* arr) /* in: sync wait array */
{
- ulint i;
- sync_cell_t* cell;
- ulint count = 0;
-
- sync_array_enter(arr);
-
- for (i = 0; i < arr->n_cells; i++) {
- cell = sync_array_get_nth_cell(arr, i);
-
- if (cell->wait_object != NULL) {
- count++;
- }
- }
+ ulint i;
+ sync_cell_t* cell;
+ ulint count = 0;
- ut_a(count == arr->n_reserved);
+ sync_array_enter(arr);
- sync_array_exit(arr);
-}
+ for (i = 0; i < arr->n_cells; i++) {
+ cell = sync_array_get_nth_cell(arr, i);
-/***********************************************************************
-Puts the cell event in reset state. */
-static
-void
-sync_cell_event_reset(
-/*==================*/
- ulint type, /* in: lock type mutex/rw_lock */
- void* object) /* in: the rw_lock/mutex object */
-{
- if (type == SYNC_MUTEX) {
- os_event_reset(((mutex_t *) object)->event);
- } else {
- os_event_reset(((rw_lock_t *) object)->event);
+ if (cell->state == SC_RESERVED) {
+ count++;
+ }
}
-}
+
+ ut_a(count == arr->n_reserved);
+
+ sync_array_exit(arr);
+}
/**********************************************************************
Reserves a wait array cell for waiting for an object.
@@ -302,30 +303,42 @@
void
sync_array_reserve_cell(
/*====================*/
- sync_array_t* arr, /* in: wait array */
- void* object, /* in: pointer to the object to wait for */
- ulint type, /* in: lock request type */
+ sync_array_t* arr, /* in: wait array */
+ void* object, /* in: pointer to the object to wait for */
+ ulint type, /* in: lock request type */
const char* file, /* in: file where requested */
- ulint line, /* in: line where requested */
- ulint* index) /* out: index of the reserved cell */
+ ulint line, /* in: line where requested */
+ ulint* index) /* out: index of the reserved cell */
{
- sync_cell_t* cell;
- ulint i;
-
- ut_a(object);
- ut_a(index);
+ sync_cell_t* cell;
+ ulint i;
- sync_array_enter(arr);
+ ut_a(object);
+ ut_a(index);
- arr->res_count++;
+ sync_array_enter(arr);
+
+ arr->res_count++;
/* Reserve a new cell. */
- for (i = 0; i < arr->n_cells; i++) {
- cell = sync_array_get_nth_cell(arr, i);
+ for (i = 0; i < arr->n_cells; i++) {
+ cell = sync_array_get_nth_cell(arr, i);
- if (cell->wait_object == NULL) {
+ if (cell->state == SC_FREE) {
+
+ /* We do not check cell->event_set because it is
+ set outside the protection of the sync array mutex
+ and we had a bug regarding it, and since resetting
+ an event when it is not needed does no harm it is
+ safer always to do it. */
+
+ cell->event_set = FALSE;
+ os_event_reset(cell->event);
+
+ cell->state = SC_RESERVED;
+ cell->reservation_time = time(NULL);
+ cell->thread = os_thread_get_curr_id();
- cell->waiting = FALSE;
cell->wait_object = object;
if (type == SYNC_MUTEX) {
@@ -333,32 +346,88 @@
} else {
cell->old_wait_rw_lock = object;
}
-
+
cell->request_type = type;
-
+ cell->waiting = FALSE;
+
cell->file = file;
cell->line = line;
-
+
arr->n_reserved++;
*index = i;
sync_array_exit(arr);
- /* Make sure the event is reset */
- sync_cell_event_reset(type, object);
+ return;
+ }
+ }
- cell->reservation_time = time(NULL);
+ ut_error; /* No free cell found */
- cell->thread = os_thread_get_curr_id();
-
- return;
- }
- }
+ return;
+}
- ut_error; /* No free cell found */
+/**********************************************************************
+Frees the cell. Note that we don't have any mutex reserved when calling
+this. */
+static
+void
+sync_array_free_cell(
+/*=================*/
+ sync_array_t* arr, /* in: wait array */
+ ulint index) /* in: index of the cell in array */
+{
+ sync_cell_t* cell;
- return;
+ cell = sync_array_get_nth_cell(arr, index);
+
+ ut_a(cell->state == SC_WAKING_UP);
+ ut_a(cell->wait_object != NULL);
+
+ cell->state = SC_FREE;
+}
+
+/**********************************************************************
+Frees the cell safely by reserving the sync array mutex and decrementing
+n_reserved if necessary. Should only be called from mutex_spin_wait. */
+
+void
+sync_array_free_cell_protected(
+/*===========================*/
+ sync_array_t* arr, /* in: wait array */
+ ulint index) /* in: index of the cell in array */
+{
+ sync_cell_t* cell;
+
+ sync_array_enter(arr);
+
+ cell = sync_array_get_nth_cell(arr, index);
+
+ ut_a(cell->state != SC_FREE);
+ ut_a(cell->wait_object != NULL);
+
+ /* We only need to decrement n_reserved if it has not already been
+ done by sync_array_signal_object. */
+ if (cell->state == SC_RESERVED) {
+ ut_a(arr->n_reserved > 0);
+ arr->n_reserved--;
+ } else if (cell->state == SC_WAKING_UP) {
+ /* This is tricky; if we don't wait for the event to be
+ signaled, signal_object can set the state of a cell to
+ SC_WAKING_UP, mutex_spin_wait can call this and set the
+ state to SC_FREE, and then signal_object gets around to
+ calling os_set_event for the cell but since it's already
+ been freed things break horribly. */
+
+ sync_array_exit(arr);
+ os_event_wait(cell->event);
+ sync_array_enter(arr);
+ }
+
+ cell->state = SC_FREE;
+
+ sync_array_exit(arr);
}
/**********************************************************************
@@ -370,56 +439,51 @@
void
sync_array_wait_event(
/*==================*/
- sync_array_t* arr, /* in: wait array */
- ulint index) /* in: index of the reserved cell */
+ sync_array_t* arr, /* in: wait array */
+ ulint index) /* in: index of the reserved cell */
{
- sync_cell_t* cell;
- os_event_t event;
-
- ut_a(arr);
+ sync_cell_t* cell;
+ os_event_t event;
- sync_array_enter(arr);
+ ut_a(arr);
- cell = sync_array_get_nth_cell(arr, index);
+ cell = sync_array_get_nth_cell(arr, index);
+ ut_a((cell->state == SC_RESERVED) || (cell->state == SC_WAKING_UP));
ut_a(cell->wait_object);
ut_a(!cell->waiting);
ut_ad(os_thread_get_curr_id() == cell->thread);
- if (cell->request_type == SYNC_MUTEX) {
- event = ((mutex_t*) cell->wait_object)->event;
- } else {
- event = ((rw_lock_t*) cell->wait_object)->event;
- }
-
- cell->waiting = TRUE;
+ event = cell->event;
+ cell->waiting = TRUE;
#ifdef UNIV_SYNC_DEBUG
-
+
/* We use simple enter to the mutex below, because if
we cannot acquire it at once, mutex_enter would call
recursively sync_array routines, leading to trouble.
rw_lock_debug_mutex freezes the debug lists. */
+ sync_array_enter(arr);
rw_lock_debug_mutex_enter();
if (TRUE == sync_array_detect_deadlock(arr, cell, cell, 0)) {
fputs("########################################\n", stderr);
ut_error;
- }
+ }
rw_lock_debug_mutex_exit();
+ sync_array_exit(arr);
#endif
- sync_array_exit(arr);
+ os_event_wait(event);
- os_event_wait(event);
-
- sync_array_free_cell(arr, index);
+ sync_array_free_cell(arr, index);
}
/**********************************************************************
-Reports info of a wait array cell. */
+Reports info of a wait array cell. Note: sync_array_print_long_waits()
+calls this without mutex protection. */
static
void
sync_array_cell_print(
@@ -434,12 +498,22 @@
type = cell->request_type;
fprintf(file,
-"--Thread %lu has waited at %s line %lu for %.2f seconds the semaphore:\n",
- (ulong) os_thread_pf(cell->thread), cell->file,
- (ulong) cell->line,
- difftime(time(NULL), cell->reservation_time));
+ "--Thread %lu has waited at %s line %lu"
+ " for %.2f seconds the semaphore:\n",
+ (ulong) os_thread_pf(cell->thread), cell->file,
+ (ulong) cell->line,
+ difftime(time(NULL), cell->reservation_time));
+ fprintf(file, "Wait array cell state %lu\n", (ulong)cell->state);
+
+ /* If the memory area pointed to by old_wait_mutex /
+ old_wait_rw_lock has been freed, this can crash. */
+
+ if (cell->state != SC_RESERVED) {
+ /* If cell has this state, then even if we are holding the sync
+ array mutex, the wait object may get freed meanwhile. Do not
+ print the wait object then. */
- if (type == SYNC_MUTEX) {
+ } else if (type == SYNC_MUTEX) {
/* We use old_wait_mutex in case the cell has already
been freed meanwhile */
mutex = cell->old_wait_mutex;
@@ -450,7 +524,7 @@
"Last time reserved in file %s line %lu, "
#endif /* UNIV_SYNC_DEBUG */
"waiters flag %lu\n",
- mutex, mutex->cfile_name, (ulong) mutex->cline,
+ (void*) mutex, mutex->cfile_name, (ulong) mutex->cline,
(ulong) mutex->lock_word,
#ifdef UNIV_SYNC_DEBUG
mutex->file_name, (ulong) mutex->line,
@@ -465,17 +539,18 @@
fprintf(file,
" RW-latch at %p created in file %s line %lu\n",
- rwlock, rwlock->cfile_name,
+ (void*) rwlock, rwlock->cfile_name,
(ulong) rwlock->cline);
if (rwlock->writer != RW_LOCK_NOT_LOCKED) {
fprintf(file,
- "a writer (thread id %lu) has reserved it in mode %s",
+ "a writer (thread id %lu) has"
+ " reserved it in mode %s",
(ulong) os_thread_pf(rwlock->writer_thread),
rwlock->writer == RW_LOCK_EX
? " exclusive\n"
: " wait exclusive\n");
}
-
+
fprintf(file,
"number of readers %lu, waiters flag %lu\n"
"Last time read locked in file %s line %lu\n"
@@ -490,8 +565,8 @@
ut_error;
}
- if (!cell->waiting) {
- fputs("wait has ended\n", file);
+ if (cell->event_set) {
+ fputs("wait is ending\n", file);
}
}
@@ -504,22 +579,22 @@
/*===================*/
/* out: pointer to cell or NULL
if not found */
- sync_array_t* arr, /* in: wait array */
+ sync_array_t* arr, /* in: wait array */
os_thread_id_t thread) /* in: thread id */
{
- ulint i;
- sync_cell_t* cell;
+ ulint i;
+ sync_cell_t* cell;
- for (i = 0; i < arr->n_cells; i++) {
+ for (i = 0; i < arr->n_cells; i++) {
- cell = sync_array_get_nth_cell(arr, i);
+ cell = sync_array_get_nth_cell(arr, i);
- if (cell->wait_object != NULL
+ if ((cell->state == SC_RESERVED)
&& os_thread_eq(cell->thread, thread)) {
- return(cell); /* Found */
- }
- }
+ return(cell); /* Found */
+ }
+ }
return(NULL); /* Not found */
}
@@ -531,8 +606,8 @@
sync_array_deadlock_step(
/*=====================*/
/* out: TRUE if deadlock detected */
- sync_array_t* arr, /* in: wait array; NOTE! the caller must
- own the mutex to array */
+ sync_array_t* arr, /* in: wait array; NOTE! the caller must
+ own the mutex to array */
sync_cell_t* start, /* in: cell where recursive search
started */
os_thread_id_t thread, /* in: thread to look at */
@@ -551,7 +626,7 @@
return(FALSE);
}
-
+
new = sync_array_find_thread(arr, thread);
if (new == start) {
@@ -561,7 +636,7 @@
/* Deadlock */
fputs("########################################\n"
- "DEADLOCK of threads detected!\n", stderr);
+ "DEADLOCK of threads detected!\n", stderr);
return(TRUE);
@@ -583,8 +658,8 @@
sync_array_detect_deadlock(
/*=======================*/
/* out: TRUE if deadlock detected */
- sync_array_t* arr, /* in: wait array; NOTE! the caller must
- own the mutex to array */
+ sync_array_t* arr, /* in: wait array; NOTE! the caller must
+ own the mutex to array */
sync_cell_t* start, /* in: cell where recursive search started */
sync_cell_t* cell, /* in: cell to search */
ulint depth) /* in: recursion depth */
@@ -594,19 +669,19 @@
os_thread_id_t thread;
ibool ret;
rw_lock_debug_t*debug;
-
- ut_a(arr && start && cell);
+
+ ut_a(arr && start && cell);
ut_ad(cell->wait_object);
ut_ad(os_thread_get_curr_id() == start->thread);
ut_ad(depth < 100);
-
+
depth++;
-
- if (!cell->waiting) {
+
+ if (cell->event_set || !cell->waiting) {
return(FALSE); /* No deadlock here */
}
-
+
if (cell->request_type == SYNC_MUTEX) {
mutex = cell->wait_object;
@@ -624,11 +699,13 @@
a thread with ID_UNDEFINED value. */
ret = sync_array_deadlock_step(arr, start, thread, 0,
- depth);
+ depth);
if (ret) {
fprintf(stderr,
- "Mutex %p owned by thread %lu file %s line %lu\n",
- mutex, (ulong) os_thread_pf(mutex->thread_id),
+ "Mutex %p owned by thread %lu"
+ " file %s line %lu\n",
+ (void*) mutex,
+ (ulong) os_thread_pf(mutex->thread_id),
mutex->file_name, (ulong) mutex->line);
sync_array_cell_print(stderr, cell);
@@ -640,76 +717,79 @@
} else if (cell->request_type == RW_LOCK_EX) {
- lock = cell->wait_object;
-
- debug = UT_LIST_GET_FIRST(lock->debug_list);
+ lock = cell->wait_object;
- while (debug != NULL) {
+ debug = UT_LIST_GET_FIRST(lock->debug_list);
- thread = debug->thread_id;
+ while (debug != NULL) {
- if (((debug->lock_type == RW_LOCK_EX)
- && !os_thread_eq(thread, cell->thread))
- || ((debug->lock_type == RW_LOCK_WAIT_EX)
- && !os_thread_eq(thread, cell->thread))
- || (debug->lock_type == RW_LOCK_SHARED)) {
+ thread = debug->thread_id;
- /* The (wait) x-lock request can block infinitely
- only if someone (can be also cell thread) is holding
- s-lock, or someone (cannot be cell thread) (wait)
- x-lock, and he is blocked by start thread */
-
- ret = sync_array_deadlock_step(arr, start, thread,
- debug->pass,
- depth);
- if (ret) {
- print:
- fprintf(stderr, "rw-lock %p ", lock);
- sync_array_cell_print(stderr, cell);
- rw_lock_debug_print(debug);
- return(TRUE);
+ if (((debug->lock_type == RW_LOCK_EX)
+ && !os_thread_eq(thread, cell->thread))
+ || ((debug->lock_type == RW_LOCK_WAIT_EX)
+ && !os_thread_eq(thread, cell->thread))
+ || (debug->lock_type == RW_LOCK_SHARED)) {
+
+ /* The (wait) x-lock request can block
+ infinitely only if someone (can be also cell
+ thread) is holding s-lock, or someone
+ (cannot be cell thread) (wait) x-lock, and
+ he is blocked by start thread */
+
+ ret = sync_array_deadlock_step(
+ arr, start, thread, debug->pass,
+ depth);
+ if (ret) {
+print:
+ fprintf(stderr, "rw-lock %p ",
+ (void*) lock);
+ sync_array_cell_print(stderr, cell);
+ rw_lock_debug_print(debug);
+ return(TRUE);
+ }
}
- }
- debug = UT_LIST_GET_NEXT(list, debug);
- }
+ debug = UT_LIST_GET_NEXT(list, debug);
+ }
- return(FALSE);
+ return(FALSE);
} else if (cell->request_type == RW_LOCK_SHARED) {
- lock = cell->wait_object;
- debug = UT_LIST_GET_FIRST(lock->debug_list);
-
- while (debug != NULL) {
-
- thread = debug->thread_id;
+ lock = cell->wait_object;
+ debug = UT_LIST_GET_FIRST(lock->debug_list);
- if ((debug->lock_type == RW_LOCK_EX)
- || (debug->lock_type == RW_LOCK_WAIT_EX)) {
+ while (debug != NULL) {
- /* The s-lock request can block infinitely only if
- someone (can also be cell thread) is holding (wait)
- x-lock, and he is blocked by start thread */
+ thread = debug->thread_id;
- ret = sync_array_deadlock_step(arr, start, thread,
- debug->pass,
- depth);
- if (ret) {
- goto print;
+ if ((debug->lock_type == RW_LOCK_EX)
+ || (debug->lock_type == RW_LOCK_WAIT_EX)) {
+
+ /* The s-lock request can block infinitely
+ only if someone (can also be cell thread) is
+ holding (wait) x-lock, and he is blocked by
+ start thread */
+
+ ret = sync_array_deadlock_step(
+ arr, start, thread, debug->pass,
+ depth);
+ if (ret) {
+ goto print;
+ }
}
- }
- debug = UT_LIST_GET_NEXT(list, debug);
- }
+ debug = UT_LIST_GET_NEXT(list, debug);
+ }
- return(FALSE);
+ return(FALSE);
} else {
ut_error;
}
- return(TRUE); /* Execution never reaches this line: for compiler
+ return(TRUE); /* Execution never reaches this line: for compiler
fooling only */
}
#endif /* UNIV_SYNC_DEBUG */
@@ -724,7 +804,7 @@
{
mutex_t* mutex;
rw_lock_t* lock;
-
+
if (cell->request_type == SYNC_MUTEX) {
mutex = cell->wait_object;
@@ -736,15 +816,15 @@
} else if (cell->request_type == RW_LOCK_EX) {
- lock = cell->wait_object;
+ lock = cell->wait_object;
- if (rw_lock_get_reader_count(lock) == 0
+ if (rw_lock_get_reader_count(lock) == 0
&& rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
return(TRUE);
}
- if (rw_lock_get_reader_count(lock) == 0
+ if (rw_lock_get_reader_count(lock) == 0
&& rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX
&& os_thread_eq(lock->writer_thread, cell->thread)) {
@@ -752,10 +832,10 @@
}
} else if (cell->request_type == RW_LOCK_SHARED) {
- lock = cell->wait_object;
+ lock = cell->wait_object;
if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
-
+
return(TRUE);
}
}
@@ -763,95 +843,154 @@
return(FALSE);
}
-/**********************************************************************
-Frees the cell. NOTE! sync_array_wait_event frees the cell
-automatically! */
+/**************************************************************************
+Looks for the cells in the wait array which refer to the wait object
+specified, and sets their corresponding events to the signaled state. In this
+way releases the threads waiting for the object to contend for the object.
+It is possible that no such cell is found, in which case does nothing. */
void
-sync_array_free_cell(
-/*=================*/
+sync_array_signal_object(
+/*=====================*/
sync_array_t* arr, /* in: wait array */
- ulint index) /* in: index of the cell in array */
+ void* object) /* in: wait object */
{
- sync_cell_t* cell;
-
- sync_array_enter(arr);
+ sync_cell_t* cell;
+ ulint count;
+ ulint i;
+ ulint res_count;
- cell = sync_array_get_nth_cell(arr, index);
+ /* We store the addresses of cells we need to signal and signal
+ them only after we have released the sync array's mutex (for
+ performance reasons). cell_count is the number of such cells, and
+ cell_ptr points to the first one. If there are less than
+ UT_ARR_SIZE(cells) of them, cell_ptr == &cells[0], otherwise
+ cell_ptr points to malloc'd memory that we must free. */
+
+ sync_cell_t* cells[100];
+ sync_cell_t** cell_ptr = &cells[0];
+ ulint cell_count = 0;
+ ulint cell_max_count = UT_ARR_SIZE(cells);
- ut_a(cell->wait_object != NULL);
+ ut_a(100 == cell_max_count);
- cell->waiting = FALSE;
- cell->wait_object = NULL;
+ sync_array_enter(arr);
- ut_a(arr->n_reserved > 0);
- arr->n_reserved--;
+ arr->sg_count++;
- sync_array_exit(arr);
-}
+ i = 0;
+ count = 0;
-/**************************************************************************
-Increments the signalled count. */
+ /* We need to store this to a local variable because it is modified
+ inside the loop */
+ res_count = arr->n_reserved;
-void
-sync_array_object_signalled(
-/*========================*/
- sync_array_t* arr) /* in: wait array */
-{
- sync_array_enter(arr);
+ while (count < res_count) {
- arr->sg_count++;
+ cell = sync_array_get_nth_cell(arr, i);
+
+ if (cell->state == SC_RESERVED) {
+
+ count++;
+ if (cell->wait_object == object) {
+ cell->state = SC_WAKING_UP;
+
+ ut_a(arr->n_reserved > 0);
+ arr->n_reserved--;
+
+ if (cell_count == cell_max_count) {
+ sync_cell_t** old_cell_ptr = cell_ptr;
+ size_t old_size, new_size;
+
+ old_size = cell_max_count
+ * sizeof(sync_cell_t*);
+ cell_max_count *= 2;
+ new_size = cell_max_count
+ * sizeof(sync_cell_t*);
+
+ cell_ptr = malloc(new_size);
+ ut_a(cell_ptr);
+ memcpy(cell_ptr, old_cell_ptr,
+ old_size);
+
+ if (old_cell_ptr != &cells[0]) {
+ free(old_cell_ptr);
+ }
+ }
+
+ cell_ptr[cell_count] = cell;
+ cell_count++;
+ }
+ }
+
+ i++;
+ }
+
+ sync_array_exit(arr);
- sync_array_exit(arr);
+ for (i = 0; i < cell_count; i++) {
+ cell = cell_ptr[i];
+
+ cell->event_set = TRUE;
+ os_event_set(cell->event);
+ }
+
+ if (cell_ptr != &cells[0]) {
+ free(cell_ptr);
+ }
}
/**************************************************************************
If the wakeup algorithm does not work perfectly at semaphore relases,
this function will do the waking (see the comment in mutex_exit). This
-function should be called about every 1 second in the server. */
+function should be called about every 1 second in the server.
+
+Note that there's a race condition between this thread and mutex_exit
+changing the lock_word and calling signal_object, so sometimes this finds
+threads to wake up even when nothing has gone wrong. */
void
sync_arr_wake_threads_if_sema_free(void)
/*====================================*/
{
- sync_array_t* arr = sync_primary_wait_array;
- sync_cell_t* cell;
- ulint count;
- ulint i;
+ sync_array_t* arr = sync_primary_wait_array;
+ sync_cell_t* cell;
+ ulint count;
+ ulint i;
+ ulint res_count;
- sync_array_enter(arr);
+ sync_array_enter(arr);
i = 0;
count = 0;
- while (count < arr->n_reserved) {
+ /* We need to store this to a local variable because it is modified
+ inside the loop */
- cell = sync_array_get_nth_cell(arr, i);
+ res_count = arr->n_reserved;
- if (cell->wait_object != NULL) {
+ while (count < res_count) {
- count++;
+ cell = sync_array_get_nth_cell(arr, i);
- if (sync_arr_cell_can_wake_up(cell)) {
+ if (cell->state == SC_RESERVED) {
- if (cell->request_type == SYNC_MUTEX) {
- mutex_t* mutex;
+ count++;
- mutex = cell->wait_object;
- os_event_set(mutex->event);
- } else {
- rw_lock_t* lock;
+ if (sync_arr_cell_can_wake_up(cell)) {
+ cell->state = SC_WAKING_UP;
+ cell->event_set = TRUE;
+ os_event_set(cell->event);
- lock = cell->wait_object;
- os_event_set(lock->event);
- }
- }
- }
+ ut_a(arr->n_reserved > 0);
+ arr->n_reserved--;
+ }
+ }
- i++;
- }
+ i++;
+ }
- sync_array_exit(arr);
+ sync_array_exit(arr);
}
/**************************************************************************
@@ -863,36 +1002,37 @@
/* out: TRUE if fatal semaphore wait threshold
was exceeded */
{
- sync_cell_t* cell;
- ibool old_val;
+ sync_cell_t* cell;
+ ibool old_val;
ibool noticed = FALSE;
- ulint i;
+ ulint i;
ulint fatal_timeout = srv_fatal_semaphore_wait_threshold;
ibool fatal = FALSE;
- for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
+ for (i = 0; i < sync_primary_wait_array->n_cells; i++) {
- cell = sync_array_get_nth_cell(sync_primary_wait_array, i);
+ cell = sync_array_get_nth_cell(sync_primary_wait_array, i);
- if (cell->wait_object != NULL && cell->waiting
+ if ((cell->state != SC_FREE)
&& difftime(time(NULL), cell->reservation_time) > 240) {
fputs("InnoDB: Warning: a long semaphore wait:\n",
- stderr);
+ stderr);
sync_array_cell_print(stderr, cell);
noticed = TRUE;
- }
+ }
- if (cell->wait_object != NULL && cell->waiting
+ if ((cell->state != SC_FREE)
&& difftime(time(NULL), cell->reservation_time)
> fatal_timeout) {
fatal = TRUE;
- }
- }
+ }
+ }
if (noticed) {
fprintf(stderr,
-"InnoDB: ###### Starts InnoDB Monitor for 30 secs to print diagnostic info:\n");
- old_val = srv_print_innodb_monitor;
+ "InnoDB: ###### Starts InnoDB Monitor"
+ " for 30 secs to print diagnostic info:\n");
+ old_val = srv_print_innodb_monitor;
/* If some crucial semaphore is reserved, then also the InnoDB
Monitor can hang, and we do not get diagnostics. Since in
@@ -901,17 +1041,19 @@
now the values of pending calls of these. */
fprintf(stderr,
-"InnoDB: Pending preads %lu, pwrites %lu\n", (ulong)os_file_n_pending_preads,
- (ulong)os_file_n_pending_pwrites);
+ "InnoDB: Pending preads %lu, pwrites %lu\n",
+ (ulong)os_file_n_pending_preads,
+ (ulong)os_file_n_pending_pwrites);
- srv_print_innodb_monitor = TRUE;
+ srv_print_innodb_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
- os_thread_sleep(30000000);
+ os_thread_sleep(30000000);
- srv_print_innodb_monitor = old_val;
+ srv_print_innodb_monitor = old_val;
fprintf(stderr,
-"InnoDB: ###### Diagnostic info printed to the standard error stream\n");
+ "InnoDB: ###### Diagnostic info printed"
+ " to the standard error stream\n");
}
return(fatal);
@@ -927,27 +1069,22 @@
sync_array_t* arr) /* in: wait array; NOTE! caller must own the
mutex */
{
- sync_cell_t* cell;
- ulint count;
- ulint i;
+ sync_cell_t* cell;
+ ulint i;
fprintf(file,
- "OS WAIT ARRAY INFO: reservation count %ld, signal count %ld\n",
- (long) arr->res_count, (long) arr->sg_count);
- i = 0;
- count = 0;
+ "OS WAIT ARRAY INFO: reservation count %ld,"
+ " signal count %ld\n",
+ (long) arr->res_count,
+ (long) arr->sg_count);
+ for (i = 0; i < arr->n_cells; i++) {
- while (count < arr->n_reserved) {
+ cell = sync_array_get_nth_cell(arr, i);
- cell = sync_array_get_nth_cell(arr, i);
-
- if (cell->wait_object != NULL) {
- count++;
+ if (cell->state != SC_FREE) {
sync_array_cell_print(file, cell);
- }
-
- i++;
- }
+ }
+ }
}
/**************************************************************************
@@ -959,10 +1096,10 @@
FILE* file, /* in: file where to print */
sync_array_t* arr) /* in: wait array */
{
- sync_array_enter(arr);
+ sync_array_enter(arr);
sync_array_output_info(file, arr);
-
- sync_array_exit(arr);
+
+ sync_array_exit(arr);
}
--- 1.19.3.1/innobase/sync/sync0rw.c 2007-01-17 16:44:05 -07:00
+++ 1.30/storage/innobase/sync/sync0rw.c 2007-01-17 17:18:03 -07:00
@@ -90,25 +90,27 @@
/*================*/
rw_lock_t* lock, /* in: pointer to memory */
#ifdef UNIV_DEBUG
+# ifdef UNIV_SYNC_DEBUG
+ ulint level, /* in: level */
+# endif /* UNIV_SYNC_DEBUG */
const char* cmutex_name, /* in: mutex name */
#endif /* UNIV_DEBUG */
const char* cfile_name, /* in: file name where created */
- ulint cline) /* in: file line where created */
+ ulint cline) /* in: file line where created */
{
- /* If this is the very first time a synchronization
- object is created, then the following call initializes
- the sync system. */
+ /* If this is the very first time a synchronization object is
+ created, then the following call initializes the sync system. */
- mutex_create(rw_lock_get_mutex(lock));
- mutex_set_level(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
+ mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
lock->mutex.cfile_name = cfile_name;
lock->mutex.cline = cline;
+
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
lock->mutex.cmutex_name = cmutex_name;
lock->mutex.mutex_type = 1;
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
-
+
rw_lock_set_waiters(lock, 0);
rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
lock->writer_count = 0;
@@ -119,10 +121,11 @@
#ifdef UNIV_SYNC_DEBUG
UT_LIST_INIT(lock->debug_list);
- lock->level = SYNC_LEVEL_NONE;
+ lock->level = level;
#endif /* UNIV_SYNC_DEBUG */
+
lock->magic_n = RW_LOCK_MAGIC_N;
-
+
lock->cfile_name = cfile_name;
lock->cline = cline;
@@ -130,13 +133,12 @@
lock->last_x_file_name = "not yet reserved";
lock->last_s_line = 0;
lock->last_x_line = 0;
- lock->event = os_event_create(NULL);
mutex_enter(&rw_lock_list_mutex);
-
+
if (UT_LIST_GET_LEN(rw_lock_list) > 0) {
ut_a(UT_LIST_GET_FIRST(rw_lock_list)->magic_n
- == RW_LOCK_MAGIC_N);
+ == RW_LOCK_MAGIC_N);
}
UT_LIST_ADD_FIRST(list, rw_lock_list, lock);
@@ -160,13 +162,12 @@
ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
ut_a(rw_lock_get_waiters(lock) == 0);
ut_a(rw_lock_get_reader_count(lock) == 0);
-
+
lock->magic_n = 0;
mutex_free(rw_lock_get_mutex(lock));
mutex_enter(&rw_lock_list_mutex);
- os_event_free(lock->event);
if (UT_LIST_GET_PREV(list, lock)) {
ut_a(UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N);
@@ -202,7 +203,7 @@
ut_a((rw_lock_get_waiters(lock) == 0)
|| (rw_lock_get_waiters(lock) == 1));
ut_a((lock->writer != RW_LOCK_EX) || (lock->writer_count > 0));
-
+
mutex_exit(rw_lock_get_mutex(lock));
return(TRUE);
@@ -217,31 +218,31 @@
void
rw_lock_s_lock_spin(
/*================*/
- rw_lock_t* lock, /* in: pointer to rw-lock */
+ rw_lock_t* lock, /* in: pointer to rw-lock */
ulint pass, /* in: pass value; != 0, if the lock
will be passed to another thread to unlock */
const char* file_name, /* in: file name where lock requested */
ulint line) /* in: line where requested */
{
- ulint index; /* index of the reserved wait cell */
- ulint i; /* spin round count */
-
- ut_ad(rw_lock_validate(lock));
+ ulint index; /* index of the reserved wait cell */
+ ulint i; /* spin round count */
+
+ ut_ad(rw_lock_validate(lock));
lock_loop:
rw_s_spin_wait_count++;
/* Spin waiting for the writer field to become free */
- i = 0;
+ i = 0;
- while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED
- && i < SYNC_SPIN_ROUNDS) {
- if (srv_spin_wait_delay) {
- ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
- }
+ while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED
+ && i < SYNC_SPIN_ROUNDS) {
+ if (srv_spin_wait_delay) {
+ ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
+ }
- i++;
- }
+ i++;
+ }
if (i == SYNC_SPIN_ROUNDS) {
os_thread_yield();
@@ -249,14 +250,16 @@
if (srv_print_latch_waits) {
fprintf(stderr,
- "Thread %lu spin wait rw-s-lock at %p cfile %s cline %lu rnds %lu\n",
- (ulong) os_thread_pf(os_thread_get_curr_id()), lock,
- lock->cfile_name, (ulong) lock->cline, (ulong) i);
+ "Thread %lu spin wait rw-s-lock at %p"
+ " cfile %s cline %lu rnds %lu\n",
+ (ulong) os_thread_pf(os_thread_get_curr_id()),
+ (void*) lock,
+ lock->cfile_name, (ulong) lock->cline, (ulong) i);
}
mutex_enter(rw_lock_get_mutex(lock));
- /* We try once again to obtain the lock */
+ /* We try once again to obtain the lock */
if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
mutex_exit(rw_lock_get_mutex(lock));
@@ -268,10 +271,10 @@
rw_s_system_call_count++;
- sync_array_reserve_cell(sync_primary_wait_array,
- lock, RW_LOCK_SHARED,
- file_name, line,
- &index);
+ sync_array_reserve_cell(sync_primary_wait_array,
+ lock, RW_LOCK_SHARED,
+ file_name, line,
+ &index);
rw_lock_set_waiters(lock, 1);
@@ -279,18 +282,20 @@
if (srv_print_latch_waits) {
fprintf(stderr,
- "Thread %lu OS wait rw-s-lock at %p cfile %s cline %lu\n",
+ "Thread %lu OS wait rw-s-lock at %p"
+ " cfile %s cline %lu\n",
os_thread_pf(os_thread_get_curr_id()),
- lock, lock->cfile_name, (ulong) lock->cline);
+ (void*) lock, lock->cfile_name,
+ (ulong) lock->cline);
}
rw_s_system_call_count++;
rw_s_os_wait_count++;
- sync_array_wait_event(sync_primary_wait_array, index);
+ sync_array_wait_event(sync_primary_wait_array, index);
- goto lock_loop;
- }
+ goto lock_loop;
+ }
}
/**********************************************************************
@@ -328,7 +333,7 @@
/* out: RW_LOCK_NOT_LOCKED if did
not succeed, RW_LOCK_EX if success,
RW_LOCK_WAIT_EX, if got wait reservation */
- rw_lock_t* lock, /* in: pointer to rw-lock */
+ rw_lock_t* lock, /* in: pointer to rw-lock */
ulint pass, /* in: pass value; != 0, if the lock will
be passed to another thread to unlock */
const char* file_name,/* in: file name where lock requested */
@@ -340,19 +345,19 @@
if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
if (rw_lock_get_reader_count(lock) == 0) {
-
+
rw_lock_set_writer(lock, RW_LOCK_EX);
lock->writer_thread = os_thread_get_curr_id();
lock->writer_count++;
lock->pass = pass;
-
+
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info(lock, pass, RW_LOCK_EX,
- file_name, line);
+ file_name, line);
#endif
lock->last_x_file_name = file_name;
lock->last_x_line = line;
-
+
/* Locking succeeded, we may return */
return(RW_LOCK_EX);
} else {
@@ -364,7 +369,7 @@
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info(lock, pass, RW_LOCK_WAIT_EX,
- file_name, line);
+ file_name, line);
#endif
return(RW_LOCK_WAIT_EX);
@@ -372,7 +377,7 @@
} else if ((rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX)
&& os_thread_eq(lock->writer_thread,
- os_thread_get_curr_id())) {
+ os_thread_get_curr_id())) {
if (rw_lock_get_reader_count(lock) == 0) {
@@ -384,9 +389,9 @@
#ifdef UNIV_SYNC_DEBUG
rw_lock_remove_debug_info(lock, pass, RW_LOCK_WAIT_EX);
rw_lock_add_debug_info(lock, pass, RW_LOCK_EX,
- file_name, line);
+ file_name, line);
#endif
-
+
lock->last_x_file_name = file_name;
lock->last_x_line = line;
@@ -398,7 +403,7 @@
} else if ((rw_lock_get_writer(lock) == RW_LOCK_EX)
&& os_thread_eq(lock->writer_thread,
- os_thread_get_curr_id())
+ os_thread_get_curr_id())
&& (lock->pass == 0)
&& (pass == 0)) {
@@ -406,9 +411,9 @@
#ifdef UNIV_SYNC_DEBUG
rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, file_name,
- line);
+ line);
#endif
-
+
lock->last_x_file_name = file_name;
lock->last_x_line = line;
@@ -433,79 +438,80 @@
void
rw_lock_x_lock_func(
/*================*/
- rw_lock_t* lock, /* in: pointer to rw-lock */
+ rw_lock_t* lock, /* in: pointer to rw-lock */
ulint pass, /* in: pass value; != 0, if the lock will
be passed to another thread to unlock */
const char* file_name,/* in: file name where lock requested */
ulint line) /* in: line where requested */
{
- ulint index; /* index of the reserved wait cell */
- ulint state; /* lock state acquired */
- ulint i; /* spin round count */
-
- ut_ad(rw_lock_validate(lock));
+ ulint index; /* index of the reserved wait cell */
+ ulint state; /* lock state acquired */
+ ulint i; /* spin round count */
+
+ ut_ad(rw_lock_validate(lock));
lock_loop:
- /* Acquire the mutex protecting the rw-lock fields */
+ /* Acquire the mutex protecting the rw-lock fields */
mutex_enter_fast(&(lock->mutex));
state = rw_lock_x_lock_low(lock, pass, file_name, line);
-
+
mutex_exit(&(lock->mutex));
-
+
if (state == RW_LOCK_EX) {
return; /* Locking succeeded */
} else if (state == RW_LOCK_NOT_LOCKED) {
- /* Spin waiting for the writer field to become free */
+ /* Spin waiting for the writer field to become free */
i = 0;
- while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED
- && i < SYNC_SPIN_ROUNDS) {
- if (srv_spin_wait_delay) {
+ while (rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED
+ && i < SYNC_SPIN_ROUNDS) {
+ if (srv_spin_wait_delay) {
ut_delay(ut_rnd_interval(0,
- srv_spin_wait_delay));
- }
-
- i++;
- }
+ srv_spin_wait_delay));
+ }
+
+ i++;
+ }
if (i == SYNC_SPIN_ROUNDS) {
os_thread_yield();
}
- } else if (state == RW_LOCK_WAIT_EX) {
+ } else if (state == RW_LOCK_WAIT_EX) {
- /* Spin waiting for the reader count field to become zero */
+ /* Spin waiting for the reader count field to become zero */
i = 0;
- while (rw_lock_get_reader_count(lock) != 0
- && i < SYNC_SPIN_ROUNDS) {
- if (srv_spin_wait_delay) {
+ while (rw_lock_get_reader_count(lock) != 0
+ && i < SYNC_SPIN_ROUNDS) {
+ if (srv_spin_wait_delay) {
ut_delay(ut_rnd_interval(0,
- srv_spin_wait_delay));
- }
+ srv_spin_wait_delay));
+ }
i++;
- }
+ }
if (i == SYNC_SPIN_ROUNDS) {
os_thread_yield();
}
- } else {
+ } else {
i = 0; /* Eliminate a compiler warning */
ut_error;
- }
+ }
if (srv_print_latch_waits) {
fprintf(stderr,
- "Thread %lu spin wait rw-x-lock at %p cfile %s cline %lu rnds %lu\n",
- os_thread_pf(os_thread_get_curr_id()), lock,
- lock->cfile_name, (ulong) lock->cline, (ulong) i);
+ "Thread %lu spin wait rw-x-lock at %p"
+ " cfile %s cline %lu rnds %lu\n",
+ os_thread_pf(os_thread_get_curr_id()), (void*) lock,
+ lock->cfile_name, (ulong) lock->cline, (ulong) i);
}
rw_x_spin_wait_count++;
- /* We try once again to obtain the lock. Acquire the mutex protecting
+ /* We try once again to obtain the lock. Acquire the mutex protecting
the rw-lock fields */
mutex_enter(rw_lock_get_mutex(lock));
@@ -520,7 +526,7 @@
rw_x_system_call_count++;
- sync_array_reserve_cell(sync_primary_wait_array,
+ sync_array_reserve_cell(sync_primary_wait_array,
lock, RW_LOCK_EX,
file_name, line,
&index);
@@ -531,17 +537,18 @@
if (srv_print_latch_waits) {
fprintf(stderr,
- "Thread %lu OS wait for rw-x-lock at %p cfile %s cline %lu\n",
- os_thread_pf(os_thread_get_curr_id()), lock,
- lock->cfile_name, (ulong) lock->cline);
+ "Thread %lu OS wait for rw-x-lock at %p"
+ " cfile %s cline %lu\n",
+ os_thread_pf(os_thread_get_curr_id()), (void*) lock,
+ lock->cfile_name, (ulong) lock->cline);
}
rw_x_system_call_count++;
rw_x_os_wait_count++;
- sync_array_wait_event(sync_primary_wait_array, index);
+ sync_array_wait_event(sync_primary_wait_array, index);
- goto lock_loop;
+ goto lock_loop;
}
#ifdef UNIV_SYNC_DEBUG
@@ -558,7 +565,7 @@
{
loop:
if (0 == mutex_enter_nowait(&rw_lock_debug_mutex,
- __FILE__, __LINE__)) {
+ __FILE__, __LINE__)) {
return;
}
@@ -567,13 +574,13 @@
rw_lock_debug_waiters = TRUE;
if (0 == mutex_enter_nowait(&rw_lock_debug_mutex,
- __FILE__, __LINE__)) {
+ __FILE__, __LINE__)) {
return;
}
os_event_wait(rw_lock_debug_event);
- goto loop;
+ goto loop;
}
/**********************************************************************
@@ -613,19 +620,19 @@
rw_lock_debug_mutex_enter();
info->file_name = file_name;
- info->line = line;
+ info->line = line;
info->lock_type = lock_type;
info->thread_id = os_thread_get_curr_id();
info->pass = pass;
- UT_LIST_ADD_FIRST(list, lock->debug_list, info);
+ UT_LIST_ADD_FIRST(list, lock->debug_list, info);
rw_lock_debug_mutex_exit();
if ((pass == 0) && (lock_type != RW_LOCK_WAIT_EX)) {
sync_thread_add_level(lock, lock->level);
}
-}
+}
/**********************************************************************
Removes a debug information struct for an rw-lock. */
@@ -653,16 +660,16 @@
if ((pass == info->pass)
&& ((pass != 0)
|| os_thread_eq(info->thread_id,
- os_thread_get_curr_id()))
+ os_thread_get_curr_id()))
&& (info->lock_type == lock_type)) {
- /* Found! */
- UT_LIST_REMOVE(list, lock->debug_list, info);
+ /* Found! */
+ UT_LIST_REMOVE(list, lock->debug_list, info);
rw_lock_debug_mutex_exit();
- rw_lock_debug_free(info);
+ rw_lock_debug_free(info);
- return;
+ return;
}
info = UT_LIST_GET_NEXT(list, info);
@@ -672,18 +679,6 @@
}
#endif /* UNIV_SYNC_DEBUG */
-/**********************************************************************
-Sets the rw-lock latching level field. */
-
-void
-rw_lock_set_level(
-/*==============*/
- rw_lock_t* lock, /* in: rw-lock */
- ulint level) /* in: level */
-{
- lock->level = level;
-}
-
#ifdef UNIV_SYNC_DEBUG
/**********************************************************************
Checks if the thread has locked the rw-lock in the specified mode, with
@@ -713,9 +708,9 @@
&& (info->lock_type == lock_type)) {
mutex_exit(&(lock->mutex));
- /* Found! */
+ /* Found! */
- return(TRUE);
+ return(TRUE);
}
info = UT_LIST_GET_NEXT(list, info);
@@ -741,7 +736,7 @@
ut_ad(lock);
ut_ad(rw_lock_validate(lock));
-
+
mutex_enter(&(lock->mutex));
if (lock_type == RW_LOCK_SHARED) {
@@ -766,18 +761,19 @@
Prints debug info of currently locked rw-locks. */
void
-rw_lock_list_print_info(void)
-/*=========================*/
+rw_lock_list_print_info(
+/*====================*/
+ FILE* file) /* in: file where to print */
{
rw_lock_t* lock;
ulint count = 0;
rw_lock_debug_t* info;
-
+
mutex_enter(&rw_lock_list_mutex);
fputs("-------------\n"
- "RW-LATCH INFO\n"
- "-------------\n", stderr);
+ "RW-LATCH INFO\n"
+ "-------------\n", file);
lock = UT_LIST_GET_FIRST(rw_lock_list);
@@ -791,16 +787,16 @@
|| (rw_lock_get_reader_count(lock) != 0)
|| (rw_lock_get_waiters(lock) != 0)) {
- fprintf(stderr, "RW-LOCK: %p ", lock);
+ fprintf(file, "RW-LOCK: %p ", (void*) lock);
if (rw_lock_get_waiters(lock)) {
- fputs(" Waiters for the lock exist\n", stderr);
+ fputs(" Waiters for the lock exist\n", file);
} else {
- putc('\n', stderr);
+ putc('\n', file);
}
-
+
info = UT_LIST_GET_FIRST(lock->debug_list);
- while (info != NULL) {
+ while (info != NULL) {
rw_lock_debug_print(info);
info = UT_LIST_GET_NEXT(list, info);
}
@@ -810,7 +806,7 @@
lock = UT_LIST_GET_NEXT(list, lock);
}
- fprintf(stderr, "Total number of rw-locks %ld\n", count);
+ fprintf(file, "Total number of rw-locks %ld\n", count);
mutex_exit(&rw_lock_list_mutex);
}
@@ -823,11 +819,11 @@
rw_lock_t* lock) /* in: rw-lock */
{
rw_lock_debug_t* info;
-
+
fprintf(stderr,
"-------------\n"
"RW-LATCH INFO\n"
- "RW-LATCH: %p ", lock);
+ "RW-LATCH: %p ", (void*) lock);
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
|| (rw_lock_get_reader_count(lock) != 0)
@@ -838,9 +834,9 @@
} else {
putc('\n', stderr);
}
-
+
info = UT_LIST_GET_FIRST(lock->debug_list);
- while (info != NULL) {
+ while (info != NULL) {
rw_lock_debug_print(info);
info = UT_LIST_GET_NEXT(list, info);
}
@@ -857,11 +853,11 @@
{
ulint rwt;
- rwt = info->lock_type;
-
+ rwt = info->lock_type;
+
fprintf(stderr, "Locked: thread %ld file %s line %ld ",
(ulong) os_thread_pf(info->thread_id), info->file_name,
- (ulong) info->line);
+ (ulong) info->line);
if (rwt == RW_LOCK_SHARED) {
fputs("S-LOCK", stderr);
} else if (rwt == RW_LOCK_EX) {
@@ -887,7 +883,7 @@
{
rw_lock_t* lock;
ulint count = 0;
-
+
mutex_enter(&rw_lock_list_mutex);
lock = UT_LIST_GET_FIRST(rw_lock_list);
@@ -896,7 +892,7 @@
mutex_enter(rw_lock_get_mutex(lock));
if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
- || (rw_lock_get_reader_count(lock) != 0)) {
+ || (rw_lock_get_reader_count(lock) != 0)) {
count++;
}
--- 1.34.5.1/innobase/sync/sync0sync.c 2007-01-17 16:44:05 -07:00
+++ 1.47/storage/innobase/sync/sync0sync.c 2007-01-17 17:18:03 -07:00
@@ -27,7 +27,7 @@
provide efficient spin locks, but we cannot count on that.
Another reason for implementing a spin lock is that on multiprocessor systems
-it can be more efficient for a processor to run a loop waiting for the
+it can be more efficient for a processor to run a loop waiting for the
semaphore to be released than to switch to a different thread. A thread switch
takes 25 us on both platforms mentioned above. See Gray and Reuter's book
Transaction processing for background.
@@ -35,7 +35,7 @@
How long should the spin loop last before suspending the thread? On a
uniprocessor, spinning does not help at all, because if the thread owning the
mutex is not executing, it cannot be released. Spinning actually wastes
-resources.
+resources.
On a multiprocessor, we do not know if the thread owning the mutex is
executing or not. Thus it would make sense to spin as long as the operation
@@ -52,12 +52,12 @@
make sure that thread swithches due to mutex collisions are not frequent,
i.e., they do not happen every 100 us or so, because that wastes too much
resources. If the thread switches are not frequent, the 20 us wasted in spin
-loop is not too much.
+loop is not too much.
Empirical studies on the effect of spin time should be done for different
platforms.
-
+
IMPLEMENTATION OF THE MUTEX
===========================
@@ -105,11 +105,9 @@
or it reserves the mutex for itself. In any case, some thread (which may be
also some earlier thread, not necessarily the one currently holding the mutex)
will set the waiters field to 0 in mutex_exit, and then call
-sync_array_signal_object with the mutex as an argument.
+sync_array_signal_object with the mutex as an argument.
Q.E.D. */
-ulint sync_dummy = 0;
-
/* The number of system calls made in this module. Intended for performance
monitoring. */
@@ -133,6 +131,7 @@
typedef struct sync_level_struct sync_level_t;
typedef struct sync_thread_struct sync_thread_t;
+#ifdef UNIV_SYNC_DEBUG
/* The latch levels currently owned by threads are stored in this data
structure; the size of this array is OS_THREAD_MAX_N */
@@ -140,6 +139,7 @@
/* Mutex protecting sync_thread_level_arrays */
mutex_t sync_thread_mutex;
+#endif /* UNIV_SYNC_DEBUG */
/* Global list of database mutexes (not OS mutexes) created. */
ut_list_base_node_t mutex_list;
@@ -147,11 +147,10 @@
/* Mutex protecting the mutex_list variable */
mutex_t mutex_list_mutex;
+#ifdef UNIV_SYNC_DEBUG
/* Latching order checks start when this is set TRUE */
ibool sync_order_checks_on = FALSE;
-
-/* Dummy mutex used to implement mutex_fence */
-mutex_t dummy_mutex_for_fence;
+#endif /* UNIV_SYNC_DEBUG */
struct sync_thread_struct{
os_thread_id_t id; /* OS thread id */
@@ -204,55 +203,62 @@
mutex_t* mutex, /* in: pointer to memory */
#ifdef UNIV_DEBUG
const char* cmutex_name, /* in: mutex name */
+# ifdef UNIV_SYNC_DEBUG
+ ulint level, /* in: level */
+# endif /* UNIV_SYNC_DEBUG */
#endif /* UNIV_DEBUG */
const char* cfile_name, /* in: file name where created */
ulint cline) /* in: file line where created */
{
#if defined(_WIN32) && defined(UNIV_CAN_USE_X86_ASSEMBLER)
mutex_reset_lock_word(mutex);
-#else
+#else
os_fast_mutex_init(&(mutex->os_fast_mutex));
mutex->lock_word = 0;
#endif
- mutex->event = os_event_create(NULL);
mutex_set_waiters(mutex, 0);
+#ifdef UNIV_DEBUG
mutex->magic_n = MUTEX_MAGIC_N;
+#endif /* UNIV_DEBUG */
#ifdef UNIV_SYNC_DEBUG
mutex->line = 0;
mutex->file_name = "not yet reserved";
+ mutex->level = level;
#endif /* UNIV_SYNC_DEBUG */
- mutex->level = SYNC_LEVEL_NONE;
mutex->cfile_name = cfile_name;
mutex->cline = cline;
#ifndef UNIV_HOTBACKUP
mutex->count_os_wait = 0;
# ifdef UNIV_DEBUG
- 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_yield= 0;
+ 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_yield= 0;
# endif /* UNIV_DEBUG */
#endif /* !UNIV_HOTBACKUP */
-
+
/* Check that lock_word is aligned; this is important on Intel */
ut_ad(((ulint)(&(mutex->lock_word))) % 4 == 0);
/* NOTE! The very first mutexes are not put to the mutex list */
- if ((mutex == &mutex_list_mutex) || (mutex == &sync_thread_mutex)) {
+ if ((mutex == &mutex_list_mutex)
+#ifdef UNIV_SYNC_DEBUG
+ || (mutex == &sync_thread_mutex)
+#endif /* UNIV_SYNC_DEBUG */
+ ) {
- return;
+ return;
}
-
+
mutex_enter(&mutex_list_mutex);
- if (UT_LIST_GET_LEN(mutex_list) > 0) {
- ut_a(UT_LIST_GET_FIRST(mutex_list)->magic_n == MUTEX_MAGIC_N);
- }
+ ut_ad(UT_LIST_GET_LEN(mutex_list) == 0
+ || UT_LIST_GET_FIRST(mutex_list)->magic_n == MUTEX_MAGIC_N);
UT_LIST_ADD_FIRST(list, mutex_list, mutex);
@@ -269,40 +275,39 @@
/*=======*/
mutex_t* mutex) /* in: mutex */
{
-#ifdef UNIV_DEBUG
- ut_a(mutex_validate(mutex));
-#endif /* UNIV_DEBUG */
+ ut_ad(mutex_validate(mutex));
ut_a(mutex_get_lock_word(mutex) == 0);
ut_a(mutex_get_waiters(mutex) == 0);
-
- if (mutex != &mutex_list_mutex && mutex != &sync_thread_mutex) {
- mutex_enter(&mutex_list_mutex);
+ if (mutex != &mutex_list_mutex
+#ifdef UNIV_SYNC_DEBUG
+ && mutex != &sync_thread_mutex
+#endif /* UNIV_SYNC_DEBUG */
+ ) {
- if (UT_LIST_GET_PREV(list, mutex)) {
- ut_a(UT_LIST_GET_PREV(list, mutex)->magic_n
- == MUTEX_MAGIC_N);
- }
- if (UT_LIST_GET_NEXT(list, mutex)) {
- ut_a(UT_LIST_GET_NEXT(list, mutex)->magic_n
- == MUTEX_MAGIC_N);
- }
-
- UT_LIST_REMOVE(list, mutex_list, mutex);
+ mutex_enter(&mutex_list_mutex);
+
+ ut_ad(!UT_LIST_GET_PREV(list, mutex)
+ || UT_LIST_GET_PREV(list, mutex)->magic_n
+ == MUTEX_MAGIC_N);
+ ut_ad(!UT_LIST_GET_NEXT(list, mutex)
+ || UT_LIST_GET_NEXT(list, mutex)->magic_n
+ == MUTEX_MAGIC_N);
+
+ UT_LIST_REMOVE(list, mutex_list, mutex);
mutex_exit(&mutex_list_mutex);
}
- os_event_free(mutex->event);
-
-#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER)
+#if !defined(_WIN32) || !defined(UNIV_CAN_USE_X86_ASSEMBLER)
os_fast_mutex_free(&(mutex->os_fast_mutex));
#endif
/* If we free the mutex protecting the mutex list (freeing is
not necessary), we have to reset the magic number AFTER removing
it from the list. */
-
+#ifdef UNIV_DEBUG
mutex->magic_n = 0;
+#endif /* UNIV_DEBUG */
}
/************************************************************************
@@ -334,6 +339,7 @@
return(1);
}
+#ifdef UNIV_DEBUG
/**********************************************************************
Checks that the mutex has been initialized. */
@@ -347,6 +353,7 @@
return(TRUE);
}
+#endif /* UNIV_DEBUG */
/**********************************************************************
Sets the waiters field in a mutex. */
@@ -355,10 +362,10 @@
mutex_set_waiters(
/*==============*/
mutex_t* mutex, /* in: mutex */
- ulint n) /* in: value to set */
+ ulint n) /* in: value to set */
{
-volatile ulint* ptr; /* declared volatile to ensure that
- the value is stored to memory */
+ volatile ulint* ptr; /* declared volatile to ensure that
+ the value is stored to memory */
ut_ad(mutex);
ptr = &(mutex->waiters);
@@ -375,190 +382,180 @@
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 */
+ ulint index; /* index of the reserved wait cell */
+ ulint i; /* spin round count */
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
- ib_longlong lstart_time = 0, lfinish_time; /* for timing os_wait */
- ulint ltime_diff;
- ulint sec;
- ulint ms;
- uint timer_started = 0;
+ ib_longlong lstart_time = 0, lfinish_time; /* for timing os_wait */
+ ulint ltime_diff;
+ ulint sec;
+ ulint ms;
+ uint timer_started = 0;
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
- ut_ad(mutex);
+ ut_ad(mutex);
mutex_loop:
- i = 0;
+ i = 0;
-/* 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 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:
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
- mutex_spin_wait_count++;
- mutex->count_spin_loop++;
+ mutex_spin_wait_count++;
+ mutex->count_spin_loop++;
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
- 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));
- }
+ 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++;
- }
+ i++;
+ }
- if (i == SYNC_SPIN_ROUNDS)
- {
+ if (i == SYNC_SPIN_ROUNDS) {
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
- 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;
- }
+ 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;
+ }
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
- os_thread_yield();
- }
+ 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);
+ 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()), (void*) mutex,
+ mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
#endif
- mutex_spin_round_count += i;
+ mutex_spin_round_count += i;
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
- mutex->count_spin_rounds += i;
+ mutex->count_spin_rounds += i;
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
- 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
- goto finish_timing;
- }
+ 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. */
+
+ i++;
+
+ if (i < SYNC_SPIN_ROUNDS) {
+ goto spin_loop;
+ }
+
+ sync_array_reserve_cell(sync_primary_wait_array, mutex,
+ SYNC_MUTEX, file_name, line, &index);
+
+ 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);
- /* 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)
- {
- goto spin_loop;
- }
-
- sync_array_reserve_cell(sync_primary_wait_array, mutex,
- SYNC_MUTEX, file_name, line, &index);
-
- 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);
-
- /* 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 */
+ /* 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 */
- sync_array_free_cell(sync_primary_wait_array, index);
+ sync_array_free_cell_protected(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
#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);
+ fprintf(stderr, "Thread %lu spin wait succeeds at 2:"
+ " mutex at %p\n",
+ (ulong) os_thread_pf(os_thread_get_curr_id()),
+ (void*) mutex);
#endif
- goto finish_timing;
+ goto finish_timing;
+
+ /* 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. */
+ }
+ }
- /* 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. */
- }
- }
-
- /* 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. */
+ /* 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. */
#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);
+ 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()), (void*) mutex,
+ mutex->cfile_name, (ulong) mutex->cline, (ulong) i);
#endif
- mutex_system_call_count++;
- mutex_os_wait_count++;
+ mutex_system_call_count++;
+ mutex_os_wait_count++;
#ifndef UNIV_HOTBACKUP
- mutex->count_os_wait++;
+ mutex->count_os_wait++;
# ifdef UNIV_DEBUG
- /*
- !!!!! 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;
- }
+ /* !!!!! 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;
+ }
# endif /* UNIV_DEBUG */
#endif /* !UNIV_HOTBACKUP */
- sync_array_wait_event(sync_primary_wait_array, index);
- goto mutex_loop;
+ sync_array_wait_event(sync_primary_wait_array, index);
+ goto mutex_loop;
finish_timing:
#if defined UNIV_DEBUG && !defined UNIV_HOTBACKUP
- if (timed_mutexes == 1 && timer_started==1)
- {
- ut_usectime(&sec, &ms);
- lfinish_time= (ib_longlong)sec * 1000000 + ms;
-
- ltime_diff= (ulint) (lfinish_time - lstart_time);
- mutex->lspent_time += ltime_diff;
- if (mutex->lmax_spent_time < ltime_diff)
- {
- mutex->lmax_spent_time= ltime_diff;
- }
- }
+ if (timed_mutexes == 1 && timer_started==1) {
+ ut_usectime(&sec, &ms);
+ lfinish_time= (ib_longlong)sec * 1000000 + ms;
+
+ ltime_diff= (ulint) (lfinish_time - lstart_time);
+ mutex->lspent_time += ltime_diff;
+
+ if (mutex->lmax_spent_time < ltime_diff) {
+ mutex->lmax_spent_time= ltime_diff;
+ }
+ }
#endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
- return;
+ return;
}
/**********************************************************************
@@ -573,8 +570,8 @@
/* The memory order of resetting the waiters field and
signaling the object is important. See LEMMA 1 above. */
- os_event_set(mutex->event);
- sync_array_object_signalled(sync_primary_wait_array);
+
+ sync_array_signal_object(sync_primary_wait_array, mutex);
}
#ifdef UNIV_SYNC_DEBUG
@@ -594,9 +591,9 @@
sync_thread_add_level(mutex, mutex->level);
mutex->file_name = file_name;
- mutex->line = line;
+ mutex->line = line;
mutex->thread_id = os_thread_get_curr_id();
-}
+}
/**********************************************************************
Gets the debug information for a reserved mutex. */
@@ -616,23 +613,8 @@
*line = mutex->line;
*thread_id = mutex->thread_id;
}
-#endif /* UNIV_SYNC_DEBUG */
/**********************************************************************
-Sets the mutex latching level field. */
-
-void
-mutex_set_level(
-/*============*/
- mutex_t* mutex, /* in: mutex */
- ulint level) /* in: level */
-{
- mutex->level = level;
-}
-
-
-#ifdef UNIV_SYNC_DEBUG
-/**********************************************************************
Checks that the current thread owns the mutex. Works only in the debug
version. */
@@ -642,13 +624,13 @@
/* out: TRUE if owns */
mutex_t* mutex) /* in: mutex */
{
- ut_a(mutex_validate(mutex));
+ ut_ad(mutex_validate(mutex));
if (mutex_get_lock_word(mutex) != 1) {
return(FALSE);
}
-
+
if (!os_thread_eq(mutex->thread_id, os_thread_get_curr_id())) {
return(FALSE);
@@ -659,10 +641,11 @@
/**********************************************************************
Prints debug info of currently reserved mutexes. */
-
+static
void
-mutex_list_print_info(void)
-/*=======================*/
+mutex_list_print_info(
+/*==================*/
+ FILE* file) /* in: file where to print */
{
mutex_t* mutex;
const char* file_name;
@@ -671,8 +654,8 @@
ulint count = 0;
fputs("----------\n"
- "MUTEX INFO\n"
- "----------\n", stderr);
+ "MUTEX INFO\n"
+ "----------\n", file);
mutex_enter(&mutex_list_mutex);
@@ -682,19 +665,20 @@
count++;
if (mutex_get_lock_word(mutex) != 0) {
- mutex_get_debug_info(mutex, &file_name, &line,
- &thread_id);
- fprintf(stderr,
- "Locked mutex: addr %p thread %ld file %s line %ld\n",
- mutex, os_thread_pf(thread_id),
+ mutex_get_debug_info(mutex, &file_name, &line,
+ &thread_id);
+ fprintf(file,
+ "Locked mutex: addr %p thread %ld"
+ " file %s line %ld\n",
+ (void*) mutex, os_thread_pf(thread_id),
file_name, line);
}
mutex = UT_LIST_GET_NEXT(list, mutex);
}
- fprintf(stderr, "Total number of mutexes %ld\n", count);
-
+ fprintf(file, "Total number of mutexes %ld\n", count);
+
mutex_exit(&mutex_list_mutex);
}
@@ -739,7 +723,6 @@
{
return(mutex_n_reserved() + rw_lock_n_locked() == 0);
}
-#endif /* UNIV_SYNC_DEBUG */
/**********************************************************************
Gets the value in the nth slot in the thread level arrays. */
@@ -762,7 +745,7 @@
sync_thread_level_arrays_find_slot(void)
/*====================================*/
/* out: pointer to thread slot, NULL if not found */
-
+
{
sync_thread_t* slot;
os_thread_id_t id;
@@ -790,7 +773,7 @@
sync_thread_level_arrays_find_free(void)
/*====================================*/
/* out: pointer to thread slot */
-
+
{
sync_thread_t* slot;
ulint i;
@@ -852,8 +835,9 @@
mutex = slot->latch;
fprintf(stderr,
- "InnoDB error: sync levels should be > %lu but a level is %lu\n",
- (ulong) limit, (ulong) slot->level);
+ "InnoDB error: sync levels should be"
+ " > %lu but a level is %lu\n",
+ (ulong) limit, (ulong) slot->level);
if (mutex->magic_n == MUTEX_MAGIC_N) {
fprintf(stderr,
@@ -862,30 +846,30 @@
(ulong) mutex->cline);
if (mutex_get_lock_word(mutex) != 0) {
-#ifdef UNIV_SYNC_DEBUG
const char* file_name;
ulint line;
os_thread_id_t thread_id;
- mutex_get_debug_info(mutex,
- &file_name, &line, &thread_id);
+ mutex_get_debug_info(
+ mutex, &file_name,
+ &line, &thread_id);
fprintf(stderr,
- "InnoDB: Locked mutex: addr %p thread %ld file %s line %ld\n",
- mutex, os_thread_pf(thread_id), file_name, (ulong) line);
-#else /* UNIV_SYNC_DEBUG */
- fprintf(stderr,
- "InnoDB: Locked mutex: addr %p\n", mutex);
-#endif /* UNIV_SYNC_DEBUG */
+ "InnoDB: Locked mutex:"
+ " addr %p thread %ld"
+ " file %s line %ld\n",
+ (void*) mutex,
+ os_thread_pf(
+ thread_id),
+ file_name,
+ (ulong) line);
} else {
fputs("Not locked\n", stderr);
- }
+ }
} else {
-#ifdef UNIV_SYNC_DEBUG
rw_lock_print(lock);
-#endif /* UNIV_SYNC_DEBUG */
}
-
+
return(FALSE);
}
}
@@ -963,9 +947,10 @@
slot = sync_thread_levels_get_nth(arr, i);
- if (slot->latch != NULL && (!dict_mutex_allowed ||
- (slot->level != SYNC_DICT
- && slot->level != SYNC_DICT_OPERATION))) {
+ if (slot->latch != NULL
+ && (!dict_mutex_allowed
+ || (slot->level != SYNC_DICT
+ && slot->level != SYNC_DICT_OPERATION))) {
mutex_exit(&sync_thread_mutex);
ut_error;
@@ -999,14 +984,14 @@
sync_thread_add_level(
/*==================*/
void* latch, /* in: pointer to a mutex or an rw-lock */
- ulint level) /* in: level in the latching order; if SYNC_LEVEL_NONE,
- nothing is done */
+ ulint level) /* in: level in the latching order; if
+ SYNC_LEVEL_VARYING, nothing is done */
{
sync_level_t* array;
sync_level_t* slot;
sync_thread_t* thread_slot;
ulint i;
-
+
if (!sync_order_checks_on) {
return;
@@ -1014,15 +999,13 @@
if ((latch == (void*)&sync_thread_mutex)
|| (latch == (void*)&mutex_list_mutex)
-#ifdef UNIV_SYNC_DEBUG
|| (latch == (void*)&rw_lock_debug_mutex)
-#endif /* UNIV_SYNC_DEBUG */
|| (latch == (void*)&rw_lock_list_mutex)) {
return;
}
- if (level == SYNC_LEVEL_NONE) {
+ if (level == SYNC_LEVEL_VARYING) {
return;
}
@@ -1034,12 +1017,12 @@
if (thread_slot == NULL) {
/* We have to allocate the level array for a new thread */
array = ut_malloc(sizeof(sync_level_t) * SYNC_THREAD_N_LEVELS);
-
+
thread_slot = sync_thread_level_arrays_find_free();
-
- thread_slot->id = os_thread_get_curr_id();
+
+ thread_slot->id = os_thread_get_curr_id();
thread_slot->levels = array;
-
+
for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
slot = sync_thread_levels_get_nth(array, i);
@@ -1049,116 +1032,152 @@
}
array = thread_slot->levels;
-
+
/* NOTE that there is a problem with _NODE and _LEAF levels: if the
B-tree height changes, then a leaf can change to an internal node
or the other way around. We do not know at present if this can cause
unnecessary assertion failures below. */
- if (level == SYNC_NO_ORDER_CHECK) {
+ switch (level) {
+ case SYNC_NO_ORDER_CHECK:
+ case SYNC_EXTERN_STORAGE:
+ case SYNC_TREE_NODE_FROM_HASH:
/* Do no order checking */
-
- } else if (level == SYNC_MEM_POOL) {
+ break;
+ case SYNC_MEM_POOL:
ut_a(sync_thread_levels_g(array, SYNC_MEM_POOL));
- } else if (level == SYNC_MEM_HASH) {
+ break;
+ case SYNC_MEM_HASH:
ut_a(sync_thread_levels_g(array, SYNC_MEM_HASH));
- } else if (level == SYNC_RECV) {
+ break;
+ case SYNC_RECV:
ut_a(sync_thread_levels_g(array, SYNC_RECV));
- } else if (level == SYNC_LOG) {
+ break;
+ case SYNC_WORK_QUEUE:
+ ut_a(sync_thread_levels_g(array, SYNC_WORK_QUEUE));
+ break;
+ case SYNC_LOG:
ut_a(sync_thread_levels_g(array, SYNC_LOG));
- } else if (level == SYNC_THR_LOCAL) {
+ break;
+ case SYNC_THR_LOCAL:
ut_a(sync_thread_levels_g(array, SYNC_THR_LOCAL));
- } else if (level == SYNC_ANY_LATCH) {
+ break;
+ case SYNC_ANY_LATCH:
ut_a(sync_thread_levels_g(array, SYNC_ANY_LATCH));
- } else if (level == SYNC_TRX_SYS_HEADER) {
+ break;
+ case SYNC_TRX_SYS_HEADER:
ut_a(sync_thread_levels_g(array, SYNC_TRX_SYS_HEADER));
- } else if (level == SYNC_DOUBLEWRITE) {
+ break;
+ case SYNC_DOUBLEWRITE:
ut_a(sync_thread_levels_g(array, SYNC_DOUBLEWRITE));
- } else if (level == SYNC_BUF_BLOCK) {
+ break;
+ case SYNC_BUF_BLOCK:
ut_a((sync_thread_levels_contain(array, SYNC_BUF_POOL)
- && sync_thread_levels_g(array, SYNC_BUF_BLOCK - 1))
+ && sync_thread_levels_g(array, SYNC_BUF_BLOCK - 1))
|| sync_thread_levels_g(array, SYNC_BUF_BLOCK));
- } else if (level == SYNC_BUF_POOL) {
+ break;
+ case SYNC_BUF_POOL:
ut_a(sync_thread_levels_g(array, SYNC_BUF_POOL));
- } else if (level == SYNC_SEARCH_SYS) {
+ break;
+ case SYNC_SEARCH_SYS:
ut_a(sync_thread_levels_g(array, SYNC_SEARCH_SYS));
- } else if (level == SYNC_TRX_LOCK_HEAP) {
+ break;
+ case SYNC_TRX_LOCK_HEAP:
ut_a(sync_thread_levels_g(array, SYNC_TRX_LOCK_HEAP));
- } else if (level == SYNC_REC_LOCK) {
+ break;
+ case SYNC_REC_LOCK:
ut_a((sync_thread_levels_contain(array, SYNC_KERNEL)
- && sync_thread_levels_g(array, SYNC_REC_LOCK - 1))
+ && sync_thread_levels_g(array, SYNC_REC_LOCK - 1))
|| sync_thread_levels_g(array, SYNC_REC_LOCK));
- } else if (level == SYNC_KERNEL) {
+ break;
+ case SYNC_KERNEL:
ut_a(sync_thread_levels_g(array, SYNC_KERNEL));
- } else if (level == SYNC_IBUF_BITMAP) {
+ break;
+ case SYNC_IBUF_BITMAP:
ut_a((sync_thread_levels_contain(array, SYNC_IBUF_BITMAP_MUTEX)
- && sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1))
+ && sync_thread_levels_g(array, SYNC_IBUF_BITMAP - 1))
|| sync_thread_levels_g(array, SYNC_IBUF_BITMAP));
- } else if (level == SYNC_IBUF_BITMAP_MUTEX) {
+ break;
+ case SYNC_IBUF_BITMAP_MUTEX:
ut_a(sync_thread_levels_g(array, SYNC_IBUF_BITMAP_MUTEX));
- } else if (level == SYNC_FSP_PAGE) {
+ break;
+ case SYNC_FSP_PAGE:
ut_a(sync_thread_levels_contain(array, SYNC_FSP));
- } else if (level == SYNC_FSP) {
+ break;
+ case SYNC_FSP:
ut_a(sync_thread_levels_contain(array, SYNC_FSP)
|| sync_thread_levels_g(array, SYNC_FSP));
- } else if (level == SYNC_EXTERN_STORAGE) {
- ut_a(TRUE);
- } else if (level == SYNC_TRX_UNDO_PAGE) {
+ break;
+ case SYNC_TRX_UNDO_PAGE:
ut_a(sync_thread_levels_contain(array, SYNC_TRX_UNDO)
|| sync_thread_levels_contain(array, SYNC_RSEG)
|| sync_thread_levels_contain(array, SYNC_PURGE_SYS)
|| sync_thread_levels_g(array, SYNC_TRX_UNDO_PAGE));
- } else if (level == SYNC_RSEG_HEADER) {
+ break;
+ case SYNC_RSEG_HEADER:
ut_a(sync_thread_levels_contain(array, SYNC_RSEG));
- } else if (level == SYNC_RSEG_HEADER_NEW) {
+ break;
+ case SYNC_RSEG_HEADER_NEW:
ut_a(sync_thread_levels_contain(array, SYNC_KERNEL)
&& sync_thread_levels_contain(array, SYNC_FSP_PAGE));
- } else if (level == SYNC_RSEG) {
+ break;
+ case SYNC_RSEG:
ut_a(sync_thread_levels_g(array, SYNC_RSEG));
- } else if (level == SYNC_TRX_UNDO) {
+ break;
+ case SYNC_TRX_UNDO:
ut_a(sync_thread_levels_g(array, SYNC_TRX_UNDO));
- } else if (level == SYNC_PURGE_LATCH) {
+ break;
+ case SYNC_PURGE_LATCH:
ut_a(sync_thread_levels_g(array, SYNC_PURGE_LATCH));
- } else if (level == SYNC_PURGE_SYS) {
+ break;
+ case SYNC_PURGE_SYS:
ut_a(sync_thread_levels_g(array, SYNC_PURGE_SYS));
- } else if (level == SYNC_TREE_NODE) {
+ break;
+ case SYNC_TREE_NODE:
ut_a(sync_thread_levels_contain(array, SYNC_INDEX_TREE)
- || sync_thread_levels_contain(array, SYNC_DICT_OPERATION)
|| sync_thread_levels_g(array, SYNC_TREE_NODE - 1));
- } else if (level == SYNC_TREE_NODE_FROM_HASH) {
- ut_a(1);
- } else if (level == SYNC_TREE_NODE_NEW) {
+ break;
+ case SYNC_TREE_NODE_NEW:
ut_a(sync_thread_levels_contain(array, SYNC_FSP_PAGE)
|| sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
- } else if (level == SYNC_INDEX_TREE) {
+ break;
+ case SYNC_INDEX_TREE:
ut_a((sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
&& sync_thread_levels_contain(array, SYNC_FSP)
&& sync_thread_levels_g(array, SYNC_FSP_PAGE - 1))
|| sync_thread_levels_g(array, SYNC_TREE_NODE - 1));
- } else if (level == SYNC_IBUF_MUTEX) {
+ break;
+ case SYNC_IBUF_MUTEX:
ut_a(sync_thread_levels_g(array, SYNC_FSP_PAGE - 1));
- } else if (level == SYNC_IBUF_PESS_INSERT_MUTEX) {
+ break;
+ case SYNC_IBUF_PESS_INSERT_MUTEX:
ut_a(sync_thread_levels_g(array, SYNC_FSP - 1)
&& !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX));
- } else if (level == SYNC_IBUF_HEADER) {
+ break;
+ case SYNC_IBUF_HEADER:
ut_a(sync_thread_levels_g(array, SYNC_FSP - 1)
&& !sync_thread_levels_contain(array, SYNC_IBUF_MUTEX)
- && !sync_thread_levels_contain(array,
- SYNC_IBUF_PESS_INSERT_MUTEX));
- } else if (level == SYNC_DICT_AUTOINC_MUTEX) {
+ && !sync_thread_levels_contain(
+ array, SYNC_IBUF_PESS_INSERT_MUTEX));
+ break;
+ case SYNC_DICT_AUTOINC_MUTEX:
ut_a(sync_thread_levels_g(array, SYNC_DICT_AUTOINC_MUTEX));
- } else if (level == SYNC_DICT_OPERATION) {
+ break;
+ case SYNC_DICT_OPERATION:
ut_a(sync_thread_levels_g(array, SYNC_DICT_OPERATION));
- } else if (level == SYNC_DICT_HEADER) {
+ break;
+ case SYNC_DICT_HEADER:
ut_a(sync_thread_levels_g(array, SYNC_DICT_HEADER));
- } else if (level == SYNC_DICT) {
+ break;
+ case SYNC_DICT:
#ifdef UNIV_DEBUG
ut_a(buf_debug_prints
|| sync_thread_levels_g(array, SYNC_DICT));
#else /* UNIV_DEBUG */
ut_a(sync_thread_levels_g(array, SYNC_DICT));
#endif /* UNIV_DEBUG */
- } else {
+ break;
+ default:
ut_error;
}
@@ -1178,7 +1197,7 @@
mutex_exit(&sync_thread_mutex);
}
-
+
/**********************************************************************
Removes a latch from the thread level array if it is found there. */
@@ -1193,7 +1212,7 @@
sync_level_t* slot;
sync_thread_t* thread_slot;
ulint i;
-
+
if (!sync_order_checks_on) {
return(FALSE);
@@ -1201,9 +1220,7 @@
if ((latch == (void*)&sync_thread_mutex)
|| (latch == (void*)&mutex_list_mutex)
-#ifdef UNIV_SYNC_DEBUG
|| (latch == (void*)&rw_lock_debug_mutex)
-#endif /* UNIV_SYNC_DEBUG */
|| (latch == (void*)&rw_lock_list_mutex)) {
return(FALSE);
@@ -1222,7 +1239,7 @@
}
array = thread_slot->levels;
-
+
for (i = 0; i < SYNC_THREAD_N_LEVELS; i++) {
slot = sync_thread_levels_get_nth(array, i);
@@ -1242,7 +1259,8 @@
return(FALSE);
}
-
+#endif /* UNIV_SYNC_DEBUG */
+
/**********************************************************************
Initializes the synchronization data structures. */
@@ -1250,9 +1268,11 @@
sync_init(void)
/*===========*/
{
+#ifdef UNIV_SYNC_DEBUG
sync_thread_t* thread_slot;
ulint i;
-
+#endif /* UNIV_SYNC_DEBUG */
+
ut_a(sync_initialized == FALSE);
sync_initialized = TRUE;
@@ -1261,37 +1281,34 @@
mutex */
sync_primary_wait_array = sync_array_create(OS_THREAD_MAX_N,
- SYNC_ARRAY_OS_MUTEX);
-
+ SYNC_ARRAY_OS_MUTEX);
+#ifdef UNIV_SYNC_DEBUG
/* Create the thread latch level array where the latch levels
are stored for each OS thread */
sync_thread_level_arrays = ut_malloc(OS_THREAD_MAX_N
- * sizeof(sync_thread_t));
+ * sizeof(sync_thread_t));
for (i = 0; i < OS_THREAD_MAX_N; i++) {
thread_slot = sync_thread_level_arrays_get_nth(i);
thread_slot->levels = NULL;
}
-
- /* Init the mutex list and create the mutex to protect it. */
+#endif /* UNIV_SYNC_DEBUG */
+ /* Init the mutex list and create the mutex to protect it. */
UT_LIST_INIT(mutex_list);
- mutex_create(&mutex_list_mutex);
- mutex_set_level(&mutex_list_mutex, SYNC_NO_ORDER_CHECK);
+ mutex_create(&mutex_list_mutex, SYNC_NO_ORDER_CHECK);
+#ifdef UNIV_SYNC_DEBUG
+ mutex_create(&sync_thread_mutex, SYNC_NO_ORDER_CHECK);
+#endif /* UNIV_SYNC_DEBUG */
- mutex_create(&sync_thread_mutex);
- mutex_set_level(&sync_thread_mutex, SYNC_NO_ORDER_CHECK);
-
/* Init the rw-lock list and create the mutex to protect it. */
UT_LIST_INIT(rw_lock_list);
- mutex_create(&rw_lock_list_mutex);
- mutex_set_level(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK);
+ mutex_create(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK);
#ifdef UNIV_SYNC_DEBUG
- mutex_create(&rw_lock_debug_mutex);
- mutex_set_level(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK);
+ mutex_create(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK);
rw_lock_debug_event = os_event_create(NULL);
rw_lock_debug_waiters = FALSE;
@@ -1313,12 +1330,14 @@
mutex = UT_LIST_GET_FIRST(mutex_list);
while (mutex) {
- mutex_free(mutex);
+ mutex_free(mutex);
mutex = UT_LIST_GET_FIRST(mutex_list);
}
mutex_free(&mutex_list_mutex);
- mutex_free(&sync_thread_mutex);
+#ifdef UNIV_SYNC_DEBUG
+ mutex_free(&sync_thread_mutex);
+#endif /* UNIV_SYNC_DEBUG */
}
/***********************************************************************
@@ -1330,20 +1349,21 @@
FILE* file) /* in: file where to print */
{
#ifdef UNIV_SYNC_DEBUG
- fprintf(stderr, "Mutex exits %lu, rws exits %lu, rwx exits %lu\n",
+ fprintf(file, "Mutex exits %lu, rws exits %lu, rwx exits %lu\n",
mutex_exit_count, rw_s_exit_count, rw_x_exit_count);
#endif
fprintf(file,
-"Mutex spin waits %lu, rounds %lu, OS waits %lu\n"
-"RW-shared spins %lu, OS waits %lu; RW-excl spins %lu, OS waits %lu\n",
- (ulong) mutex_spin_wait_count,
- (ulong) mutex_spin_round_count,
- (ulong) mutex_os_wait_count,
- (ulong) rw_s_spin_wait_count,
- (ulong) rw_s_os_wait_count,
- (ulong) rw_x_spin_wait_count,
- (ulong) rw_x_os_wait_count);
+ "Mutex spin waits %lu, rounds %lu, OS waits %lu\n"
+ "RW-shared spins %lu, OS waits %lu;"
+ " RW-excl spins %lu, OS waits %lu\n",
+ (ulong) mutex_spin_wait_count,
+ (ulong) mutex_spin_round_count,
+ (ulong) mutex_os_wait_count,
+ (ulong) rw_s_spin_wait_count,
+ (ulong) rw_s_os_wait_count,
+ (ulong) rw_x_spin_wait_count,
+ (ulong) rw_x_os_wait_count);
}
/***********************************************************************
@@ -1355,9 +1375,9 @@
FILE* file) /* in: file where to print */
{
#ifdef UNIV_SYNC_DEBUG
- mutex_list_print_info();
+ mutex_list_print_info(file);
- rw_lock_list_print_info();
+ rw_lock_list_print_info(file);
#endif /* UNIV_SYNC_DEBUG */
sync_array_print_info(file, sync_primary_wait_array);
| Thread |
|---|
| • bk commit into 5.1 tree (tsmith:1.2403) | tim | 18 Jan |