-diff -r 174803e7e869 mysql-test/r/create.result
---- a/mysql-test/r/create.result Thu Sep 04 12:17:56 2008 -0700
-+++ b/mysql-test/r/create.result Thu Sep 04 12:20:19 2008 -0700
+diff -r 1a59073d658d mysql-test/r/create.result
+--- a/mysql-test/r/create.result Sat Sep 13 17:31:30 2008 -0700
++++ b/mysql-test/r/create.result Sat Sep 13 17:31:40 2008 -0700
@@ -1720,7 +1720,8 @@
`COMMAND` varchar(16) NOT NULL DEFAULT '',
`TIME` bigint(7) NOT NULL DEFAULT '0',
) ENGINE=MyISAM DEFAULT CHARSET=utf8
drop table t1;
create table t1 like information_schema.character_sets;
-diff -r 174803e7e869 patch_info/acc-pslist.info
---- /dev/null Thu Jan 01 00:00:00 1970 +0000
-+++ b/patch_info/acc-pslist.info Thu Sep 04 12:20:19 2008 -0700
-@@ -0,0 +1,6 @@
-+File=acc-pslist.patch
-+Name=Milliseconds in PROCESSLIST
-+Version=1.0
-+Author=Percona <info@percona.com>
-+License=GPL
-+Comment=
-diff -r 174803e7e869 sql/sql_show.cc
---- a/sql/sql_show.cc Thu Sep 04 12:17:56 2008 -0700
-+++ b/sql/sql_show.cc Thu Sep 04 12:20:19 2008 -0700
+diff -r 1a59073d658d sql/sql_show.cc
+--- a/sql/sql_show.cc Sat Sep 13 17:31:30 2008 -0700
++++ b/sql/sql_show.cc Sat Sep 13 17:31:40 2008 -0700
@@ -1803,7 +1803,7 @@
TABLE *table= tables->table;
CHARSET_INFO *cs= system_charset_info;
DBUG_ENTER("fill_process_list");
user= thd->security_ctx->master_access & PROCESS_ACL ?
-@@ -1861,8 +1861,8 @@
+@@ -1873,8 +1873,8 @@
table->field[4]->store(command_name[tmp->command].str,
command_name[tmp->command].length, cs);
/* MYSQL_TIME */
}
}
-@@ -5532,7 +5536,7 @@
+@@ -5531,7 +5535,7 @@
into it two numbers, based on modulus of base-10 numbers. In the ones
position is the number of decimals. Tens position is unused. In the
hundreds and thousands position is a two-digit decimal number representing
0<decimals<10 and 0<=length<100 .
@param
-@@ -6540,6 +6544,8 @@
+@@ -6539,6 +6543,8 @@
{"STATE", 64, MYSQL_TYPE_STRING, 0, 1, "State", SKIP_OPEN_TABLE},
{"INFO", PROCESS_LIST_INFO_WIDTH, MYSQL_TYPE_STRING, 0, 1, "Info",
SKIP_OPEN_TABLE},
--- /dev/null
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/include/sync0rw.h mysql-5.1.29-rc/storage/innobase/include/sync0rw.h
+--- mysql-5.1.29-rc_orig/storage/innobase/include/sync0rw.h 2008-10-12 06:54:14.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/include/sync0rw.h 2008-11-17 15:34:00.000000000 +0900
+@@ -328,7 +328,17 @@
+ Accessor functions for rw lock. */
+ UNIV_INLINE
+ ulint
+-rw_lock_get_waiters(
++rw_lock_get_s_waiters(
++/*==================*/
++ rw_lock_t* lock);
++UNIV_INLINE
++ulint
++rw_lock_get_x_waiters(
++/*==================*/
++ rw_lock_t* lock);
++UNIV_INLINE
++ulint
++rw_lock_get_wx_waiters(
+ /*================*/
+ rw_lock_t* lock);
+ UNIV_INLINE
+@@ -412,6 +422,11 @@
+ rw_lock_debug_t* info); /* in: debug struct */
+ #endif /* UNIV_SYNC_DEBUG */
+
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++/* This value means NOT_LOCKED */
++#define RW_LOCK_BIAS 0x00100000
++#endif
++
+ /* NOTE! The structure appears here only for the compiler to know its size.
+ Do not use its fields directly! The structure used in the spin lock
+ implementation of a read-write lock. Several threads may have a shared lock
+@@ -421,9 +436,9 @@
+ field. Then no new readers are allowed in. */
+
+ struct rw_lock_struct {
+- os_event_t event; /* Used by sync0arr.c for thread queueing */
+-
+-#ifdef __WIN__
++ /* Used by sync0arr.c for thread queueing */
++ os_event_t s_event; /* Used for s_lock */
++ os_event_t x_event; /* Used for x_lock */
+ os_event_t wait_ex_event; /* This windows specific event is
+ used by the thread which has set the
+ lock state to RW_LOCK_WAIT_EX. The
+@@ -431,30 +446,34 @@
+ thread will be the next one to proceed
+ once the current the event gets
+ signalled. See LEMMA 2 in sync0sync.c */
++
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ volatile lint lock_word; /* Used by using atomic builtin */
+ #endif
+
+- ulint reader_count; /* Number of readers who have locked this
++ volatile 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
++ volatile 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
+ RW_LOCK_NOT_LOCKED, otherwise. */
+- os_thread_id_t writer_thread;
++ volatile os_thread_id_t writer_thread;
+ /* Thread id of a possible writer thread */
+- ulint writer_count; /* Number of times the same thread has
++ volatile ulint writer_count; /* Number of times the same thread has
+ recursively locked the lock in the exclusive
+ mode */
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_t mutex; /* The mutex protecting rw_lock_struct */
++#endif
+ 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
+ asynchronous i/o). */
+- ulint waiters; /* This ulint is set to 1 if there are
+- waiters (readers or writers) in the global
+- wait array, waiting for this rw_lock.
+- Otherwise, == 0. */
++ volatile ulint s_waiters; /* 1: there are waiters (s_lock) */
++ volatile ulint x_waiters; /* 1: there are waiters (x_lock) */
++ volatile ulint wait_ex_waiters; /* 1: there are waiters (wait_ex) */
+ UT_LIST_NODE_T(rw_lock_t) list;
+ /* All allocated rw locks are put into a
+ list */
+@@ -467,7 +486,7 @@
+ const char* cfile_name;/* File name where lock 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 */
+- ibool writer_is_wait_ex;
++ volatile 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
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/include/sync0rw.ic mysql-5.1.29-rc/storage/innobase/include/sync0rw.ic
+--- mysql-5.1.29-rc_orig/storage/innobase/include/sync0rw.ic 2008-10-12 06:54:14.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/include/sync0rw.ic 2008-11-17 16:07:32.000000000 +0900
+@@ -47,20 +47,52 @@
+ Accessor functions for rw lock. */
+ UNIV_INLINE
+ ulint
+-rw_lock_get_waiters(
++rw_lock_get_s_waiters(
+ /*================*/
+ rw_lock_t* lock)
+ {
+- return(lock->waiters);
++ return(lock->s_waiters);
+ }
+ UNIV_INLINE
+-void
+-rw_lock_set_waiters(
++ulint
++rw_lock_get_x_waiters(
++/*================*/
++ rw_lock_t* lock)
++{
++ return(lock->x_waiters);
++}
++UNIV_INLINE
++ulint
++rw_lock_get_wx_waiters(
+ /*================*/
++ rw_lock_t* lock)
++{
++ return(lock->wait_ex_waiters);
++}
++UNIV_INLINE
++void
++rw_lock_set_s_waiters(
++ rw_lock_t* lock,
++ ulint flag)
++{
++ lock->s_waiters = flag;
++}
++UNIV_INLINE
++void
++rw_lock_set_x_waiters(
+ rw_lock_t* lock,
+ ulint flag)
+ {
+- lock->waiters = flag;
++ lock->x_waiters = flag;
++}
++UNIV_INLINE
++void
++rw_lock_set_wx_waiters(
++/*================*/
++ rw_lock_t* lock,
++ ulint flag)
++{
++ lock->wait_ex_waiters = flag;
+ }
+ UNIV_INLINE
+ ulint
+@@ -68,7 +100,19 @@
+ /*===============*/
+ rw_lock_t* lock)
+ {
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ if (lock->writer == RW_LOCK_NOT_LOCKED) {
++ return(RW_LOCK_NOT_LOCKED);
++ }
++
++ if (lock->writer_is_wait_ex) {
++ return(RW_LOCK_WAIT_EX);
++ } else {
++ return(RW_LOCK_EX);
++ }
++#else
+ return(lock->writer);
++#endif
+ }
+ UNIV_INLINE
+ void
+@@ -96,6 +140,7 @@
+ {
+ lock->reader_count = count;
+ }
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ UNIV_INLINE
+ mutex_t*
+ rw_lock_get_mutex(
+@@ -104,6 +149,7 @@
+ {
+ return(&(lock->mutex));
+ }
++#endif
+
+ /**********************************************************************
+ Returns the value of writer_count for the lock. Does not reserve the lock
+@@ -133,13 +179,27 @@
+ const char* file_name, /* in: file name where lock requested */
+ ulint line) /* in: line where requested */
+ {
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ ut_ad(mutex_own(rw_lock_get_mutex(lock)));
++#endif
+
+ /* Check if the writer field is free */
+
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ if (UNIV_LIKELY(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)) {
++ /* try s-lock */
++ if(__sync_sub_and_fetch(&(lock->lock_word),1) <= 0) {
++ /* fail */
++ __sync_fetch_and_add(&(lock->lock_word),1);
++ return(FALSE); /* locking did not succeed */
++ }
++ /* success */
++ __sync_fetch_and_add(&(lock->reader_count),1);
++#else
+ if (UNIV_LIKELY(lock->writer == RW_LOCK_NOT_LOCKED)) {
+ /* Set the shared lock by incrementing the reader count */
+ lock->reader_count++;
++#endif
+
+ #ifdef UNIV_SYNC_DEBUG
+ rw_lock_add_debug_info(lock, pass, RW_LOCK_SHARED, file_name,
+@@ -166,11 +226,15 @@
+ const char* file_name, /* in: file name where requested */
+ ulint line) /* in: line where lock requested */
+ {
+- ut_ad(lock->writer == RW_LOCK_NOT_LOCKED);
++ ut_ad(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
+ ut_ad(rw_lock_get_reader_count(lock) == 0);
+
+ /* Set the shared lock by incrementing the reader count */
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ __sync_fetch_and_add(&(lock->reader_count),1);
++#else
+ lock->reader_count++;
++#endif
+
+ lock->last_s_file_name = file_name;
+ lock->last_s_line = line;
+@@ -198,7 +262,11 @@
+
+ rw_lock_set_writer(lock, RW_LOCK_EX);
+ lock->writer_thread = os_thread_get_curr_id();
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ __sync_fetch_and_add(&(lock->writer_count),1);
++#else
+ lock->writer_count++;
++#endif
+ lock->pass = 0;
+
+ lock->last_x_file_name = file_name;
+@@ -240,15 +308,21 @@
+ ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
+ #endif /* UNIV_SYNC_DEBUG */
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_enter(rw_lock_get_mutex(lock));
++#endif
+
+ if (UNIV_LIKELY(rw_lock_s_lock_low(lock, pass, file_name, line))) {
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_exit(rw_lock_get_mutex(lock));
++#endif
+
+ return; /* Success */
+ } else {
+ /* Did not succeed, try spin wait */
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_exit(rw_lock_get_mutex(lock));
++#endif
+
+ rw_lock_s_lock_spin(lock, pass, file_name, line);
+
+@@ -271,11 +345,23 @@
+ {
+ ibool success = FALSE;
+
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
++ /* try s-lock */
++ if(__sync_sub_and_fetch(&(lock->lock_word),1) <= 0) {
++ /* fail */
++ __sync_fetch_and_add(&(lock->lock_word),1);
++ return(FALSE); /* locking did not succeed */
++ }
++ /* success */
++ __sync_fetch_and_add(&(lock->reader_count),1);
++#else
+ mutex_enter(rw_lock_get_mutex(lock));
+
+ if (lock->writer == RW_LOCK_NOT_LOCKED) {
+ /* Set the shared lock by incrementing the reader count */
+ lock->reader_count++;
++#endif
+
+ #ifdef UNIV_SYNC_DEBUG
+ rw_lock_add_debug_info(lock, 0, RW_LOCK_SHARED, file_name,
+@@ -288,7 +374,9 @@
+ success = TRUE;
+ }
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_exit(rw_lock_get_mutex(lock));
++#endif
+
+ return(success);
+ }
+@@ -308,6 +396,55 @@
+ {
+ ibool success = FALSE;
+ os_thread_id_t curr_thread = os_thread_get_curr_id();
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ if ((lock->lock_word == RW_LOCK_BIAS)
++ && rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
++ /* try x-lock */
++ if(__sync_sub_and_fetch(&(lock->lock_word),
++ RW_LOCK_BIAS) == 0) {
++ /* success */
++ /* try to lock writer */
++ if(__sync_lock_test_and_set(&(lock->writer),RW_LOCK_EX)
++ == RW_LOCK_NOT_LOCKED) {
++ /* success */
++ lock->writer_thread = curr_thread;
++ lock->pass = 0;
++ lock->writer_is_wait_ex = FALSE;
++ /* next function may work as memory barrier */
++ relock:
++ __sync_fetch_and_add(&(lock->writer_count),1);
++
++#ifdef UNIV_SYNC_DEBUG
++ rw_lock_add_debug_info(lock, 0, RW_LOCK_EX, file_name, line);
++#endif
++
++ lock->last_x_file_name = file_name;
++ lock->last_x_line = line;
++
++ ut_ad(rw_lock_validate(lock));
++
++ return(TRUE);
++ } else {
++ /* x-unlock */
++ __sync_fetch_and_add(&(lock->lock_word),
++ RW_LOCK_BIAS);
++ }
++ } else {
++ /* fail (x-lock) */
++ __sync_fetch_and_add(&(lock->lock_word),RW_LOCK_BIAS);
++ }
++ }
++
++ if (lock->pass == 0
++ && os_thread_eq(lock->writer_thread, curr_thread)
++ && rw_lock_get_writer(lock) == RW_LOCK_EX) {
++ goto relock;
++ }
++
++ ut_ad(rw_lock_validate(lock));
++
++ return(FALSE);
++#else
+ mutex_enter(rw_lock_get_mutex(lock));
+
+ if (UNIV_UNLIKELY(rw_lock_get_reader_count(lock) != 0)) {
+@@ -338,6 +475,7 @@
+ ut_ad(rw_lock_validate(lock));
+
+ return(success);
++#endif
+ }
+
+ /**********************************************************************
+@@ -353,16 +491,33 @@
+ #endif
+ )
+ {
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_t* mutex = &(lock->mutex);
+- ibool sg = FALSE;
++#endif
++ ibool x_sg = FALSE;
++ ibool wx_sg = FALSE;
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ ibool last = FALSE;
++#endif
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ /* Acquire the mutex protecting the rw-lock fields */
+ mutex_enter(mutex);
++#endif
+
+ /* Reset the shared lock by decrementing the reader count */
+
+ ut_a(lock->reader_count > 0);
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ /* unlock lock_word */
++ __sync_fetch_and_add(&(lock->lock_word),1);
++
++ if(__sync_sub_and_fetch(&(lock->reader_count),1) == 0) {
++ last = TRUE;
++ }
++#else
+ lock->reader_count--;
++#endif
+
+ #ifdef UNIV_SYNC_DEBUG
+ rw_lock_remove_debug_info(lock, pass, RW_LOCK_SHARED);
+@@ -371,20 +526,36 @@
+ /* If there may be waiters and this was the last s-lock,
+ signal the object */
+
+- if (UNIV_UNLIKELY(lock->waiters)
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ if (UNIV_UNLIKELY(last && lock->wait_ex_waiters)) {
++#else
++ if (UNIV_UNLIKELY(lock->wait_ex_waiters)
+ && lock->reader_count == 0) {
+- sg = TRUE;
++#endif
++ wx_sg = TRUE;
+
+- rw_lock_set_waiters(lock, 0);
++ rw_lock_set_wx_waiters(lock, 0);
+ }
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ else if (UNIV_UNLIKELY(last && lock->x_waiters)) {
++#else
++ else if (UNIV_UNLIKELY(lock->x_waiters)
++ && lock->reader_count == 0) {
++#endif
++ x_sg = TRUE;
+
++ rw_lock_set_x_waiters(lock, 0);
++ }
++
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_exit(mutex);
++#endif
+
+- if (UNIV_UNLIKELY(sg)) {
+-#ifdef __WIN__
++ if (UNIV_UNLIKELY(wx_sg)) {
+ os_event_set(lock->wait_ex_event);
+-#endif
+- os_event_set(lock->event);
++ sync_array_object_signalled(sync_primary_wait_array);
++ } else if (UNIV_UNLIKELY(x_sg)) {
++ os_event_set(lock->x_event);
+ sync_array_object_signalled(sync_primary_wait_array);
+ }
+
+@@ -408,13 +579,19 @@
+
+ ut_ad(lock->reader_count > 0);
+
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ __sync_sub_and_fetch(&(lock->reader_count),1);
++#else
+ lock->reader_count--;
++#endif
+
+ #ifdef UNIV_SYNC_DEBUG
+ rw_lock_remove_debug_info(lock, 0, RW_LOCK_SHARED);
+ #endif
+
+- ut_ad(!lock->waiters);
++ ut_ad(!lock->s_waiters);
++ ut_ad(!lock->x_waiters);
++ ut_ad(!lock->wait_ex_waiters);
+ ut_ad(rw_lock_validate(lock));
+ #ifdef UNIV_SYNC_PERF_STAT
+ rw_s_exit_count++;
+@@ -434,41 +611,81 @@
+ #endif
+ )
+ {
+- ibool sg = FALSE;
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ ibool last = FALSE;
++#endif
++ ibool s_sg = FALSE;
++ ibool x_sg = FALSE;
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ /* Acquire the mutex protecting the rw-lock fields */
+ mutex_enter(&(lock->mutex));
++#endif
+
+ /* Reset the exclusive lock if this thread no longer has an x-mode
+ lock */
+
+ ut_ad(lock->writer_count > 0);
+
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ if(__sync_sub_and_fetch(&(lock->writer_count),1) == 0) {
++ last = TRUE;
++ }
++
++ if (last) {
++ /* unlock lock_word */
++ __sync_fetch_and_add(&(lock->lock_word),RW_LOCK_BIAS);
++
++ /* FIXME: It is a value of bad manners for pthread.
++ But we shouldn't keep an ID of not-owner. */
++ lock->writer_thread = -1;
++
++ /* atomic operation may be safer about memory order. */
++ rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
++ __sync_synchronize();
++ }
++#else
+ lock->writer_count--;
+
+ if (lock->writer_count == 0) {
+ rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
+ }
++#endif
+
+ #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) {
+-
+- sg = TRUE;
+- rw_lock_set_waiters(lock, 0);
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ if (last) {
++#else
++ if (lock->writer_count == 0) {
++#endif
++ if(lock->s_waiters){
++ s_sg = TRUE;
++ rw_lock_set_s_waiters(lock, 0);
++ }
++ if(lock->x_waiters){
++ x_sg = TRUE;
++ rw_lock_set_x_waiters(lock, 0);
++ }
+ }
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_exit(&(lock->mutex));
++#endif
+
+- if (UNIV_UNLIKELY(sg)) {
++ if (UNIV_UNLIKELY(s_sg)) {
++ os_event_set(lock->s_event);
++ sync_array_object_signalled(sync_primary_wait_array);
++ }
++ if (UNIV_UNLIKELY(x_sg)) {
+ #ifdef __WIN__
++ /* I doubt the necessity of it. */
+ os_event_set(lock->wait_ex_event);
+ #endif
+- os_event_set(lock->event);
++ os_event_set(lock->x_event);
+ sync_array_object_signalled(sync_primary_wait_array);
+ }
+
+@@ -493,9 +710,13 @@
+
+ ut_ad(lock->writer_count > 0);
+
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ if(__sync_sub_and_fetch(&(lock->writer_count),1) == 0) {
++#else
+ lock->writer_count--;
+
+ if (lock->writer_count == 0) {
++#endif
+ rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
+ }
+
+@@ -503,7 +724,9 @@
+ rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
+ #endif
+
+- ut_ad(!lock->waiters);
++ ut_ad(!lock->s_waiters);
++ ut_ad(!lock->x_waiters);
++ ut_ad(!lock->wait_ex_waiters);
+ ut_ad(rw_lock_validate(lock));
+
+ #ifdef UNIV_SYNC_PERF_STAT
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/sync/sync0arr.c mysql-5.1.29-rc/storage/innobase/sync/sync0arr.c
+--- mysql-5.1.29-rc_orig/storage/innobase/sync/sync0arr.c 2008-10-12 06:54:15.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/sync/sync0arr.c 2008-11-17 16:17:39.000000000 +0900
+@@ -307,13 +307,13 @@
+ {
+ if (type == SYNC_MUTEX) {
+ return(os_event_reset(((mutex_t *) object)->event));
+-#ifdef __WIN__
+ } else if (type == RW_LOCK_WAIT_EX) {
+ return(os_event_reset(
+ ((rw_lock_t *) object)->wait_ex_event));
+-#endif
+- } else {
+- return(os_event_reset(((rw_lock_t *) object)->event));
++ } else if (type == RW_LOCK_SHARED) {
++ return(os_event_reset(((rw_lock_t *) object)->s_event));
++ } else { /* RW_LOCK_EX */
++ return(os_event_reset(((rw_lock_t *) object)->x_event));
+ }
+ }
+
+@@ -413,15 +413,12 @@
+
+ if (cell->request_type == SYNC_MUTEX) {
+ event = ((mutex_t*) cell->wait_object)->event;
+-#ifdef __WIN__
+- /* On windows if the thread about to wait is the one which
+- has set the state of the rw_lock to RW_LOCK_WAIT_EX, then
+- it waits on a special event i.e.: wait_ex_event. */
+ } else if (cell->request_type == RW_LOCK_WAIT_EX) {
+ event = ((rw_lock_t*) cell->wait_object)->wait_ex_event;
+-#endif
++ } else if (cell->request_type == RW_LOCK_SHARED) {
++ event = ((rw_lock_t*) cell->wait_object)->s_event;
+ } else {
+- event = ((rw_lock_t*) cell->wait_object)->event;
++ event = ((rw_lock_t*) cell->wait_object)->x_event;
+ }
+
+ cell->waiting = TRUE;
+@@ -462,6 +459,7 @@
+ mutex_t* mutex;
+ rw_lock_t* rwlock;
+ ulint type;
++ ulint writer;
+
+ type = cell->request_type;
+
+@@ -491,12 +489,10 @@
+ (ulong) mutex->waiters);
+
+ } else if (type == RW_LOCK_EX
+-#ifdef __WIN__
+ || type == RW_LOCK_WAIT_EX
+-#endif
+ || type == RW_LOCK_SHARED) {
+
+- fputs(type == RW_LOCK_EX ? "X-lock on" : "S-lock on", file);
++ fputs(type == RW_LOCK_SHARED ? "S-lock on" : "X-lock on", file);
+
+ rwlock = cell->old_wait_rw_lock;
+
+@@ -504,22 +500,24 @@
+ " RW-latch at %p created in file %s line %lu\n",
+ (void*) rwlock, rwlock->cfile_name,
+ (ulong) rwlock->cline);
+- if (rwlock->writer != RW_LOCK_NOT_LOCKED) {
++ writer = rw_lock_get_writer(rwlock);
++ if (writer != RW_LOCK_NOT_LOCKED) {
+ fprintf(file,
+ "a writer (thread id %lu) has"
+ " reserved it in mode %s",
+ (ulong) os_thread_pf(rwlock->writer_thread),
+- rwlock->writer == RW_LOCK_EX
++ writer == RW_LOCK_EX
+ ? " exclusive\n"
+ : " wait exclusive\n");
+ }
+
+ fprintf(file,
+- "number of readers %lu, waiters flag %lu\n"
++ "number of readers %lu, s_waiters flag %lu, x_waiters flag %lu\n"
+ "Last time read locked in file %s line %lu\n"
+ "Last time write locked in file %s line %lu\n",
+ (ulong) rwlock->reader_count,
+- (ulong) rwlock->waiters,
++ (ulong) rwlock->s_waiters,
++ (ulong) (rwlock->x_waiters || rwlock->wait_ex_waiters),
+ rwlock->last_s_file_name,
+ (ulong) rwlock->last_s_line,
+ rwlock->last_x_file_name,
+@@ -844,11 +842,15 @@
+ /*========================*/
+ sync_array_t* arr) /* in: wait array */
+ {
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ __sync_fetch_and_add(&(arr->sg_count),1);
++#else
+ sync_array_enter(arr);
+
+ arr->sg_count++;
+
+ sync_array_exit(arr);
++#endif
+ }
+
+ /**************************************************************************
+@@ -889,19 +891,23 @@
+
+ mutex = cell->wait_object;
+ os_event_set(mutex->event);
+-#ifdef __WIN__
+ } else if (cell->request_type
+ == RW_LOCK_WAIT_EX) {
+ rw_lock_t* lock;
+
+ lock = cell->wait_object;
+ os_event_set(lock->wait_ex_event);
+-#endif
+- } else {
++ } else if (cell->request_type
++ == RW_LOCK_SHARED) {
+ rw_lock_t* lock;
+
+ lock = cell->wait_object;
+- os_event_set(lock->event);
++ os_event_set(lock->s_event);
++ } else {
++ rw_lock_t* lock;
++
++ lock = cell->wait_object;
++ os_event_set(lock->x_event);
+ }
+ }
+ }
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/sync/sync0rw.c mysql-5.1.29-rc/storage/innobase/sync/sync0rw.c
+--- mysql-5.1.29-rc_orig/storage/innobase/sync/sync0rw.c 2008-10-12 06:54:15.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/sync/sync0rw.c 2008-11-17 17:43:45.000000000 +0900
+@@ -119,6 +119,7 @@
+ /* If this is the very first time a synchronization object is
+ created, then the following call initializes the sync system. */
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK);
+
+ lock->mutex.cfile_name = cfile_name;
+@@ -128,8 +129,14 @@
+ lock->mutex.cmutex_name = cmutex_name;
+ lock->mutex.mutex_type = 1;
+ #endif /* UNIV_DEBUG && !UNIV_HOTBACKUP */
++#endif /* !HAVE_GCC_ATOMIC_BUILTINS */
+
+- rw_lock_set_waiters(lock, 0);
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ lock->lock_word = RW_LOCK_BIAS;
++#endif
++ rw_lock_set_s_waiters(lock, 0);
++ rw_lock_set_x_waiters(lock, 0);
++ rw_lock_set_wx_waiters(lock, 0);
+ rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
+ lock->writer_count = 0;
+ rw_lock_set_reader_count(lock, 0);
+@@ -151,11 +158,9 @@
+ lock->last_x_file_name = "not yet reserved";
+ lock->last_s_line = 0;
+ lock->last_x_line = 0;
+- lock->event = os_event_create(NULL);
+-
+-#ifdef __WIN__
++ lock->s_event = os_event_create(NULL);
++ lock->x_event = os_event_create(NULL);
+ lock->wait_ex_event = os_event_create(NULL);
+-#endif
+
+ mutex_enter(&rw_lock_list_mutex);
+
+@@ -181,19 +186,21 @@
+ {
+ ut_ad(rw_lock_validate(lock));
+ ut_a(rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED);
+- ut_a(rw_lock_get_waiters(lock) == 0);
++ ut_a(rw_lock_get_s_waiters(lock) == 0);
++ ut_a(rw_lock_get_x_waiters(lock) == 0);
++ ut_a(rw_lock_get_wx_waiters(lock) == 0);
+ ut_a(rw_lock_get_reader_count(lock) == 0);
+
+ lock->magic_n = 0;
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_free(rw_lock_get_mutex(lock));
++#endif
+
+ mutex_enter(&rw_lock_list_mutex);
+- os_event_free(lock->event);
+-
+-#ifdef __WIN__
++ os_event_free(lock->s_event);
++ os_event_free(lock->x_event);
+ os_event_free(lock->wait_ex_event);
+-#endif
+
+ if (UT_LIST_GET_PREV(list, lock)) {
+ ut_a(UT_LIST_GET_PREV(list, lock)->magic_n == RW_LOCK_MAGIC_N);
+@@ -212,6 +219,8 @@
+ Checks that the rw-lock has been initialized and that there are no
+ simultaneous shared and exclusive locks. */
+
++/* MEMO: If HAVE_GCC_ATOMIC_BUILTINS, we should use this function statically. */
++
+ ibool
+ rw_lock_validate(
+ /*=============*/
+@@ -219,7 +228,9 @@
+ {
+ ut_a(lock);
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_enter(rw_lock_get_mutex(lock));
++#endif
+
+ ut_a(lock->magic_n == RW_LOCK_MAGIC_N);
+ ut_a((rw_lock_get_reader_count(lock) == 0)
+@@ -227,11 +238,17 @@
+ ut_a((rw_lock_get_writer(lock) == RW_LOCK_EX)
+ || (rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX)
+ || (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED));
+- ut_a((rw_lock_get_waiters(lock) == 0)
+- || (rw_lock_get_waiters(lock) == 1));
++ ut_a((rw_lock_get_s_waiters(lock) == 0)
++ || (rw_lock_get_s_waiters(lock) == 1));
++ ut_a((rw_lock_get_x_waiters(lock) == 0)
++ || (rw_lock_get_x_waiters(lock) == 1));
++ ut_a((rw_lock_get_wx_waiters(lock) == 0)
++ || (rw_lock_get_wx_waiters(lock) == 1));
+ ut_a((lock->writer != RW_LOCK_EX) || (lock->writer_count > 0));
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_exit(rw_lock_get_mutex(lock));
++#endif
+
+ return(TRUE);
+ }
+@@ -258,13 +275,14 @@
+ ut_ad(rw_lock_validate(lock));
+
+ lock_loop:
++ i = 0;
++spin_loop:
+ rw_s_spin_wait_count++;
+
+ /* 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) {
++ while (i < SYNC_SPIN_ROUNDS
++ && rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) {
+ if (srv_spin_wait_delay) {
+ ut_delay(ut_rnd_interval(0, srv_spin_wait_delay));
+ }
+@@ -285,15 +303,27 @@
+ lock->cfile_name, (ulong) lock->cline, (ulong) i);
+ }
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_enter(rw_lock_get_mutex(lock));
++#endif
+
+ /* We try once again to obtain the lock */
+
+ if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_exit(rw_lock_get_mutex(lock));
++#endif
+
+ return; /* Success */
+ } else {
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ /* like sync0sync.c doing */
++ i++;
++
++ if (i < SYNC_SPIN_ROUNDS) {
++ goto spin_loop;
++ }
++#endif
+ /* If we get here, locking did not succeed, we may
+ suspend the thread to wait in the wait array */
+
+@@ -304,9 +334,19 @@
+ file_name, line,
+ &index);
+
+- rw_lock_set_waiters(lock, 1);
++ rw_lock_set_s_waiters(lock, 1);
+
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ /* like sync0sync.c doing */
++ for (i = 0; i < 4; i++) {
++ if (TRUE == rw_lock_s_lock_low(lock, pass, file_name, line)) {
++ sync_array_free_cell(sync_primary_wait_array, index);
++ return; /* Success */
++ }
++ }
++#else
+ mutex_exit(rw_lock_get_mutex(lock));
++#endif
+
+ if (srv_print_latch_waits) {
+ fprintf(stderr,
+@@ -343,13 +383,19 @@
+ {
+ ut_ad(rw_lock_is_locked(lock, RW_LOCK_EX));
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_enter(&(lock->mutex));
++#endif
+
+ lock->writer_thread = os_thread_get_curr_id();
+
+ lock->pass = 0;
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_exit(&(lock->mutex));
++#else
++ __sync_synchronize();
++#endif
+ }
+
+ /**********************************************************************
+@@ -367,6 +413,89 @@
+ const char* file_name,/* in: file name where lock requested */
+ ulint line) /* in: line where requested */
+ {
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ os_thread_id_t curr_thread = os_thread_get_curr_id();
++
++ /* try to lock writer */
++ if(__sync_lock_test_and_set(&(lock->writer),RW_LOCK_EX)
++ == RW_LOCK_NOT_LOCKED) {
++ /* success */
++ /* obtain RW_LOCK_WAIT_EX right */
++ lock->writer_thread = curr_thread;
++ lock->pass = pass;
++ lock->writer_is_wait_ex = TRUE;
++ /* atomic operation may be safer about memory order. */
++ __sync_synchronize();
++#ifdef UNIV_SYNC_DEBUG
++ rw_lock_add_debug_info(lock, pass, RW_LOCK_WAIT_EX,
++ file_name, line);
++#endif
++ }
++
++ if (!os_thread_eq(lock->writer_thread, curr_thread)) {
++ return(RW_LOCK_NOT_LOCKED);
++ }
++
++ switch(rw_lock_get_writer(lock)) {
++ case RW_LOCK_WAIT_EX:
++ /* have right to try x-lock */
++ if (lock->lock_word == RW_LOCK_BIAS) {
++ /* try x-lock */
++ if(__sync_sub_and_fetch(&(lock->lock_word),
++ RW_LOCK_BIAS) == 0) {
++ /* success */
++ lock->pass = pass;
++ lock->writer_is_wait_ex = FALSE;
++ __sync_fetch_and_add(&(lock->writer_count),1);
++
++#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);
++#endif
++
++ lock->last_x_file_name = file_name;
++ lock->last_x_line = line;
++
++ /* Locking succeeded, we may return */
++ return(RW_LOCK_EX);
++ } else {
++ /* fail */
++ __sync_fetch_and_add(&(lock->lock_word),
++ RW_LOCK_BIAS);
++ }
++ }
++ /* There are readers, we have to wait */
++ return(RW_LOCK_WAIT_EX);
++
++ break;
++
++ case RW_LOCK_EX:
++ /* already have x-lock */
++ if ((lock->pass == 0)&&(pass == 0)) {
++ __sync_fetch_and_add(&(lock->writer_count),1);
++
++#ifdef UNIV_SYNC_DEBUG
++ rw_lock_add_debug_info(lock, pass, RW_LOCK_EX, 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);
++ }
++
++ return(RW_LOCK_NOT_LOCKED);
++
++ break;
++
++ default: /* ??? */
++ return(RW_LOCK_NOT_LOCKED);
++ }
++#else /* HAVE_GCC_ATOMIC_BUILTINS */
++
+ ut_ad(mutex_own(rw_lock_get_mutex(lock)));
+
+ if (rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED) {
+@@ -447,6 +576,7 @@
+ /* Locking succeeded, we may return */
+ return(RW_LOCK_EX);
+ }
++#endif /* HAVE_GCC_ATOMIC_BUILTINS */
+
+ /* Locking did not succeed */
+ return(RW_LOCK_NOT_LOCKED);
+@@ -472,19 +602,33 @@
+ ulint line) /* in: line where requested */
+ {
+ ulint index; /* index of the reserved wait cell */
+- ulint state; /* lock state acquired */
++ ulint state = RW_LOCK_NOT_LOCKED; /* lock state acquired */
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ ulint prev_state = RW_LOCK_NOT_LOCKED;
++#endif
+ ulint i; /* spin round count */
+
+ ut_ad(rw_lock_validate(lock));
+
+ lock_loop:
++ i = 0;
++
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ prev_state = state;
++#else
+ /* Acquire the mutex protecting the rw-lock fields */
+ mutex_enter_fast(&(lock->mutex));
++#endif
+
+ state = rw_lock_x_lock_low(lock, pass, file_name, line);
+
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ if (state != prev_state) i=0; /* if progress, reset counter. */
++#else
+ mutex_exit(&(lock->mutex));
++#endif
+
++spin_loop:
+ if (state == RW_LOCK_EX) {
+
+ return; /* Locking succeeded */
+@@ -492,10 +636,9 @@
+ } else if (state == RW_LOCK_NOT_LOCKED) {
+
+ /* 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) {
++ while (i < SYNC_SPIN_ROUNDS
++ && rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED) {
+ if (srv_spin_wait_delay) {
+ ut_delay(ut_rnd_interval(0,
+ srv_spin_wait_delay));
+@@ -509,9 +652,12 @@
+ } else if (state == RW_LOCK_WAIT_EX) {
+
+ /* Spin waiting for the reader count field to become zero */
+- i = 0;
+
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ while (lock->lock_word != RW_LOCK_BIAS
++#else
+ while (rw_lock_get_reader_count(lock) != 0
++#endif
+ && i < SYNC_SPIN_ROUNDS) {
+ if (srv_spin_wait_delay) {
+ ut_delay(ut_rnd_interval(0,
+@@ -524,7 +670,6 @@
+ os_thread_yield();
+ }
+ } else {
+- i = 0; /* Eliminate a compiler warning */
+ ut_error;
+ }
+
+@@ -541,34 +686,69 @@
+ /* We try once again to obtain the lock. Acquire the mutex protecting
+ the rw-lock fields */
+
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ prev_state = state;
++#else
+ mutex_enter(rw_lock_get_mutex(lock));
++#endif
+
+ state = rw_lock_x_lock_low(lock, pass, file_name, line);
+
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ if (state != prev_state) i=0; /* if progress, reset counter. */
++#endif
++
+ if (state == RW_LOCK_EX) {
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_exit(rw_lock_get_mutex(lock));
++#endif
+
+ return; /* Locking succeeded */
+ }
+
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ /* like sync0sync.c doing */
++ i++;
++
++ if (i < SYNC_SPIN_ROUNDS) {
++ goto spin_loop;
++ }
++#endif
++
+ rw_x_system_call_count++;
+
+ sync_array_reserve_cell(sync_primary_wait_array,
+ lock,
+-#ifdef __WIN__
+- /* On windows RW_LOCK_WAIT_EX signifies
+- that this thread should wait on the
+- special wait_ex_event. */
+ (state == RW_LOCK_WAIT_EX)
+ ? RW_LOCK_WAIT_EX :
+-#endif
+ RW_LOCK_EX,
+ file_name, line,
+ &index);
+
+- rw_lock_set_waiters(lock, 1);
++ if (state == RW_LOCK_WAIT_EX) {
++ rw_lock_set_wx_waiters(lock, 1);
++ } else {
++ rw_lock_set_x_waiters(lock, 1);
++ }
+
++#ifdef HAVE_GCC_ATOMIC_BUILTINS
++ /* like sync0sync.c doing */
++ for (i = 0; i < 4; i++) {
++ prev_state = state;
++ state = rw_lock_x_lock_low(lock, pass, file_name, line);
++ if (state == RW_LOCK_EX) {
++ sync_array_free_cell(sync_primary_wait_array, index);
++ return; /* Locking succeeded */
++ }
++ if (state != prev_state) {
++ /* retry! */
++ sync_array_free_cell(sync_primary_wait_array, index);
++ goto lock_loop;
++ }
++ }
++#else
+ mutex_exit(rw_lock_get_mutex(lock));
++#endif
+
+ if (srv_print_latch_waits) {
+ fprintf(stderr,
+@@ -730,7 +910,9 @@
+ ut_ad(lock);
+ ut_ad(rw_lock_validate(lock));
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_enter(&(lock->mutex));
++#endif
+
+ info = UT_LIST_GET_FIRST(lock->debug_list);
+
+@@ -740,7 +922,9 @@
+ && (info->pass == 0)
+ && (info->lock_type == lock_type)) {
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_exit(&(lock->mutex));
++#endif
+ /* Found! */
+
+ return(TRUE);
+@@ -748,7 +932,9 @@
+
+ info = UT_LIST_GET_NEXT(list, info);
+ }
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_exit(&(lock->mutex));
++#endif
+
+ return(FALSE);
+ }
+@@ -770,21 +956,25 @@
+ ut_ad(lock);
+ ut_ad(rw_lock_validate(lock));
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_enter(&(lock->mutex));
++#endif
+
+ if (lock_type == RW_LOCK_SHARED) {
+ if (lock->reader_count > 0) {
+ ret = TRUE;
+ }
+ } else if (lock_type == RW_LOCK_EX) {
+- if (lock->writer == RW_LOCK_EX) {
++ if (rw_lock_get_writer(lock) == RW_LOCK_EX) {
+ ret = TRUE;
+ }
+ } else {
+ ut_error;
+ }
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_exit(&(lock->mutex));
++#endif
+
+ return(ret);
+ }
+@@ -814,16 +1004,26 @@
+
+ count++;
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_enter(&(lock->mutex));
++#endif
+
+ if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
+ || (rw_lock_get_reader_count(lock) != 0)
+- || (rw_lock_get_waiters(lock) != 0)) {
++ || (rw_lock_get_s_waiters(lock) != 0)
++ || (rw_lock_get_x_waiters(lock) != 0)
++ || (rw_lock_get_wx_waiters(lock) != 0)) {
+
+ fprintf(file, "RW-LOCK: %p ", (void*) lock);
+
+- if (rw_lock_get_waiters(lock)) {
+- fputs(" Waiters for the lock exist\n", file);
++ if (rw_lock_get_s_waiters(lock)) {
++ fputs(" s_waiters for the lock exist,", file);
++ }
++ if (rw_lock_get_x_waiters(lock)) {
++ fputs(" x_waiters for the lock exist\n", file);
++ }
++ if (rw_lock_get_wx_waiters(lock)) {
++ fputs(" wait_ex_waiters for the lock exist\n", file);
+ } else {
+ putc('\n', file);
+ }
+@@ -835,7 +1035,9 @@
+ }
+ }
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_exit(&(lock->mutex));
++#endif
+ lock = UT_LIST_GET_NEXT(list, lock);
+ }
+
+@@ -860,10 +1062,18 @@
+
+ if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
+ || (rw_lock_get_reader_count(lock) != 0)
+- || (rw_lock_get_waiters(lock) != 0)) {
++ || (rw_lock_get_s_waiters(lock) != 0)
++ || (rw_lock_get_x_waiters(lock) != 0)
++ || (rw_lock_get_wx_waiters(lock) != 0)) {
+
+- if (rw_lock_get_waiters(lock)) {
+- fputs(" Waiters for the lock exist\n", stderr);
++ if (rw_lock_get_s_waiters(lock)) {
++ fputs(" s_waiters for the lock exist,", stderr);
++ }
++ if (rw_lock_get_x_waiters(lock)) {
++ fputs(" x_waiters for the lock exist\n", stderr);
++ }
++ if (rw_lock_get_wx_waiters(lock)) {
++ fputs(" wait_ex_waiters for the lock exist\n", stderr);
+ } else {
+ putc('\n', stderr);
+ }
+@@ -922,14 +1132,18 @@
+ lock = UT_LIST_GET_FIRST(rw_lock_list);
+
+ while (lock != NULL) {
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_enter(rw_lock_get_mutex(lock));
++#endif
+
+ if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
+ || (rw_lock_get_reader_count(lock) != 0)) {
+ count++;
+ }
+
++#ifndef HAVE_GCC_ATOMIC_BUILTINS
+ mutex_exit(rw_lock_get_mutex(lock));
++#endif
+ lock = UT_LIST_GET_NEXT(list, lock);
+ }
+
+diff -ruN mysql-5.1.29-rc_orig/patch_info/innodb_rw_lock.info mysql-5.1.29-rc/patch_info/innodb_rw_lock.info
+--- /dev/null 1970-01-01 09:00:00.000000000 +0900
++++ mysql-5.1.29-rc/patch_info/innodb_rw_lock.info 2008-11-17 15:23:46.000000000 +0900
+@@ -0,0 +1,6 @@
++File=innodb_rw_lock.patch
++Name=Fix of InnoDB rw_locks
++Version=1.0
++Author=Yasufumi Kinoshita
++License=BSD
++Comment=
-diff -r debbd352c16a patch_info/microslow.info
---- /dev/null Thu Jan 01 00:00:00 1970 +0000
-+++ b/patch_info/microslow.info Thu Sep 04 12:16:10 2008 -0700
-@@ -0,0 +1,6 @@
-+File=microslow.patch
-+Name=Extended statistics in slow.log
-+Version=1.0
-+Author=Percona <info@percona.com>
-+License=GPL
-+Comment=
-diff -r debbd352c16a sql/event_scheduler.cc
---- a/sql/event_scheduler.cc Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/event_scheduler.cc Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/event_scheduler.cc
+--- a/sql/event_scheduler.cc Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/event_scheduler.cc Thu Dec 04 08:55:29 2008 -0800
@@ -192,6 +192,7 @@
thd->client_capabilities|= CLIENT_MULTI_RESULTS;
pthread_mutex_lock(&LOCK_thread_count);
pthread_mutex_unlock(&LOCK_thread_count);
/*
-diff -r debbd352c16a sql/filesort.cc
---- a/sql/filesort.cc Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/filesort.cc Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/filesort.cc
+--- a/sql/filesort.cc Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/filesort.cc Thu Dec 04 08:55:29 2008 -0800
@@ -188,6 +188,7 @@
{
status_var_increment(thd->status_var.filesort_scan_count);
if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer)
{
x_free(table_sort.buffpek);
-@@ -1162,6 +1164,7 @@
+@@ -1202,6 +1204,7 @@
DBUG_ENTER("merge_buffers");
status_var_increment(current_thd->status_var.filesort_merge_passes);
if (param->not_killable)
{
killed= ¬_killable;
-diff -r debbd352c16a sql/log.cc
---- a/sql/log.cc Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/log.cc Thu Sep 04 12:16:10 2008 -0700
-@@ -955,7 +955,7 @@
+diff -r 0b1f42e1aacf sql/log.cc
+--- a/sql/log.cc Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/log.cc Thu Dec 04 08:55:29 2008 -0800
+@@ -963,7 +963,7 @@
/* fill in user_host value: the format is "%s[%s] @ %s [%s]" */
user_host_len= (strxnmov(user_host_buff, MAX_USER_HOST_SIZE,
sctx->priv_user ? sctx->priv_user : "", "[",
sctx->host ? sctx->host : "", " [",
sctx->ip ? sctx->ip : "", "]", NullS) -
user_host_buff);
-@@ -977,6 +977,13 @@
+@@ -985,6 +985,13 @@
query= command_name[thd->command].str;
query_length= command_name[thd->command].length;
}
for (current_handler= slow_log_handler_list; *current_handler ;)
error= (*current_handler++)->log_slow(thd, current_time, thd->start_time,
-@@ -2233,16 +2240,31 @@
+@@ -2242,16 +2249,31 @@
if (my_b_write(&log_file, (uchar*) "\n", 1))
tmp_errno= errno;
}
if (thd->db && strcmp(thd->db, db))
{ // Database changed
if (my_b_printf(&log_file,"use %s;\n",thd->db) == (uint) -1)
-diff -r debbd352c16a sql/mysql_priv.h
---- a/sql/mysql_priv.h Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/mysql_priv.h Thu Sep 04 12:16:10 2008 -0700
-@@ -595,6 +595,73 @@
+diff -r 0b1f42e1aacf sql/mysql_priv.h
+--- a/sql/mysql_priv.h Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/mysql_priv.h Thu Dec 04 08:55:29 2008 -0800
+@@ -597,6 +597,73 @@
#define WEEK_FIRST_WEEKDAY 4
#define STRING_BUFFER_USUAL_SIZE 80
/*
Some defines for exit codes for ::is_equal class functions.
-diff -r debbd352c16a sql/mysqld.cc
---- a/sql/mysqld.cc Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/mysqld.cc Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/mysqld.cc
+--- a/sql/mysqld.cc Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/mysqld.cc Thu Dec 04 08:55:29 2008 -0800
@@ -5553,6 +5553,9 @@
OPT_SECURE_FILE_PRIV,
OPT_MIN_EXAMINED_ROW_LIMIT,
+ OPT_LOG_SLOW_VERBOSITY,
+ OPT_LOG_SLOW_FILTER,
OPT_OLD_MODE,
- OPT_SLAVE_EXEC_MODE
- };
-@@ -6467,6 +6470,17 @@
+ OPT_SLAVE_EXEC_MODE,
+ OPT_GENERAL_LOG_FILE,
+@@ -6480,6 +6483,17 @@
(uchar**) 0,
0, (GET_ULONG | GET_ASK_ADDR) , REQUIRED_ARG, 100,
1, 100, 0, 1, 0},
{"long_query_time", OPT_LONG_QUERY_TIME,
"Log all queries that have taken more than long_query_time seconds to execute to file. "
"The argument will be treated as a decimal value with microsecond precission.",
-@@ -7542,6 +7556,10 @@
+@@ -7556,6 +7570,10 @@
global_system_variables.old_passwords= 0;
global_system_variables.old_alter_table= 0;
global_system_variables.binlog_format= BINLOG_FORMAT_UNSPEC;
/*
Default behavior for 4.1 and 5.0 is to treat NULL values as unequal
when collecting index statistics for MyISAM tables.
-@@ -7988,6 +8006,24 @@
+@@ -8007,6 +8025,24 @@
case OPT_BOOTSTRAP:
opt_noacl=opt_bootstrap=1;
break;
case OPT_SERVER_ID:
server_id_supplied = 1;
break;
-diff -r debbd352c16a sql/set_var.cc
---- a/sql/set_var.cc Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/set_var.cc Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/set_var.cc
+--- a/sql/set_var.cc Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/set_var.cc Thu Dec 04 08:55:29 2008 -0800
@@ -336,6 +336,20 @@
&SV::max_join_size,
fix_max_join_size);
static sys_var_long_ptr_global
sys_max_prepared_stmt_count(&vars, "max_prepared_stmt_count",
&max_prepared_stmt_count,
-@@ -3605,6 +3619,192 @@
+@@ -3631,6 +3645,192 @@
#endif
}
/****************************************************************************
Functions to handle table_type
****************************************************************************/
-diff -r debbd352c16a sql/set_var.h
---- a/sql/set_var.h Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/set_var.h Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/set_var.h
+--- a/sql/set_var.h Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/set_var.h Thu Dec 04 08:55:29 2008 -0800
@@ -1057,6 +1057,68 @@
bool update(THD *thd, set_var *var);
};
/**
Handler for setting the system variable --read-only.
-@@ -1322,3 +1384,10 @@
+@@ -1323,3 +1385,10 @@
bool process_key_caches(process_key_cache_t func);
void delete_elements(I_List<NAMED_LIST> *list,
void (*free_element)(const char*, uchar*));
+ const ulong none_val, const ulong invalid_val);
+const char *msl_option_get_name(const struct msl_opts *opts, ulong val);
+char *msl_flag_get_name(const struct msl_opts *opts, char *buf, ulong val);
-diff -r debbd352c16a sql/slave.cc
---- a/sql/slave.cc Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/slave.cc Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/slave.cc
+--- a/sql/slave.cc Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/slave.cc Thu Dec 04 08:55:29 2008 -0800
@@ -1561,6 +1561,7 @@
+ MAX_LOG_EVENT_HEADER; /* note, incr over the global not session var */
thd->slave_thread = 1;
set_slave_thread_options(thd);
thd->client_capabilities = CLIENT_LOCAL_FILES;
pthread_mutex_lock(&LOCK_thread_count);
-diff -r debbd352c16a sql/sql_cache.cc
---- a/sql/sql_cache.cc Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/sql_cache.cc Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/sql_cache.cc
+--- a/sql/sql_cache.cc Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/sql_cache.cc Thu Dec 04 08:55:29 2008 -0800
@@ -1465,6 +1465,7 @@
thd->limit_found_rows = query->found_rows();
DBUG_RETURN(0); // Query was not cached
}
-diff -r debbd352c16a sql/sql_class.h
---- a/sql/sql_class.h Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/sql_class.h Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/sql_class.h
+--- a/sql/sql_class.h Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/sql_class.h Thu Dec 04 08:55:29 2008 -0800
@@ -396,6 +396,11 @@
DATE_TIME_FORMAT *datetime_format;
DATE_TIME_FORMAT *time_format;
my_bool sysdate_is_now;
+
-+ ulong log_slow_rate_limit;
-+ ulong log_slow_filter;
-+ ulong log_slow_verbosity;
-+
++ ulong log_slow_rate_limit;
++ ulong log_slow_filter;
++ ulong log_slow_verbosity;
++
};
-@@ -1322,6 +1326,11 @@
+@@ -1339,6 +1344,11 @@
thr_lock_type update_lock_default;
Delayed_insert *di;
/* <> 0 if we are inside of trigger or stored function. */
uint in_sub_stmt;
-diff -r debbd352c16a sql/sql_connect.cc
---- a/sql/sql_connect.cc Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/sql_connect.cc Thu Sep 04 12:16:10 2008 -0700
+diff -r 0b1f42e1aacf sql/sql_connect.cc
+--- a/sql/sql_connect.cc Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/sql_connect.cc Thu Dec 04 08:55:29 2008 -0800
@@ -1124,6 +1124,15 @@
prepare_new_connection_state(thd);
while (!net->error && net->vio != 0 &&
!(thd->killed == THD::KILL_CONNECTION))
{
-diff -r debbd352c16a sql/sql_parse.cc
---- a/sql/sql_parse.cc Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/sql_parse.cc Thu Sep 04 12:16:10 2008 -0700
-@@ -1629,6 +1629,27 @@
+diff -r 0b1f42e1aacf sql/sql_parse.cc
+--- a/sql/sql_parse.cc Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/sql_parse.cc Thu Dec 04 08:55:29 2008 -0800
+@@ -1692,6 +1692,27 @@
if (unlikely(thd->in_sub_stmt))
DBUG_VOID_RETURN; // Don't set time for sub stmt
/*
Do not log administrative statements unless the appropriate option is
set; do not log into slow log if reading from backup.
-@@ -5640,6 +5661,9 @@
+@@ -5773,6 +5794,9 @@
thd->total_warn_count=0; // Warnings for this query
thd->rand_used= 0;
thd->sent_row_count= thd->examined_row_count= 0;
/*
Because we come here only for start of top-statements, binlog format is
-diff -r debbd352c16a sql/sql_select.cc
---- a/sql/sql_select.cc Thu Sep 04 12:13:31 2008 -0700
-+++ b/sql/sql_select.cc Thu Sep 04 12:16:10 2008 -0700
-@@ -6479,7 +6479,10 @@
+diff -r 0b1f42e1aacf sql/sql_select.cc
+--- a/sql/sql_select.cc Thu Dec 04 08:55:22 2008 -0800
++++ b/sql/sql_select.cc Thu Dec 04 08:55:29 2008 -0800
+@@ -6480,7 +6480,10 @@
{
join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
if (statistics)
}
}
else
-@@ -6493,7 +6496,10 @@
+@@ -6494,7 +6497,10 @@
{
join->thd->server_status|=SERVER_QUERY_NO_INDEX_USED;
if (statistics)
}
}
if (!table->no_keyread)
-@@ -9629,6 +9635,7 @@
+@@ -9638,6 +9644,7 @@
(ulong) rows_limit,test(group)));
status_var_increment(thd->status_var.created_tmp_tables);
if (use_temp_pool && !(test_flags & TEST_KEEP_TMP_TABLES))
temp_pool_slot = bitmap_lock_set_next(&temp_pool);
-@@ -10499,6 +10506,7 @@
+@@ -10508,6 +10515,7 @@
goto err;
}
status_var_increment(table->in_use->status_var.created_tmp_disk_tables);
--- /dev/null
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/buf/buf0buf.c mysql-5.1.29-rc/storage/innobase/buf/buf0buf.c
+--- mysql-5.1.29-rc_orig/storage/innobase/buf/buf0buf.c 2008-10-12 06:54:12.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/buf/buf0buf.c 2008-11-18 15:44:00.000000000 +0900
+@@ -596,6 +596,15 @@
+ ---------------------------- */
+ mutex_create(&buf_pool->mutex, SYNC_BUF_POOL);
+
++ mutex_create(&(buf_pool->flush_list_mutex), SYNC_NO_ORDER_CHECK);
++ mutex_create(&(buf_pool->LRU_mutex), SYNC_NO_ORDER_CHECK);
++ mutex_create(&(buf_pool->free_mutex), SYNC_NO_ORDER_CHECK);
++ mutex_create(&(buf_pool->hash_mutex), SYNC_NO_ORDER_CHECK);
++
++ mutex_enter(&(buf_pool->LRU_mutex));
++ mutex_enter(&(buf_pool->flush_list_mutex));
++ mutex_enter(&(buf_pool->free_mutex));
++ mutex_enter(&(buf_pool->hash_mutex));
+ mutex_enter(&(buf_pool->mutex));
+
+ if (srv_use_awe) {
+@@ -773,6 +782,10 @@
+ block->in_free_list = TRUE;
+ }
+
++ mutex_exit(&(buf_pool->LRU_mutex));
++ mutex_exit(&(buf_pool->flush_list_mutex));
++ mutex_exit(&(buf_pool->free_mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+ mutex_exit(&(buf_pool->mutex));
+
+ if (srv_use_adaptive_hash_indexes) {
+@@ -905,12 +918,12 @@
+
+ if (buf_block_peek_if_too_old(block)) {
+
+- mutex_enter(&buf_pool->mutex);
++ mutex_enter(&(buf_pool->LRU_mutex));
+ /* There has been freeing activity in the LRU list:
+ best to move to the head of the LRU list */
+
+ buf_LRU_make_block_young(block);
+- mutex_exit(&buf_pool->mutex);
++ mutex_exit(&(buf_pool->LRU_mutex));
+ }
+ }
+
+@@ -926,7 +939,7 @@
+ {
+ buf_block_t* block;
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->LRU_mutex));
+
+ block = buf_block_align(frame);
+
+@@ -934,7 +947,7 @@
+
+ buf_LRU_make_block_young(block);
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->LRU_mutex));
+ }
+
+ /************************************************************************
+@@ -945,7 +958,7 @@
+ /*===========*/
+ buf_block_t* block) /* in, own: block to be freed */
+ {
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->free_mutex));
+
+ mutex_enter(&block->mutex);
+
+@@ -955,7 +968,7 @@
+
+ mutex_exit(&block->mutex);
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->free_mutex));
+ }
+
+ /*************************************************************************
+@@ -996,11 +1009,11 @@
+ {
+ buf_block_t* block;
+
+- mutex_enter_fast(&(buf_pool->mutex));
++ mutex_enter_fast(&(buf_pool->hash_mutex));
+
+ block = buf_page_hash_get(space, offset);
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ return(block);
+ }
+@@ -1017,7 +1030,7 @@
+ {
+ buf_block_t* block;
+
+- mutex_enter_fast(&(buf_pool->mutex));
++ mutex_enter_fast(&(buf_pool->hash_mutex));
+
+ block = buf_page_hash_get(space, offset);
+
+@@ -1025,7 +1038,7 @@
+ block->check_index_page_at_flush = FALSE;
+ }
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+ }
+
+ /************************************************************************
+@@ -1044,7 +1057,7 @@
+ buf_block_t* block;
+ ibool is_hashed;
+
+- mutex_enter_fast(&(buf_pool->mutex));
++ mutex_enter_fast(&(buf_pool->hash_mutex));
+
+ block = buf_page_hash_get(space, offset);
+
+@@ -1054,7 +1067,7 @@
+ is_hashed = block->is_hashed;
+ }
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ return(is_hashed);
+ }
+@@ -1096,7 +1109,7 @@
+ {
+ buf_block_t* block;
+
+- mutex_enter_fast(&(buf_pool->mutex));
++ mutex_enter_fast(&(buf_pool->hash_mutex));
+
+ block = buf_page_hash_get(space, offset);
+
+@@ -1104,7 +1117,7 @@
+ block->file_page_was_freed = TRUE;
+ }
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ return(block);
+ }
+@@ -1125,7 +1138,7 @@
+ {
+ buf_block_t* block;
+
+- mutex_enter_fast(&(buf_pool->mutex));
++ mutex_enter_fast(&(buf_pool->hash_mutex));
+
+ block = buf_page_hash_get(space, offset);
+
+@@ -1133,7 +1146,7 @@
+ block->file_page_was_freed = FALSE;
+ }
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ return(block);
+ }
+@@ -1174,26 +1187,33 @@
+ buf_pool->n_page_gets++;
+ loop:
+ block = NULL;
+- mutex_enter_fast(&(buf_pool->mutex));
++ // mutex_enter_fast(&(buf_pool->mutex));
+
+ if (guess) {
+ block = buf_block_align(guess);
+
++ mutex_enter(&block->mutex);
+ if ((offset != block->offset) || (space != block->space)
+ || (block->state != BUF_BLOCK_FILE_PAGE)) {
+
++ mutex_exit(&block->mutex);
+ block = NULL;
+ }
+ }
+
+ if (block == NULL) {
++ mutex_enter_fast(&(buf_pool->hash_mutex));
+ block = buf_page_hash_get(space, offset);
++ if(block) {
++ mutex_enter(&block->mutex);
++ }
++ mutex_exit(&(buf_pool->hash_mutex));
+ }
+
+ if (block == NULL) {
+ /* Page not in buf_pool: needs to be read from file */
+
+- mutex_exit(&(buf_pool->mutex));
++ // mutex_exit(&(buf_pool->mutex));
+
+ if (mode == BUF_GET_IF_IN_POOL) {
+
+@@ -1212,7 +1232,7 @@
+ goto loop;
+ }
+
+- mutex_enter(&block->mutex);
++ // mutex_enter(&block->mutex);
+
+ ut_a(block->state == BUF_BLOCK_FILE_PAGE);
+
+@@ -1224,7 +1244,7 @@
+
+ if (mode == BUF_GET_IF_IN_POOL) {
+ /* The page is only being read to buffer */
+- mutex_exit(&buf_pool->mutex);
++ // mutex_exit(&buf_pool->mutex);
+ mutex_exit(&block->mutex);
+
+ return(NULL);
+@@ -1241,7 +1261,9 @@
+ LRU list and we must put it to awe_LRU_free_mapped list once
+ mapped to a frame */
+
++ mutex_enter_fast(&(buf_pool->mutex));
+ buf_awe_map_page_to_frame(block, TRUE);
++ mutex_exit(&buf_pool->mutex);
+ }
+
+ #ifdef UNIV_SYNC_DEBUG
+@@ -1249,7 +1271,7 @@
+ #else
+ buf_block_buf_fix_inc(block);
+ #endif
+- mutex_exit(&buf_pool->mutex);
++ // mutex_exit(&buf_pool->mutex);
+
+ /* Check if this is the first access to the page */
+
+@@ -1747,7 +1769,8 @@
+
+ ut_a(block);
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->LRU_mutex));
++ mutex_enter(&(buf_pool->hash_mutex));
+ mutex_enter(&block->mutex);
+
+ if (fil_tablespace_deleted_or_being_deleted_in_mem(
+@@ -1763,7 +1786,8 @@
+ already in buf_pool, return */
+
+ mutex_exit(&block->mutex);
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->LRU_mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ buf_block_free(block);
+
+@@ -1778,10 +1802,14 @@
+ ut_ad(block);
+
+ buf_page_init(space, offset, block);
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ /* The block must be put to the LRU list, to the old blocks */
+
+ buf_LRU_add_block(block, TRUE); /* TRUE == to old blocks */
++ mutex_exit(&(buf_pool->LRU_mutex));
++
++ mutex_enter(&(buf_pool->mutex)); /* for consistency about aio */
+
+ block->io_fix = BUF_IO_READ;
+
+@@ -1830,7 +1858,8 @@
+
+ free_block = buf_LRU_get_free_block();
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->LRU_mutex));
++ mutex_enter(&(buf_pool->hash_mutex));
+
+ block = buf_page_hash_get(space, offset);
+
+@@ -1841,7 +1870,8 @@
+ block->file_page_was_freed = FALSE;
+
+ /* Page can be found in buf_pool */
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->LRU_mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ buf_block_free(free_block);
+
+@@ -1864,6 +1894,7 @@
+ mutex_enter(&block->mutex);
+
+ buf_page_init(space, offset, block);
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ /* The block must be put to the LRU list */
+ buf_LRU_add_block(block, FALSE);
+@@ -1875,7 +1906,7 @@
+ #endif
+ buf_pool->n_pages_created++;
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->LRU_mutex));
+
+ mtr_memo_push(mtr, block, MTR_MEMO_BUF_FIX);
+
+@@ -1889,7 +1920,7 @@
+ ibuf_merge_or_delete_for_page(NULL, space, offset, TRUE);
+
+ /* Flush pages from the end of the LRU list if necessary */
+- buf_flush_free_margin();
++ buf_flush_free_margin(FALSE);
+
+ frame = block->frame;
+
+@@ -1928,6 +1959,7 @@
+ buf_block_t* block) /* in: pointer to the block in question */
+ {
+ ulint io_type;
++ ulint flush_type;
+
+ ut_ad(block);
+
+@@ -2040,9 +2072,6 @@
+ }
+ }
+
+- mutex_enter(&(buf_pool->mutex));
+- mutex_enter(&block->mutex);
+-
+ #ifdef UNIV_IBUF_DEBUG
+ ut_a(ibuf_count_get(block->space, block->offset) == 0);
+ #endif
+@@ -2051,9 +2080,12 @@
+ removes the newest lock debug record, without checking the thread
+ id. */
+
+- block->io_fix = 0;
+-
+ if (io_type == BUF_IO_READ) {
++ mutex_enter(&block->mutex);
++ mutex_enter(&(buf_pool->mutex));
++
++ block->io_fix = 0;
++
+ /* 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! */
+@@ -2064,6 +2096,8 @@
+
+ rw_lock_x_unlock_gen(&(block->lock), BUF_IO_READ);
+
++ mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&block->mutex);
+ #ifdef UNIV_DEBUG
+ if (buf_debug_prints) {
+ fputs("Has read ", stderr);
+@@ -2072,15 +2106,33 @@
+ } else {
+ ut_ad(io_type == BUF_IO_WRITE);
+
++ flush_type = block->flush_type;
++ if (flush_type == BUF_FLUSH_LRU) { /* optimistic! */
++ mutex_enter(&(buf_pool->LRU_mutex));
++ }
++ mutex_enter(&(buf_pool->flush_list_mutex));
++ mutex_enter(&block->mutex);
++ mutex_enter(&(buf_pool->mutex));
++
++ block->io_fix = 0;
++
+ /* Write means a flush operation: call the completion
+ routine in the flush system */
+
+ buf_flush_write_complete(block);
+
++ mutex_exit(&(buf_pool->flush_list_mutex));
++ if (flush_type == BUF_FLUSH_LRU) { /* optimistic! */
++ mutex_exit(&(buf_pool->LRU_mutex));
++ }
++
+ rw_lock_s_unlock_gen(&(block->lock), BUF_IO_WRITE);
+
+ buf_pool->n_pages_written++;
+
++ mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&block->mutex);
++
+ #ifdef UNIV_DEBUG
+ if (buf_debug_prints) {
+ fputs("Has written ", stderr);
+@@ -2088,9 +2140,6 @@
+ #endif /* UNIV_DEBUG */
+ }
+
+- mutex_exit(&block->mutex);
+- mutex_exit(&(buf_pool->mutex));
+-
+ #ifdef UNIV_DEBUG
+ if (buf_debug_prints) {
+ fprintf(stderr, "page space %lu page no %lu\n",
+@@ -2118,11 +2167,11 @@
+ freed = buf_LRU_search_and_free_block(100);
+ }
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->LRU_mutex));
+
+ ut_ad(UT_LIST_GET_LEN(buf_pool->LRU) == 0);
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->LRU_mutex));
+ }
+
+ #ifdef UNIV_DEBUG
+@@ -2142,10 +2191,22 @@
+ ulint n_flush = 0;
+ ulint n_free = 0;
+ ulint n_page = 0;
++ ulint n_single_flush_tmp = 0;
++ ulint n_lru_flush_tmp = 0;
++ ulint n_list_flush_tmp = 0;
+
+ ut_ad(buf_pool);
+
++ mutex_enter(&(buf_pool->LRU_mutex));
++ mutex_enter(&(buf_pool->flush_list_mutex));
++ mutex_enter(&(buf_pool->free_mutex));
++ mutex_enter(&(buf_pool->hash_mutex));
++
+ mutex_enter(&(buf_pool->mutex));
++ n_single_flush_tmp = buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE];
++ n_list_flush_tmp = buf_pool->n_flush[BUF_FLUSH_LIST];
++ n_lru_flush_tmp = buf_pool->n_flush[BUF_FLUSH_LRU];
++ mutex_exit(&(buf_pool->mutex));
+
+ for (i = 0; i < buf_pool->curr_size; i++) {
+
+@@ -2216,11 +2277,14 @@
+ }
+ ut_a(UT_LIST_GET_LEN(buf_pool->flush_list) == n_flush);
+
+- 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(n_single_flush_tmp == n_single_flush);
++ ut_a(n_list_flush_tmp == n_list_flush);
++ ut_a(n_lru_flush_tmp == n_lru_flush);
++
++ mutex_exit(&(buf_pool->LRU_mutex));
++ mutex_exit(&(buf_pool->flush_list_mutex));
++ mutex_exit(&(buf_pool->free_mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ ut_a(buf_LRU_validate());
+ ut_a(buf_flush_validate());
+@@ -2252,7 +2316,9 @@
+ index_ids = mem_alloc(sizeof(dulint) * size);
+ counts = mem_alloc(sizeof(ulint) * size);
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->LRU_mutex));
++ mutex_enter(&(buf_pool->flush_list_mutex));
++ mutex_enter(&(buf_pool->free_mutex));
+
+ fprintf(stderr,
+ "buf_pool size %lu\n"
+@@ -2305,7 +2371,9 @@
+ }
+ }
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->LRU_mutex));
++ mutex_exit(&(buf_pool->flush_list_mutex));
++ mutex_exit(&(buf_pool->free_mutex));
+
+ for (i = 0; i < n_found; i++) {
+ index = dict_index_get_if_in_cache(index_ids[i]);
+@@ -2339,8 +2407,6 @@
+ ulint i;
+ ulint fixed_pages_number = 0;
+
+- mutex_enter(&(buf_pool->mutex));
+-
+ for (i = 0; i < buf_pool->curr_size; i++) {
+
+ block = buf_pool_get_nth_block(buf_pool, i);
+@@ -2356,7 +2422,6 @@
+ }
+ }
+
+- mutex_exit(&(buf_pool->mutex));
+
+ return(fixed_pages_number);
+ }
+@@ -2385,7 +2450,9 @@
+ {
+ ulint ratio;
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->LRU_mutex));
++ mutex_enter(&(buf_pool->flush_list_mutex));
++ mutex_enter(&(buf_pool->free_mutex));
+
+ ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list))
+ / (1 + UT_LIST_GET_LEN(buf_pool->LRU)
+@@ -2393,7 +2460,9 @@
+
+ /* 1 + is there to avoid division by zero */
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->LRU_mutex));
++ mutex_exit(&(buf_pool->flush_list_mutex));
++ mutex_exit(&(buf_pool->free_mutex));
+
+ return(ratio);
+ }
+@@ -2413,6 +2482,9 @@
+ ut_ad(buf_pool);
+ size = buf_pool->curr_size;
+
++ mutex_enter(&(buf_pool->LRU_mutex));
++ mutex_enter(&(buf_pool->flush_list_mutex));
++ mutex_enter(&(buf_pool->free_mutex));
+ mutex_enter(&(buf_pool->mutex));
+
+ if (srv_use_awe) {
+@@ -2487,6 +2559,9 @@
+ buf_pool->n_pages_written_old = buf_pool->n_pages_written;
+ buf_pool->n_pages_awe_remapped_old = buf_pool->n_pages_awe_remapped;
+
++ mutex_exit(&(buf_pool->LRU_mutex));
++ mutex_exit(&(buf_pool->flush_list_mutex));
++ mutex_exit(&(buf_pool->free_mutex));
+ mutex_exit(&(buf_pool->mutex));
+ }
+
+@@ -2517,8 +2592,6 @@
+
+ ut_ad(buf_pool);
+
+- mutex_enter(&(buf_pool->mutex));
+-
+ for (i = 0; i < buf_pool->curr_size; i++) {
+
+ block = buf_pool_get_nth_block(buf_pool, i);
+@@ -2540,8 +2613,6 @@
+ mutex_exit(&block->mutex);
+ }
+
+- mutex_exit(&(buf_pool->mutex));
+-
+ return(TRUE);
+ }
+
+@@ -2580,11 +2651,11 @@
+ {
+ ulint len;
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->free_mutex));
+
+ len = UT_LIST_GET_LEN(buf_pool->free);
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->free_mutex));
+
+ return(len);
+ }
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/buf/buf0flu.c mysql-5.1.29-rc/storage/innobase/buf/buf0flu.c
+--- mysql-5.1.29-rc_orig/storage/innobase/buf/buf0flu.c 2008-10-12 06:54:12.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/buf/buf0flu.c 2008-11-18 15:26:07.000000000 +0900
+@@ -109,13 +109,15 @@
+ ut_ad(mutex_own(&(buf_pool->mutex)));
+ ut_ad(mutex_own(&block->mutex));
+ if (block->state != BUF_BLOCK_FILE_PAGE) {
++ /* It is permited not to own LRU_mutex.. */
++/*
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Error: buffer block state %lu"
+ " in the LRU list!\n",
+ (ulong)block->state);
+ ut_print_buf(stderr, block, sizeof(buf_block_t));
+-
++*/
+ return(FALSE);
+ }
+
+@@ -546,18 +548,20 @@
+ ut_ad(flush_type == BUF_FLUSH_LRU || flush_type == BUF_FLUSH_LIST
+ || flush_type == BUF_FLUSH_SINGLE_PAGE);
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->hash_mutex));
+
+ block = buf_page_hash_get(space, offset);
+
+ ut_a(!block || block->state == BUF_BLOCK_FILE_PAGE);
+
+ if (!block) {
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+ return(0);
+ }
+
+ mutex_enter(&block->mutex);
++ mutex_enter(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ if (flush_type == BUF_FLUSH_LIST
+ && buf_flush_ready_for_flush(block, flush_type)) {
+@@ -755,7 +759,7 @@
+ high = fil_space_get_size(space);
+ }
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->hash_mutex));
+
+ for (i = low; i < high; i++) {
+
+@@ -789,7 +793,7 @@
+
+ mutex_exit(&block->mutex);
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ /* Note: as we release the buf_pool mutex
+ above, in buf_flush_try_page we cannot be sure
+@@ -800,14 +804,14 @@
+ count += buf_flush_try_page(space, i,
+ flush_type);
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->hash_mutex));
+ } else {
+ mutex_exit(&block->mutex);
+ }
+ }
+ }
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ return(count);
+ }
+@@ -863,6 +867,13 @@
+
+ (buf_pool->init_flush)[flush_type] = TRUE;
+
++ mutex_exit(&(buf_pool->mutex));
++
++ if (flush_type == BUF_FLUSH_LRU) {
++ mutex_enter(&(buf_pool->LRU_mutex));
++ }
++ mutex_enter(&(buf_pool->flush_list_mutex));
++
+ for (;;) {
+ /* If we have flushed enough, leave the loop */
+ if (page_count >= min_n) {
+@@ -908,7 +919,10 @@
+ offset = block->offset;
+
+ mutex_exit(&block->mutex);
+- mutex_exit(&(buf_pool->mutex));
++ if (flush_type == BUF_FLUSH_LRU) {
++ mutex_exit(&(buf_pool->LRU_mutex));
++ }
++ mutex_exit(&(buf_pool->flush_list_mutex));
+
+ old_page_count = page_count;
+
+@@ -920,7 +934,10 @@
+ flush_type, offset,
+ page_count - old_page_count); */
+
+- mutex_enter(&(buf_pool->mutex));
++ if (flush_type == BUF_FLUSH_LRU) {
++ mutex_enter(&(buf_pool->LRU_mutex));
++ }
++ mutex_enter(&(buf_pool->flush_list_mutex));
+
+ } else if (flush_type == BUF_FLUSH_LRU) {
+
+@@ -943,6 +960,13 @@
+ }
+ }
+
++ if (flush_type == BUF_FLUSH_LRU) {
++ mutex_exit(&(buf_pool->LRU_mutex));
++ }
++ mutex_exit(&(buf_pool->flush_list_mutex));
++
++ mutex_enter(&(buf_pool->mutex));
++
+ (buf_pool->init_flush)[flush_type] = FALSE;
+
+ if ((buf_pool->n_flush[flush_type] == 0)
+@@ -1001,10 +1025,14 @@
+ ulint n_replaceable;
+ ulint distance = 0;
+
+- mutex_enter(&(buf_pool->mutex));
++ /* optimistic search... */
++ //mutex_enter(&(buf_pool->LRU_mutex));
++ //mutex_enter(&(buf_pool->free_mutex));
+
+ n_replaceable = UT_LIST_GET_LEN(buf_pool->free);
+
++ //mutex_exit(&(buf_pool->free_mutex));
++
+ block = UT_LIST_GET_LAST(buf_pool->LRU);
+
+ while ((block != NULL)
+@@ -1025,7 +1053,7 @@
+ block = UT_LIST_GET_PREV(LRU, block);
+ }
+
+- mutex_exit(&(buf_pool->mutex));
++ //mutex_exit(&(buf_pool->LRU_mutex));
+
+ if (n_replaceable >= BUF_FLUSH_FREE_BLOCK_MARGIN) {
+
+@@ -1044,8 +1072,9 @@
+ immediately, without waiting. */
+
+ void
+-buf_flush_free_margin(void)
++buf_flush_free_margin(
+ /*=======================*/
++ ibool wait)
+ {
+ ulint n_to_flush;
+ ulint n_flushed;
+@@ -1055,7 +1084,7 @@
+ if (n_to_flush > 0) {
+ n_flushed = buf_flush_batch(BUF_FLUSH_LRU, n_to_flush,
+ ut_dulint_zero);
+- if (n_flushed == ULINT_UNDEFINED) {
++ if (wait && n_flushed == ULINT_UNDEFINED) {
+ /* There was an LRU type flush batch already running;
+ let us wait for it to end */
+
+@@ -1105,11 +1134,11 @@
+ {
+ ibool ret;
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->flush_list_mutex));
+
+ ret = buf_flush_validate_low();
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->flush_list_mutex));
+
+ return(ret);
+ }
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/buf/buf0lru.c mysql-5.1.29-rc/storage/innobase/buf/buf0lru.c
+--- mysql-5.1.29-rc_orig/storage/innobase/buf/buf0lru.c 2008-10-12 06:54:12.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/buf/buf0lru.c 2008-11-18 15:09:58.000000000 +0900
+@@ -79,7 +79,10 @@
+ ibool all_freed;
+
+ scan_again:
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->LRU_mutex));
++ mutex_enter(&(buf_pool->flush_list_mutex));
++ mutex_enter(&(buf_pool->free_mutex));
++ mutex_enter(&(buf_pool->hash_mutex));
+
+ all_freed = TRUE;
+
+@@ -119,7 +122,10 @@
+
+ mutex_exit(&block->mutex);
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->LRU_mutex));
++ mutex_exit(&(buf_pool->flush_list_mutex));
++ mutex_exit(&(buf_pool->free_mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ /* Note that the following call will acquire
+ an S-latch on the page */
+@@ -149,7 +155,10 @@
+ block = prev_block;
+ }
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->LRU_mutex));
++ mutex_exit(&(buf_pool->flush_list_mutex));
++ mutex_exit(&(buf_pool->free_mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ if (!all_freed) {
+ os_thread_sleep(20000);
+@@ -172,14 +181,14 @@
+ ulint len;
+ ulint limit;
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->LRU_mutex));
+
+ len = UT_LIST_GET_LEN(buf_pool->LRU);
+
+ if (len < BUF_LRU_OLD_MIN_LEN) {
+ /* The LRU list is too short to do read-ahead */
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->LRU_mutex));
+
+ return(0);
+ }
+@@ -188,7 +197,7 @@
+
+ limit = block->LRU_position - len / BUF_LRU_INITIAL_RATIO;
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->LRU_mutex));
+
+ return(limit);
+ }
+@@ -212,13 +221,15 @@
+ ulint distance = 0;
+ ibool freed;
+
+- mutex_enter(&(buf_pool->mutex));
++ /* optimistic search... */
++ //mutex_enter(&(buf_pool->LRU_mutex));
+
++retry:
+ 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); /* optimistic */
+
+ mutex_enter(&block->mutex);
+
+@@ -234,9 +245,17 @@
+ }
+ #endif /* UNIV_DEBUG */
+
++ mutex_exit(&block->mutex);
++
++ mutex_enter(&(buf_pool->LRU_mutex));/* optimistic */
++
++ mutex_enter(&(buf_pool->hash_mutex));
++ mutex_enter(&block->mutex);
++ if(block->in_LRU_list && buf_flush_ready_for_replace(block)) {
+ buf_LRU_block_remove_hashed_page(block);
++ mutex_exit(&(buf_pool->hash_mutex));
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->LRU_mutex));
+ mutex_exit(&block->mutex);
+
+ /* Remove possible adaptive hash index built on the
+@@ -257,14 +276,25 @@
+
+ ut_a(block->buf_fix_count == 0);
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->free_mutex));
+ mutex_enter(&block->mutex);
+
+ buf_LRU_block_free_hashed_page(block);
+ freed = TRUE;
++ mutex_exit(&(buf_pool->free_mutex));
+ mutex_exit(&block->mutex);
+
+ break;
++ } else { /* someone may interrupt...??? */
++ mutex_exit(&(buf_pool->LRU_mutex));/* optimistic */
++
++ mutex_exit(&(buf_pool->hash_mutex));
++
++ if (!(block->in_LRU_list)) {
++ mutex_exit(&block->mutex);
++ goto retry;
++ }
++ }
+ }
+
+ mutex_exit(&block->mutex);
+@@ -275,13 +305,21 @@
+ if (!freed && n_iterations <= 10
+ && distance > 100 + (n_iterations * buf_pool->curr_size)
+ / 10) {
+- buf_pool->LRU_flush_ended = 0;
+
++ mutex_enter(&(buf_pool->mutex));
++ buf_pool->LRU_flush_ended = 0;
+ mutex_exit(&(buf_pool->mutex));
+
++ //mutex_exit(&(buf_pool->LRU_mutex));
++
+ return(FALSE);
+ }
+ }
++ if (!freed) {
++ //mutex_exit(&(buf_pool->LRU_mutex));
++ }
++
++ mutex_enter(&(buf_pool->mutex));
+ if (buf_pool->LRU_flush_ended > 0) {
+ buf_pool->LRU_flush_ended--;
+ }
+@@ -333,7 +371,8 @@
+ {
+ ibool ret = FALSE;
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->LRU_mutex));
++ mutex_enter(&(buf_pool->free_mutex));
+
+ if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
+ + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) {
+@@ -341,7 +380,8 @@
+ ret = TRUE;
+ }
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->LRU_mutex));
++ mutex_exit(&(buf_pool->free_mutex));
+
+ return(ret);
+ }
+@@ -364,7 +404,7 @@
+ ibool mon_value_was = FALSE;
+ ibool started_monitor = FALSE;
+ loop:
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->free_mutex)); /* LRU info:optimistic */
+
+ if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
+ + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 20) {
+@@ -461,7 +501,7 @@
+
+ mutex_exit(&block->mutex);
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->free_mutex));
+
+ if (started_monitor) {
+ srv_print_innodb_monitor = mon_value_was;
+@@ -473,7 +513,7 @@
+ /* If no block was in the free list, search from the end of the LRU
+ list and try to free a block there */
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->free_mutex));
+
+ freed = buf_LRU_search_and_free_block(n_iterations);
+
+@@ -517,7 +557,7 @@
+
+ /* No free block was found: try to flush the LRU list */
+
+- buf_flush_free_margin();
++ buf_flush_free_margin(TRUE);
+ ++srv_buf_pool_wait_free;
+
+ os_aio_simulated_wake_handler_threads();
+@@ -988,7 +1028,7 @@
+ ulint LRU_pos;
+
+ ut_ad(buf_pool);
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->LRU_mutex));
+
+ if (UT_LIST_GET_LEN(buf_pool->LRU) >= BUF_LRU_OLD_MIN_LEN) {
+
+@@ -1033,6 +1073,9 @@
+ ut_a(buf_pool->LRU_old_len == old_len);
+ }
+
++ mutex_exit(&(buf_pool->LRU_mutex));
++ mutex_enter(&(buf_pool->free_mutex));
++
+ UT_LIST_VALIDATE(free, buf_block_t, buf_pool->free);
+
+ block = UT_LIST_GET_FIRST(buf_pool->free);
+@@ -1043,7 +1086,7 @@
+ block = UT_LIST_GET_NEXT(free, block);
+ }
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->free_mutex));
+ return(TRUE);
+ }
+
+@@ -1059,7 +1102,7 @@
+ ulint len;
+
+ ut_ad(buf_pool);
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->LRU_mutex));
+
+ fprintf(stderr, "Pool ulint clock %lu\n",
+ (ulong) buf_pool->ulint_clock);
+@@ -1105,6 +1148,6 @@
+ }
+ }
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->LRU_mutex));
+ }
+ #endif /* UNIV_DEBUG */
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/buf/buf0rea.c mysql-5.1.29-rc/storage/innobase/buf/buf0rea.c
+--- mysql-5.1.29-rc_orig/storage/innobase/buf/buf0rea.c 2008-10-12 06:54:12.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/buf/buf0rea.c 2008-11-18 15:28:13.000000000 +0900
+@@ -219,10 +219,12 @@
+
+ return(0);
+ }
++ mutex_exit(&(buf_pool->mutex));
+
+ /* Count how many blocks in the area have been recently accessed,
+ that is, reside near the start of the LRU list. */
+
++ mutex_enter(&(buf_pool->hash_mutex));
+ for (i = low; i < high; i++) {
+ block = buf_page_hash_get(space, i);
+
+@@ -233,8 +235,9 @@
+ recent_blocks++;
+ }
+ }
++ mutex_exit(&(buf_pool->hash_mutex));
+
+- mutex_exit(&(buf_pool->mutex));
++ // mutex_exit(&(buf_pool->mutex));
+
+ if (recent_blocks < BUF_READ_AHEAD_RANDOM_THRESHOLD) {
+ /* Do nothing */
+@@ -334,7 +337,7 @@
+ }
+
+ /* Flush pages from the end of the LRU list if necessary */
+- buf_flush_free_margin();
++ buf_flush_free_margin(FALSE);
+
+ return(count + count2);
+ }
+@@ -432,6 +435,7 @@
+
+ return(0);
+ }
++ mutex_exit(&(buf_pool->mutex));
+
+ /* Check that almost all pages in the area have been accessed; if
+ offset == low, the accesses must be in a descending order, otherwise,
+@@ -445,6 +449,7 @@
+
+ fail_count = 0;
+
++ mutex_enter(&(buf_pool->hash_mutex));
+ for (i = low; i < high; i++) {
+ block = buf_page_hash_get(space, i);
+
+@@ -462,12 +467,13 @@
+ pred_block = block;
+ }
+ }
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ if (fail_count > BUF_READ_AHEAD_LINEAR_AREA
+ - BUF_READ_AHEAD_LINEAR_THRESHOLD) {
+ /* Too many failures: return */
+
+- mutex_exit(&(buf_pool->mutex));
++ //mutex_exit(&(buf_pool->mutex));
+
+ return(0);
+ }
+@@ -475,10 +481,11 @@
+ /* If we got this far, we know that enough pages in the area have
+ been accessed in the right order: linear read-ahead can be sensible */
+
++ mutex_enter(&(buf_pool->hash_mutex));
+ block = buf_page_hash_get(space, offset);
+
+ if (block == NULL) {
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ return(0);
+ }
+@@ -494,7 +501,7 @@
+ pred_offset = fil_page_get_prev(frame);
+ succ_offset = fil_page_get_next(frame);
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->hash_mutex));
+
+ if ((offset == low) && (succ_offset == offset + 1)) {
+
+@@ -573,7 +580,7 @@
+ os_aio_simulated_wake_handler_threads();
+
+ /* Flush pages from the end of the LRU list if necessary */
+- buf_flush_free_margin();
++ buf_flush_free_margin(FALSE);
+
+ #ifdef UNIV_DEBUG
+ if (buf_debug_prints && (count > 0)) {
+@@ -639,7 +646,7 @@
+ os_aio_simulated_wake_handler_threads();
+
+ /* Flush pages from the end of the LRU list if necessary */
+- buf_flush_free_margin();
++ buf_flush_free_margin(FALSE);
+
+ #ifdef UNIV_DEBUG
+ if (buf_debug_prints) {
+@@ -716,7 +723,7 @@
+ os_aio_simulated_wake_handler_threads();
+
+ /* Flush pages from the end of the LRU list if necessary */
+- buf_flush_free_margin();
++ buf_flush_free_margin(FALSE);
+
+ #ifdef UNIV_DEBUG
+ if (buf_debug_prints) {
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/include/buf0buf.h mysql-5.1.29-rc/storage/innobase/include/buf0buf.h
+--- mysql-5.1.29-rc_orig/storage/innobase/include/buf0buf.h 2008-10-12 06:54:13.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/include/buf0buf.h 2008-11-18 15:09:58.000000000 +0900
+@@ -926,6 +926,7 @@
+ currently always the same as
+ max_size */
+ hash_table_t* page_hash; /* hash table of the file pages */
++ mutex_t hash_mutex;
+
+ ulint n_pend_reads; /* number of pending read operations */
+
+@@ -958,6 +959,7 @@
+ UT_LIST_BASE_NODE_T(buf_block_t) flush_list;
+ /* base node of the modified block
+ list */
++ mutex_t flush_list_mutex;
+ ibool init_flush[BUF_FLUSH_LIST + 1];
+ /* this is TRUE when a flush of the
+ given type is being initialized */
+@@ -991,8 +993,10 @@
+ in the case of AWE, at the start are
+ always free blocks for which the
+ physical memory is mapped to a frame */
++ mutex_t free_mutex;
+ UT_LIST_BASE_NODE_T(buf_block_t) LRU;
+ /* base node of the LRU list */
++ mutex_t LRU_mutex;
+ 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 */
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/include/buf0buf.ic mysql-5.1.29-rc/storage/innobase/include/buf0buf.ic
+--- mysql-5.1.29-rc_orig/storage/innobase/include/buf0buf.ic 2008-10-12 06:54:13.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/include/buf0buf.ic 2008-11-18 15:09:58.000000000 +0900
+@@ -104,7 +104,7 @@
+ buf_block_t* block;
+ dulint lsn;
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->flush_list_mutex));
+
+ block = UT_LIST_GET_LAST(buf_pool->flush_list);
+
+@@ -114,7 +114,7 @@
+ lsn = block->oldest_modification;
+ }
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->flush_list_mutex));
+
+ return(lsn);
+ }
+@@ -388,18 +388,18 @@
+ /* out: TRUE if io going on */
+ buf_block_t* block) /* in: buf_pool block, must be bufferfixed */
+ {
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&block->mutex);
+
+ ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
+ ut_ad(block->buf_fix_count > 0);
+
+ if (block->io_fix != 0) {
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&block->mutex);
+
+ return(TRUE);
+ }
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&block->mutex);
+
+ return(FALSE);
+ }
+@@ -421,7 +421,7 @@
+
+ block = buf_block_align(frame);
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&block->mutex);
+
+ if (block->state == BUF_BLOCK_FILE_PAGE) {
+ lsn = block->newest_modification;
+@@ -429,7 +429,7 @@
+ lsn = ut_dulint_zero;
+ }
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&block->mutex);
+
+ return(lsn);
+ }
+@@ -624,9 +624,9 @@
+ ut_a(block->buf_fix_count > 0);
+
+ if (rw_latch == RW_X_LATCH && mtr->modifications) {
+- mutex_enter(&buf_pool->mutex);
++ mutex_enter(&buf_pool->flush_list_mutex);
+ buf_flush_note_modification(block, mtr);
+- mutex_exit(&buf_pool->mutex);
++ mutex_exit(&buf_pool->flush_list_mutex);
+ }
+
+ mutex_enter(&block->mutex);
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/include/buf0flu.h mysql-5.1.29-rc/storage/innobase/include/buf0flu.h
+--- mysql-5.1.29-rc_orig/storage/innobase/include/buf0flu.h 2008-10-12 06:54:13.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/include/buf0flu.h 2008-11-18 15:09:58.000000000 +0900
+@@ -26,8 +26,9 @@
+ a margin of replaceable pages there. */
+
+ void
+-buf_flush_free_margin(void);
++buf_flush_free_margin(
+ /*=======================*/
++ ibool wait);
+ /************************************************************************
+ Initializes a page for writing to the tablespace. */
+
+diff -ruN mysql-5.1.29-rc_orig/storage/innobase/include/buf0flu.ic mysql-5.1.29-rc/storage/innobase/include/buf0flu.ic
+--- mysql-5.1.29-rc_orig/storage/innobase/include/buf0flu.ic 2008-10-12 06:54:13.000000000 +0900
++++ mysql-5.1.29-rc/storage/innobase/include/buf0flu.ic 2008-11-18 15:09:58.000000000 +0900
+@@ -84,7 +84,7 @@
+ ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
+ #endif /* UNIV_SYNC_DEBUG */
+
+- mutex_enter(&(buf_pool->mutex));
++ mutex_enter(&(buf_pool->flush_list_mutex));
+
+ ut_ad(ut_dulint_cmp(block->newest_modification, end_lsn) <= 0);
+
+@@ -102,5 +102,5 @@
+ start_lsn) <= 0);
+ }
+
+- mutex_exit(&(buf_pool->mutex));
++ mutex_exit(&(buf_pool->flush_list_mutex));
+ }
+diff -ruN mysql-5.1.29-rc_orig/patch_info/split_buf_pool_mutex_fixed_optimistic_safe.info mysql-5.1.29-rc/patch_info/split_buf_pool_mutex_fixed_optimistic_safe.info
+--- /dev/null 1970-01-01 09:00:00.000000000 +0900
++++ mysql-5.1.29-rc/patch_info/split_buf_pool_mutex_fixed_optimistic_safe.info 2008-11-18 15:09:58.000000000 +0900
+@@ -0,0 +1,6 @@
++File=split_buf_pool_mutex_fixed_optimistic_safe.patch
++Name=InnoDB patch to fix buffer pool scalability
++Version=1.0
++Author=Yasufumi Kinoshita
++License=BSD
++Comment=
-diff -r ab66c8ca382a include/mysql_com.h
---- a/include/mysql_com.h Thu Sep 04 12:08:00 2008 -0700
-+++ b/include/mysql_com.h Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 include/mysql_com.h
+--- a/include/mysql_com.h Thu Dec 04 08:54:17 2008 -0800
++++ b/include/mysql_com.h Thu Dec 04 08:54:27 2008 -0800
@@ -115,6 +115,8 @@
thread */
#define REFRESH_MASTER 128 /* Remove all bin logs in the index
/* The following can't be set with mysql_refresh() */
#define REFRESH_READ_LOCK 16384 /* Lock tables for read */
-diff -r ab66c8ca382a patch_info/userstats.info
---- /dev/null Thu Jan 01 00:00:00 1970 +0000
-+++ b/patch_info/userstats.info Thu Sep 04 12:12:44 2008 -0700
-@@ -0,0 +1,6 @@
-+File=userstats.patch
-+Name=SHOW USER/TABLE/INDEX statistics
-+Version=1.0
-+Author=Google
-+License=GPL
-+Comment=Added INFORMATION_SCHEMA.*_STATISTICS
-diff -r ab66c8ca382a sql/handler.cc
---- a/sql/handler.cc Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/handler.cc Thu Sep 04 12:12:44 2008 -0700
-@@ -1168,6 +1168,7 @@
+diff -r 3ed7e96969f9 sql/handler.cc
+--- a/sql/handler.cc Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/handler.cc Thu Dec 04 08:54:27 2008 -0800
+@@ -1205,6 +1205,7 @@
error=1;
}
status_var_increment(thd->status_var.ha_commit_count);
ha_info_next= ha_info->next();
ha_info->reset(); /* keep it conveniently zero-filled */
}
-@@ -1235,6 +1236,7 @@
+@@ -1272,6 +1273,7 @@
error=1;
}
status_var_increment(thd->status_var.ha_rollback_count);
ha_info_next= ha_info->next();
ha_info->reset(); /* keep it conveniently zero-filled */
}
-@@ -1682,6 +1684,7 @@
+@@ -1724,6 +1726,7 @@
error=1;
}
status_var_increment(thd->status_var.ha_rollback_count);
ha_info_next= ha_info->next();
ha_info->reset(); /* keep it conveniently zero-filled */
}
-@@ -2016,6 +2019,8 @@
+@@ -2058,6 +2061,8 @@
dup_ref=ref+ALIGN_SIZE(ref_length);
cached_table_flags= table_flags();
}
DBUG_RETURN(error);
}
-@@ -3448,6 +3453,97 @@
+@@ -3487,6 +3492,97 @@
return;
}
/****************************************************************************
** Some general functions that isn't in the handler class
-diff -r ab66c8ca382a sql/handler.h
---- a/sql/handler.h Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/handler.h Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 sql/handler.h
+--- a/sql/handler.h Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/handler.h Thu Dec 04 08:54:27 2008 -0800
@@ -29,6 +29,10 @@
#endif
/*
Iterators creator.
Presence of the pointer should be checked before using
-@@ -1130,6 +1135,10 @@
+@@ -1137,6 +1142,10 @@
*/
- Discrete_interval auto_inc_interval_for_cur_row;
+ uint auto_inc_intervals_count;
+ ulonglong rows_read;
+ ulonglong rows_changed;
handler(handlerton *ht_arg, TABLE_SHARE *share_arg)
:table_share(share_arg), table(0),
estimation_rows_to_insert(0), ht(ht_arg),
-@@ -1154,8 +1154,10 @@
+@@ -1145,8 +1154,10 @@
ft_handler(0), inited(NONE),
locked(FALSE), implicit_emptied(0),
pushed_cond(0), next_insert_id(0), insert_id_for_cur_row(0),
- {}
+ auto_inc_intervals_count(0), rows_read(0), rows_changed(0)
+ {
-+ memset(index_rows_read, 0, sizeof(index_rows_read));
++ memset(index_rows_read, 0, sizeof(index_rows_read));
+ }
virtual ~handler(void)
{
DBUG_ASSERT(locked == FALSE);
-@@ -1262,7 +1273,13 @@
+@@ -1267,7 +1278,13 @@
{
table= table_arg;
table_share= share;
virtual double scan_time()
{ return ulonglong2double(stats.data_file_length) / IO_SIZE + 2; }
virtual double read_time(uint index, uint ranges, ha_rows rows)
-diff -r ab66c8ca382a sql/lex.h
---- a/sql/lex.h Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/lex.h Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 sql/lex.h
+--- a/sql/lex.h Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/lex.h Thu Dec 04 08:54:27 2008 -0800
@@ -245,6 +245,7 @@
{ "IN", SYM(IN_SYM)},
{ "INDEX", SYM(INDEX_SYM)},
{ "USE_FRM", SYM(USE_FRM)},
{ "USING", SYM(USING)},
{ "UTC_DATE", SYM(UTC_DATE_SYM)},
-diff -r ab66c8ca382a sql/mysql_priv.h
---- a/sql/mysql_priv.h Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/mysql_priv.h Thu Sep 04 12:12:44 2008 -0700
-@@ -1058,7 +1058,19 @@
+diff -r 3ed7e96969f9 sql/mysql_priv.h
+--- a/sql/mysql_priv.h Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/mysql_priv.h Thu Dec 04 08:54:27 2008 -0800
+@@ -1060,7 +1060,19 @@
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex);
void init_max_user_conn(void);
void init_update_queries(void);
pthread_handler_t handle_bootstrap(void *arg);
int mysql_execute_command(THD *thd);
bool do_command(THD *thd);
-@@ -2009,6 +2021,12 @@
+@@ -2015,6 +2027,12 @@
extern struct system_variables max_system_variables;
extern struct system_status_var global_status_var;
extern struct rand_struct sql_rand;
extern const char *opt_date_time_formats[];
extern KNOWN_DATE_TIME_FORMAT known_date_time_formats[];
-diff -r ab66c8ca382a sql/mysqld.cc
---- a/sql/mysqld.cc Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/mysqld.cc Thu Sep 04 12:12:44 2008 -0700
-@@ -588,6 +588,11 @@
+diff -r 3ed7e96969f9 sql/mysqld.cc
+--- a/sql/mysqld.cc Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/mysqld.cc Thu Dec 04 08:54:27 2008 -0800
+@@ -589,6 +589,11 @@
LOCK_global_system_variables,
LOCK_user_conn, LOCK_slave_list, LOCK_active_mi,
LOCK_connection_count;
/**
The below lock protects access to two global server variables:
max_prepared_stmt_count and prepared_stmt_count. These variables
-@@ -1265,6 +1270,9 @@
+@@ -1266,6 +1271,9 @@
x_free(opt_secure_file_priv);
bitmap_free(&temp_pool);
free_max_user_conn();
#ifdef HAVE_REPLICATION
end_slave_list();
#endif
-@@ -1377,6 +1385,9 @@
+@@ -1378,6 +1386,9 @@
(void) pthread_cond_destroy(&COND_thread_cache);
(void) pthread_cond_destroy(&COND_flush_thread_cache);
(void) pthread_cond_destroy(&COND_manager);
}
#endif /*EMBEDDED_LIBRARY*/
-@@ -3069,6 +3080,7 @@
+@@ -3072,6 +3083,7 @@
{"show_function_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_FUNC]), SHOW_LONG_STATUS},
{"show_grants", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS},
{"show_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS},
{"show_master_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS},
{"show_new_master", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_NEW_MASTER]), SHOW_LONG_STATUS},
{"show_open_tables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_OPEN_TABLES]), SHOW_LONG_STATUS},
-@@ -3085,9 +3097,11 @@
+@@ -3089,9 +3101,11 @@
{"show_slave_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_SLAVE_STAT]), SHOW_LONG_STATUS},
{"show_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS]), SHOW_LONG_STATUS},
{"show_storage_engines", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STORAGE_ENGINES]), SHOW_LONG_STATUS},
{"show_variables", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_VARIABLES]), SHOW_LONG_STATUS},
{"show_warnings", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_WARNS]), SHOW_LONG_STATUS},
{"slave_start", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SLAVE_START]), SHOW_LONG_STATUS},
-@@ -3503,6 +3517,9 @@
+@@ -3507,6 +3521,9 @@
#endif
(void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST);
(void) pthread_cond_init(&COND_server_started,NULL);
DBUG_RETURN(0);
}
-diff -r ab66c8ca382a sql/sql_base.cc
---- a/sql/sql_base.cc Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_base.cc Thu Sep 04 12:12:44 2008 -0700
-@@ -1342,6 +1342,12 @@
- DBUG_ASSERT(!table->file || table->file->inited == handler::NONE);
+diff -r 3ed7e96969f9 sql/sql_base.cc
+--- a/sql/sql_base.cc Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_base.cc Thu Dec 04 08:54:27 2008 -0800
+@@ -1343,6 +1343,12 @@
DBUG_PRINT("tcache", ("table: '%s'.'%s' 0x%lx", table->s->db.str,
table->s->table_name.str, (long) table));
-+
+
+ if(table->file)
+ {
+ table->file->update_global_table_stats();
+ table->file->update_global_index_stats();
+ }
-
++
*table_ptr=table->next;
/*
-@@ -1880,6 +1886,9 @@
+ When closing a MERGE parent or child table, detach the children first.
+@@ -1882,6 +1888,9 @@
DBUG_ENTER("close_temporary");
DBUG_PRINT("tmptable", ("closing table: '%s'.'%s'",
table->s->db.str, table->s->table_name.str));
free_io_cache(table);
closefrm(table, 0);
-diff -r ab66c8ca382a sql/sql_class.cc
---- a/sql/sql_class.cc Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_class.cc Thu Sep 04 12:12:44 2008 -0700
-@@ -577,6 +577,8 @@
+diff -r 3ed7e96969f9 sql/sql_class.cc
+--- a/sql/sql_class.cc Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_class.cc Thu Dec 04 08:54:27 2008 -0800
+@@ -578,6 +578,8 @@
bzero(ha_data, sizeof(ha_data));
mysys_var=0;
binlog_evt_union.do_union= FALSE;
enable_slow_log= 0;
#ifndef DBUG_OFF
dbug_sentry=THD_SENTRY_MAGIC;
-@@ -761,8 +763,55 @@
+@@ -762,8 +764,55 @@
reset_current_stmt_binlog_row_based();
bzero((char *) &status_var, sizeof(status_var));
sql_log_bin_toplevel= options & OPTION_BIN_LOG;
/*
Init THD for query processing.
-diff -r ab66c8ca382a sql/sql_class.h
---- a/sql/sql_class.h Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_class.h Thu Sep 04 12:12:44 2008 -0700
-@@ -1310,6 +1310,8 @@
+diff -r 3ed7e96969f9 sql/sql_class.h
+--- a/sql/sql_class.h Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_class.h Thu Dec 04 08:54:27 2008 -0800
+@@ -1327,6 +1327,8 @@
first byte of the packet in do_command()
*/
enum enum_server_command command;
uint32 server_id;
uint32 file_id; // for LOAD DATA INFILE
/* remote (peer) port */
-@@ -1584,6 +1586,7 @@
+@@ -1616,6 +1618,7 @@
ulonglong options; /* Bitmap of states */
longlong row_count_func; /* For the ROW_COUNT() function */
ha_rows cuted_fields;
/*
number of rows we actually sent to the client, including "synthetic"
-@@ -1735,6 +1738,27 @@
+@@ -1767,6 +1770,27 @@
*/
LOG_INFO* current_linfo;
NET* slave_net; // network connection from slave -> m.
/* Used by the sys_var class to store temporary values */
union
{
-@@ -1797,6 +1821,9 @@
+@@ -1827,6 +1851,9 @@
alloc_root.
*/
void init_for_queries();
void change_user(void);
void cleanup(void);
void cleanup_after_query();
-diff -r ab66c8ca382a sql/sql_connect.cc
---- a/sql/sql_connect.cc Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_connect.cc Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 sql/sql_connect.cc
+--- a/sql/sql_connect.cc Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_connect.cc Thu Dec 04 08:54:27 2008 -0800
@@ -520,6 +520,14 @@
0,0,
(hash_get_key) get_key_conn, (hash_free_key) free_user,
if (thread_scheduler.end_thread(thd,1))
return 0; // Probably no-threads
-diff -r ab66c8ca382a sql/sql_delete.cc
---- a/sql/sql_delete.cc Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_delete.cc Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 sql/sql_delete.cc
+--- a/sql/sql_delete.cc Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_delete.cc Thu Dec 04 08:54:27 2008 -0800
@@ -402,6 +402,7 @@
my_ok(thd, (ha_rows) thd->row_count_func);
DBUG_PRINT("info",("%ld records deleted",(long) deleted));
return 0;
}
-diff -r ab66c8ca382a sql/sql_insert.cc
---- a/sql/sql_insert.cc Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_insert.cc Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 sql/sql_insert.cc
+--- a/sql/sql_insert.cc Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_insert.cc Thu Dec 04 08:54:27 2008 -0800
@@ -969,6 +969,7 @@
thd->row_count_func= info.copied + info.deleted + updated;
::my_ok(thd, (ulong) thd->row_count_func, id, buff);
thd->abort_on_warning= 0;
DBUG_RETURN(FALSE);
-diff -r ab66c8ca382a sql/sql_lex.h
---- a/sql/sql_lex.h Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_lex.h Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 sql/sql_lex.h
+--- a/sql/sql_lex.h Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_lex.h Thu Dec 04 08:54:27 2008 -0800
@@ -118,7 +118,7 @@
SQLCOM_SHOW_CREATE_TRIGGER,
SQLCOM_ALTER_DB_UPGRADE,
/*
When a command is added here, be sure it's also added in mysqld.cc
in "struct show_var_st status_vars[]= {" ...
-diff -r ab66c8ca382a sql/sql_parse.cc
---- a/sql/sql_parse.cc Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_parse.cc Thu Sep 04 12:12:44 2008 -0700
+diff -r 3ed7e96969f9 sql/sql_parse.cc
+--- a/sql/sql_parse.cc Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_parse.cc Thu Dec 04 08:54:27 2008 -0800
@@ -45,6 +45,15 @@
static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables);
const char *any_db="*any*"; // Special symbol for check_access
-@@ -278,7 +287,9 @@
+@@ -326,7 +335,9 @@
sql_command_flags[SQLCOM_SHOW_FUNC_CODE]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_PROFILES]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND |
CF_SHOW_TABLE_COMMAND |
-@@ -481,6 +492,86 @@
+@@ -544,6 +555,86 @@
DBUG_RETURN(0);
}
/**
@brief Check access privs for a MERGE table and fix children lock types.
-@@ -899,6 +990,9 @@
+@@ -962,6 +1053,9 @@
DBUG_PRINT("info",("packet: '%*.s'; command: %d", packet_length, packet, command));
thd->command=command;
/*
Commands which always take a long time are logged into
the slow log only if opt_log_slow_admin_statements is set.
-@@ -1677,6 +1771,9 @@
+@@ -1740,6 +1834,9 @@
case SCH_COLUMN_PRIVILEGES:
case SCH_TABLE_CONSTRAINTS:
case SCH_KEY_COLUMN_USAGE:
default:
break;
}
-@@ -2020,6 +2117,9 @@
+@@ -2129,6 +2226,9 @@
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "embedded server");
break;
#endif
+ case SQLCOM_SHOW_INDEX_STATS:
case SQLCOM_SHOW_STATUS_PROC:
case SQLCOM_SHOW_STATUS_FUNC:
- res= execute_sqlcom_select(thd, all_tables);
-@@ -2195,6 +2295,7 @@
+ if (!(res= check_table_access(thd, SELECT_ACL, all_tables, UINT_MAX, FALSE)))
+@@ -2306,6 +2406,7 @@
}
#endif
case SQLCOM_BACKUP_TABLE:
{
DBUG_ASSERT(first_table == all_tables && first_table != 0);
-@@ -5245,6 +5346,130 @@
+@@ -5372,6 +5473,130 @@
#endif /*NO_EMBEDDED_ACCESS_CHECKS*/
/**
check for global access and give descriptive error message if it fails.
-@@ -5406,6 +5631,10 @@
+@@ -5539,6 +5764,10 @@
reset_dynamic(&thd->user_var_events);
thd->user_var_events_alloc= thd->mem_root;
}
thd->clear_error();
thd->main_da.reset_diagnostics_area();
thd->total_warn_count=0; // Warnings for this query
-@@ -5585,6 +5814,16 @@
+@@ -5722,6 +5951,16 @@
DBUG_ENTER("mysql_parse");
DBUG_EXECUTE_IF("parser_debug", turn_parser_debug_on(););
/*
Warning.
-@@ -5674,6 +5913,27 @@
+@@ -5816,6 +6055,27 @@
*found_semicolon= NULL;
}
DBUG_VOID_RETURN;
}
-@@ -6256,6 +6516,7 @@
+@@ -6398,6 +6658,7 @@
tables->lock_type= lock_type;
tables->updating= for_update;
}
DBUG_VOID_RETURN;
}
-@@ -6623,6 +6884,21 @@
+@@ -6779,6 +7040,21 @@
#endif
if (options & REFRESH_USER_RESOURCES)
reset_mqh((LEX_USER *) NULL, 0); /* purecov: inspected */
*write_to_binlog= tmp_write_to_binlog;
return result;
}
-diff -r ab66c8ca382a sql/sql_show.cc
---- a/sql/sql_show.cc Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_show.cc Thu Sep 04 12:12:44 2008 -0700
-@@ -2239,6 +2239,90 @@
+diff -r 3ed7e96969f9 sql/sql_show.cc
+--- a/sql/sql_show.cc Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_show.cc Thu Dec 04 08:54:27 2008 -0800
+@@ -2260,6 +2260,90 @@
DBUG_RETURN(FALSE);
}
/* collect status for all running threads */
-@@ -6565,6 +6649,38 @@
+@@ -6606,6 +6690,38 @@
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};
/*
Description of ST_FIELD_INFO in table.h
-@@ -6798,6 +6798,8 @@
+@@ -6824,6 +6824,8 @@
fill_status, make_old_format, 0, 0, -1, 0, 0},
{"GLOBAL_VARIABLES", variables_fields_info, create_schema_table,
fill_variables, make_old_format, 0, 0, -1, 0, 0},
{"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
get_all_tables, 0, get_schema_key_column_usage_record, 4, 5, 0,
OPEN_TABLE_ONLY},
-@@ -6642,11 +6760,15 @@
+@@ -6683,11 +6801,15 @@
get_all_tables, make_table_names_old_format, 0, 1, 2, 1, 0},
{"TABLE_PRIVILEGES", table_privileges_fields_info, create_schema_table,
fill_schema_table_privileges, 0, 0, -1, -1, 0, 0},
{"VARIABLES", variables_fields_info, create_schema_table, fill_variables,
make_old_format, 0, -1, -1, 1, 0},
{"VIEWS", view_fields_info, create_schema_table,
-diff -r ab66c8ca382a sql/sql_update.cc
---- a/sql/sql_update.cc Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_update.cc Thu Sep 04 12:12:45 2008 -0700
+diff -r 3ed7e96969f9 sql/sql_update.cc
+--- a/sql/sql_update.cc Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_update.cc Thu Dec 04 08:54:27 2008 -0800
@@ -816,6 +816,7 @@
thd->row_count_func=
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
DBUG_PRINT("info",("%ld records updated", (long) updated));
}
thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */
-@@ -2007,5 +2008,6 @@
+@@ -2038,5 +2039,6 @@
thd->row_count_func=
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
::my_ok(thd, (ulong) thd->row_count_func, id, buff);
+ thd->updated_row_count += thd->row_count_func;
DBUG_RETURN(FALSE);
}
-diff -r ab66c8ca382a sql/sql_yacc.yy
---- a/sql/sql_yacc.yy Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/sql_yacc.yy Thu Sep 04 12:12:45 2008 -0700
-@@ -737,6 +737,7 @@
+diff -r 3ed7e96969f9 sql/sql_yacc.yy
+--- a/sql/sql_yacc.yy Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/sql_yacc.yy Thu Dec 04 08:54:27 2008 -0800
+@@ -738,6 +738,7 @@
%token IMPORT
%token INDEXES
%token INDEX_SYM
%token INFILE
%token INITIAL_SIZE_SYM
%token INNER_SYM /* SQL-2003-R */
-@@ -1025,6 +1026,7 @@
+@@ -1026,6 +1027,7 @@
%token TABLE_REF_PRIORITY
%token TABLE_SYM /* SQL-2003-R */
%token TABLE_CHECKSUM_SYM
%token TEMPORARY /* SQL-2003-N */
%token TEMPTABLE_SYM
%token TERMINATED
-@@ -1070,6 +1072,7 @@
+@@ -1071,6 +1073,7 @@
%token UPGRADE_SYM
%token USAGE /* SQL-2003-N */
%token USER /* SQL-2003-R */
%token USE_FRM
%token USE_SYM
%token USING /* SQL-2003-R */
-@@ -9353,6 +9356,27 @@
+@@ -10090,6 +10093,27 @@
{
Lex->sql_command = SQLCOM_SHOW_SLAVE_STAT;
}
| CREATE PROCEDURE sp_name
{
LEX *lex= Lex;
-@@ -9567,6 +9591,10 @@
+@@ -10304,6 +10328,10 @@
{ Lex->type|= REFRESH_DES_KEY_FILE; }
| RESOURCES
{ Lex->type|= REFRESH_USER_RESOURCES; }
;
opt_table_list:
-diff -r ab66c8ca382a sql/structs.h
---- a/sql/structs.h Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/structs.h Thu Sep 04 12:12:45 2008 -0700
+diff -r 3ed7e96969f9 sql/structs.h
+--- a/sql/structs.h Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/structs.h Thu Dec 04 08:54:27 2008 -0800
@@ -226,6 +226,28 @@
/* Maximum amount of resources which account is allowed to consume. */
USER_RESOURCES user_resources;
/* Bits in form->update */
#define REG_MAKE_DUPP 1 /* Make a copy of record when read */
-diff -r ab66c8ca382a sql/table.h
---- a/sql/table.h Thu Sep 04 12:08:00 2008 -0700
-+++ b/sql/table.h Thu Sep 04 12:12:45 2008 -0700
-@@ -824,6 +824,7 @@
+diff -r 3ed7e96969f9 sql/table.h
+--- a/sql/table.h Thu Dec 04 08:54:17 2008 -0800
++++ b/sql/table.h Thu Dec 04 08:54:27 2008 -0800
+@@ -879,6 +879,7 @@
SCH_FILES,
SCH_GLOBAL_STATUS,
SCH_GLOBAL_VARIABLES,
SCH_KEY_COLUMN_USAGE,
SCH_OPEN_TABLES,
SCH_PARTITIONS,
-@@ -842,8 +843,10 @@
+@@ -897,8 +898,10 @@
SCH_TABLE_CONSTRAINTS,
SCH_TABLE_NAMES,
SCH_TABLE_PRIVILEGES,
SCH_VARIABLES,
SCH_VIEWS
};
-diff -r ab66c8ca382a storage/innobase/handler/ha_innodb.cc
---- a/storage/innobase/handler/ha_innodb.cc Thu Sep 04 12:08:00 2008 -0700
-+++ b/storage/innobase/handler/ha_innodb.cc Thu Sep 04 12:12:45 2008 -0700
-@@ -3925,6 +3925,8 @@
+diff -r 3ed7e96969f9 storage/innobase/handler/ha_innodb.cc
+--- a/storage/innobase/handler/ha_innodb.cc Thu Dec 04 08:54:17 2008 -0800
++++ b/storage/innobase/handler/ha_innodb.cc Thu Dec 04 08:54:27 2008 -0800
+@@ -3494,6 +3494,8 @@
error = row_insert_for_mysql((byte*) record, prebuilt);
/* Handle duplicate key errors */
if (auto_inc_used) {
ulint err;
-@@ -4001,6 +4003,8 @@
+@@ -3571,6 +3573,8 @@
break;
}
}
innodb_srv_conc_exit_innodb(prebuilt->trx);
-@@ -4647,6 +4651,8 @@
+@@ -4178,6 +4182,8 @@
ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
match_mode, 0);
innodb_srv_conc_exit_innodb(prebuilt->trx);
} else {
-@@ -4193,6 +4193,9 @@
+@@ -4187,6 +4193,9 @@
if (ret == DB_SUCCESS) {
error = 0;
table->status = 0;
} else if (ret == DB_RECORD_NOT_FOUND) {
error = HA_ERR_KEY_NOT_FOUND;
-@@ -4366,6 +4369,9 @@
+@@ -4360,6 +4369,9 @@
if (ret == DB_SUCCESS) {
error = 0;
table->status = 0;
} else if (ret == DB_RECORD_NOT_FOUND) {
error = HA_ERR_END_OF_FILE;
-diff -r ab66c8ca382a storage/myisam/ha_myisam.cc
---- a/storage/myisam/ha_myisam.cc Thu Sep 04 12:08:00 2008 -0700
-+++ b/storage/myisam/ha_myisam.cc Thu Sep 04 12:12:45 2008 -0700
+diff -r 3ed7e96969f9 storage/myisam/ha_myisam.cc
+--- a/storage/myisam/ha_myisam.cc Thu Dec 04 08:54:17 2008 -0800
++++ b/storage/myisam/ha_myisam.cc Thu Dec 04 08:54:27 2008 -0800
@@ -738,7 +738,9 @@
if ((error= update_auto_increment()))
return error;
Summary(zh_CN.UTF-8): MySQL数据库服务器
Name: mysql
Version: 5.1.35
-Release: 1
+Release: 2
License: GPL + MySQL FLOSS Exception
Group: Applications/Databases
#Source0Download: http://dev.mysql.com/downloads/mysql/5.1.html#source
Patch15: %{name}-userstats.patch
Patch16: %{name}-microslow.patch
Patch17: %{name}-acc-pslist.patch
+Patch18: %{name}-split_buf_pool_mutex_fixed_optimistic_safe.patch
+Patch19: %{name}-innodb_rw_lock.patch
# </percona>
URL: http://www.mysql.com/products/database/mysql/community_edition.html
BuildRequires: autoconf
%patch15 -p1
%patch16 -p1
%patch17 -p1
+%patch18 -p1
+%patch19 -p1
%build
%{__libtoolize}