← Back to team overview

percona-discussion team mailing list archive

[Merge] lp:~percona-dev/percona-patches/some-backports into lp:percona-patches

 

Yasufumi Kinoshita has proposed merging lp:~percona-dev/percona-patches/some-backports into lp:percona-patches.

Requested reviews:
    Percona developers (percona-dev)
-- 
https://code.launchpad.net/~percona-dev/percona-patches/some-backports/+merge/6253
Your team Percona developers is subscribed to branch lp:percona-patches.
=== added file 'innodb_extra_rseg.patch'
--- innodb_extra_rseg.patch	1970-01-01 00:00:00 +0000
+++ innodb_extra_rseg.patch	2009-05-06 09:53:18 +0000
@@ -0,0 +1,243 @@
+diff -ruN a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
+--- a/innobase/include/srv0srv.h	2009-05-06 15:35:46.000000000 +0900
++++ b/innobase/include/srv0srv.h	2009-05-06 13:37:45.000000000 +0900
+@@ -147,6 +147,8 @@
+ extern uint	srv_read_ahead;
+ extern ulint	srv_adaptive_checkpoint;
+ 
++extern ulint	srv_extra_rsegments;
++
+ extern ulint	srv_dict_size_limit;
+ 
+ extern volatile ibool srv_io_pattern;
+diff -ruN a/innobase/include/trx0sys.h b/innobase/include/trx0sys.h
+--- a/innobase/include/trx0sys.h	2009-05-06 15:35:46.000000000 +0900
++++ b/innobase/include/trx0sys.h	2009-05-06 14:52:00.000000000 +0900
+@@ -105,6 +105,13 @@
+ void
+ trx_sys_create(void);
+ /*================*/
++/*********************************************************************
++Create extra rollback segments when create_new_db */
++
++void
++trx_sys_create_extra_rseg(
++/*======================*/
++	ulint	num);	/* in: number of extra user rollback segments */
+ /********************************************************************
+ Looks for a free slot for a rollback segment in the trx system file copy. */
+ 
+diff -ruN a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
+--- a/innobase/srv/srv0srv.c	2009-05-06 15:35:46.000000000 +0900
++++ b/innobase/srv/srv0srv.c	2009-05-06 13:38:23.000000000 +0900
+@@ -347,6 +347,8 @@
+ uint	srv_read_ahead = 3; /* 1: random  2: linear  3: Both */
+ ulint	srv_adaptive_checkpoint = 0; /* 0:disable 1:enable */
+ 
++ulint	srv_extra_rsegments = 0; /* extra rseg for users */
++
+ ulint	srv_dict_size_limit = 0;
+ 
+ volatile ibool srv_io_pattern = FALSE;
+diff -ruN a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
+--- a/innobase/srv/srv0start.c	2009-05-06 15:35:46.000000000 +0900
++++ b/innobase/srv/srv0start.c	2009-05-06 14:54:43.000000000 +0900
+@@ -1418,6 +1418,8 @@
+ 		dict_create();
+                 srv_startup_is_before_trx_rollback_phase = FALSE;
+ 
++		if (srv_extra_rsegments)
++			trx_sys_create_extra_rseg(srv_extra_rsegments);
+ #ifdef UNIV_LOG_ARCHIVE
+ 	} else if (srv_archive_recovery) {
+ 		fprintf(stderr,
+diff -ruN a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c
+--- a/innobase/trx/trx0sys.c	2009-05-06 15:35:46.000000000 +0900
++++ b/innobase/trx/trx0sys.c	2009-05-06 14:54:02.000000000 +0900
+@@ -944,3 +944,28 @@
+ 
+ 	trx_sys_init_at_db_start();
+ }
++
++/*********************************************************************
++Create extra rollback segments when create_new_db */
++
++void
++trx_sys_create_extra_rseg(
++/*======================*/
++	ulint	num)	/* in: number of extra user rollback segments */
++{
++	mtr_t	mtr;
++	ulint	slot_no;
++	ulint	i;
++
++	/* Craete extra rollback segments */
++	mtr_start(&mtr);
++	for (i = 1; i < num + 1; i++) {
++		if(!trx_rseg_create(TRX_SYS_SPACE, ULINT_MAX, &slot_no, &mtr)) {
++			fprintf(stderr,
++"InnoDB: Warning: Failed to create extra rollback segments.\n");
++			break;
++		}
++		ut_a(slot_no == i);
++	}
++	mtr_commit(&mtr);
++}
+diff -ruN a/patch_info/innodb_extra_rseg.info b/patch_info/innodb_extra_rseg.info
+--- /dev/null	1970-01-01 09:00:00.000000000 +0900
++++ b/patch_info/innodb_extra_rseg.info	2009-05-06 14:49:48.000000000 +0900
+@@ -0,0 +1,6 @@
++File=innodb_extra_rseg.patch
++Name=allow to create extra rollback segments
++Version=1.0
++Author=Percona <info@xxxxxxxxxxx>
++License=GPL
++Comment
+diff -ruN a/sql/ha_innodb.cc b/sql/ha_innodb.cc
+--- a/sql/ha_innodb.cc	2009-05-06 15:35:46.000000000 +0900
++++ b/sql/ha_innodb.cc	2009-05-06 15:27:49.000000000 +0900
+@@ -152,6 +152,7 @@
+      innobase_open_files;
+ 
+ long innobase_read_io_threads, innobase_write_io_threads;
++long innobase_extra_rsegments;
+ longlong innobase_buffer_pool_size, innobase_log_file_size;
+ 
+ /* The default values for the following char* start-up parameters
+@@ -1507,6 +1508,8 @@
+ 	srv_n_read_io_threads = (ulint) innobase_read_io_threads;
+ 	srv_n_write_io_threads = (ulint) innobase_write_io_threads;
+ 
++	srv_extra_rsegments = (ulint) innobase_extra_rsegments;
++
+ 	srv_lock_wait_timeout = (ulint) innobase_lock_wait_timeout;
+ 	srv_force_recovery = (ulint) innobase_force_recovery;
+ 
+diff -ruN a/sql/ha_innodb.h b/sql/ha_innodb.h
+--- a/sql/ha_innodb.h	2009-05-06 15:35:46.000000000 +0900
++++ b/sql/ha_innodb.h	2009-05-06 13:51:35.000000000 +0900
+@@ -205,6 +205,7 @@
+ extern long innobase_buffer_pool_awe_mem_mb;
+ extern long innobase_file_io_threads, innobase_lock_wait_timeout;
+ extern long innobase_read_io_threads, innobase_write_io_threads;
++extern long innobase_extra_rsegments;
+ extern long innobase_force_recovery;
+ extern long innobase_open_files;
+ extern char *innobase_data_home_dir, *innobase_data_file_path;
+diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
+--- a/sql/mysqld.cc	2009-05-06 15:35:46.000000000 +0900
++++ b/sql/mysqld.cc	2009-05-06 14:12:05.000000000 +0900
+@@ -5096,6 +5096,7 @@
+   OPT_INNODB_ADAPTIVE_CHECKPOINT,
+   OPT_INNODB_READ_IO_THREADS,
+   OPT_INNODB_WRITE_IO_THREADS,
++  OPT_INNODB_EXTRA_RSEGMENTS,
+   OPT_INNODB_DICT_SIZE_LIMIT,
+   OPT_INNODB_ADAPTIVE_HASH_INDEX,
+   OPT_RPL_MIRROR_BINLOG,
+@@ -5454,6 +5455,10 @@
+    "Number of background write I/O threads in InnoDB.",
+    (gptr*) &innobase_write_io_threads, (gptr*) &innobase_write_io_threads,
+    0, GET_LONG, REQUIRED_ARG, 1, 1, 64, 0, 0, 0},
++  {"innodb_extra_rsegments", OPT_INNODB_EXTRA_RSEGMENTS,
++   "Number of extra user rollback segments when create new database.",
++   (gptr*) &innobase_extra_rsegments, (gptr*) &innobase_extra_rsegments,
++   0, GET_LONG, REQUIRED_ARG, 0, 0, 127, 0, 0, 0},
+   {"innodb_dict_size_limit", OPT_INNODB_DICT_SIZE_LIMIT,
+    "Limit the allocated memory for dictionary cache. (0: unlimited)",
+    (gptr*) &srv_dict_size_limit, (gptr*) &srv_dict_size_limit, 0,
+diff -ruN a/sql/set_var.cc b/sql/set_var.cc
+--- a/sql/set_var.cc	2009-05-06 15:35:46.000000000 +0900
++++ b/sql/set_var.cc	2009-05-06 14:13:24.000000000 +0900
+@@ -1063,6 +1063,7 @@
+   {sys_innodb_adaptive_checkpoint.name, (char*) &sys_innodb_adaptive_checkpoint, SHOW_SYS},
+   {"innodb_read_io_threads", (char*) &innobase_read_io_threads, SHOW_LONG},
+   {"innodb_write_io_threads", (char*) &innobase_write_io_threads, SHOW_LONG},
++  {"innodb_extra_rsegments", (char*) &innobase_extra_rsegments, SHOW_LONG},
+   {sys_innodb_dict_size_limit.name, (char*) &sys_innodb_dict_size_limit, SHOW_SYS},
+   {sys_innodb_io_pattern_trace.name, (char*) &sys_innodb_io_pattern_trace, SHOW_SYS},
+   {sys_innodb_io_pattern_trace_running.name, (char*) &sys_innodb_io_pattern_trace_running, SHOW_SYS},
+diff -ruN a/sql/sql_show.cc b/sql/sql_show.cc
+--- a/sql/sql_show.cc	2009-05-06 15:35:46.000000000 +0900
++++ b/sql/sql_show.cc	2009-05-06 15:29:47.000000000 +0900
+@@ -39,6 +39,8 @@
+ #include "srv0srv.h"
+ #include "buf0buf.h"
+ #include "dict0dict.h"
++#include "trx0rseg.h" /* for trx_rseg_struct */
++#include "trx0sys.h" /* for trx_sys */
+ }
+ /* We need to undef it in InnoDB */
+ #undef byte
+@@ -4160,6 +4162,45 @@
+   DBUG_RETURN(returnable);
+ }
+ 
++int
++innodb_rseg_fill(
++/*=================*/
++	THD*		thd,	/* in: thread */
++	TABLE_LIST*	tables,	/* in/out: tables to fill */
++	COND*		cond)	/* in: condition (ignored) */
++{
++	TABLE*	table	= (TABLE *) tables->table;
++	int	status	= 0;
++	trx_rseg_t*	rseg;
++
++	DBUG_ENTER("innodb_rseg_fill");
++
++	/* deny access to non-superusers */
++	if (check_global_access(thd, PROCESS_ACL)) {
++
++		DBUG_RETURN(0);
++	}
++
++	rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
++
++	while (rseg) {
++		table->field[0]->store(rseg->id);
++		table->field[1]->store(rseg->space);
++		table->field[2]->store(rseg->page_no);
++		table->field[3]->store(rseg->max_size);
++		table->field[4]->store(rseg->curr_size);
++
++		if (schema_table_store_record(thd, table)) {
++			status = 1;
++			break;
++		}
++
++		rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
++	}
++
++	DBUG_RETURN(status);
++}
++
+ /*
+   Find schema_tables elment by name
+ 
+@@ -4978,6 +5019,16 @@
+   {"N_WRITE", 11, MYSQL_TYPE_LONG, 0, 0, "write ios"},
+   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+ };
++
++ST_FIELD_INFO innodb_rseg_fields_info[]=
++{
++  {"RSEG_ID", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, ""},
++  {"SPACE_ID", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, ""},
++  {"PAGE_NO", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, ""},
++  {"MAX_SIZE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, ""},
++  {"CURR_SIZE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG, 0, 0, ""},
++  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
++};
+ #endif
+ 
+ ST_FIELD_INFO variables_fields_info[]=
+@@ -5157,6 +5208,8 @@
+ #ifdef HAVE_INNOBASE_DB
+   {"INNODB_IO_PATTERN", innodb_io_pattern_field_info, create_schema_table,
+     innodb_io_pattern_fill_table, 0, 0, -1, -1, 0},
++  {"INNODB_RSEG", innodb_rseg_fields_info, create_schema_table,
++    innodb_rseg_fill, 0, 0, -1, -1, 0},
+ #endif
+   {0, 0, 0, 0, 0, 0, 0, 0, 0}
+ };

=== modified file 'innodb_io_patches.patch'
--- innodb_io_patches.patch	2009-01-14 04:45:41 +0000
+++ innodb_io_patches.patch	2009-05-06 09:53:18 +0000
@@ -1,6 +1,6 @@
 diff -ruN a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c
---- a/innobase/buf/buf0flu.c	2008-12-19 02:19:35.000000000 +0900
-+++ b/innobase/buf/buf0flu.c	2009-01-09 15:51:10.000000000 +0900
+--- a/innobase/buf/buf0flu.c	2009-01-30 06:42:14.000000000 +0900
++++ b/innobase/buf/buf0flu.c	2009-05-06 10:06:28.000000000 +0900
 @@ -898,10 +898,17 @@
  
  				old_page_count = page_count;
@@ -20,8 +20,8 @@
  				"Flush type %lu, page no %lu, neighb %lu\n",
  				flush_type, offset,
 diff -ruN a/innobase/buf/buf0rea.c b/innobase/buf/buf0rea.c
---- a/innobase/buf/buf0rea.c	2009-01-09 15:40:22.000000000 +0900
-+++ b/innobase/buf/buf0rea.c	2009-01-09 15:40:46.000000000 +0900
+--- a/innobase/buf/buf0rea.c	2009-05-06 10:04:12.000000000 +0900
++++ b/innobase/buf/buf0rea.c	2009-05-06 10:06:28.000000000 +0900
 @@ -189,6 +189,10 @@
  	ulint		err;
  	ulint		i;
@@ -45,8 +45,8 @@
  	        /* No read-ahead to avoid thread deadlocks */
  	        return(0);
 diff -ruN a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c
---- a/innobase/ibuf/ibuf0ibuf.c	2008-12-19 02:19:35.000000000 +0900
-+++ b/innobase/ibuf/ibuf0ibuf.c	2009-01-09 15:53:18.000000000 +0900
+--- a/innobase/ibuf/ibuf0ibuf.c	2009-01-30 06:42:16.000000000 +0900
++++ b/innobase/ibuf/ibuf0ibuf.c	2009-05-06 10:06:28.000000000 +0900
 @@ -370,8 +370,9 @@
  	grow in size, as the references on the upper levels of the tree can
  	change */
@@ -74,8 +74,8 @@
  	sync = FALSE;
  	
 diff -ruN a/innobase/include/os0file.h b/innobase/include/os0file.h
---- a/innobase/include/os0file.h	2009-01-09 15:40:22.000000000 +0900
-+++ b/innobase/include/os0file.h	2009-01-09 15:40:46.000000000 +0900
+--- a/innobase/include/os0file.h	2009-05-06 10:04:12.000000000 +0900
++++ b/innobase/include/os0file.h	2009-05-06 10:06:28.000000000 +0900
 @@ -551,8 +551,10 @@
  /*========*/
  	ulint	n,		/* in: maximum number of pending aio operations
@@ -90,8 +90,8 @@
  /***********************************************************************
  Requests an asynchronous i/o operation. */
 diff -ruN a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
---- a/innobase/include/srv0srv.h	2009-01-09 15:40:22.000000000 +0900
-+++ b/innobase/include/srv0srv.h	2009-01-09 15:54:33.000000000 +0900
+--- a/innobase/include/srv0srv.h	2009-05-06 10:04:12.000000000 +0900
++++ b/innobase/include/srv0srv.h	2009-05-06 10:19:25.000000000 +0900
 @@ -89,6 +89,8 @@
  extern ulint	srv_lock_table_size;
  
@@ -101,7 +101,7 @@
  
  #ifdef UNIV_LOG_ARCHIVE
  extern ibool	srv_log_archive_on;
-@@ -133,6 +135,14 @@
+@@ -133,6 +135,15 @@
  extern ulong	srv_max_purge_lag;
  extern ibool	srv_use_awe;
  extern ibool	srv_use_adaptive_hash_indexes;
@@ -111,14 +111,15 @@
 +extern ulint	srv_ibuf_active_contract;
 +extern ulint	srv_ibuf_accel_rate;
 +extern ulint	srv_flush_neighbor_pages;
++extern ulint	srv_enable_unsafe_group_commit;
 +extern uint	srv_read_ahead;
 +extern ulint	srv_adaptive_checkpoint;
  /*-------------------------------------------*/
  
  extern ulint	srv_n_rows_inserted;
 diff -ruN a/innobase/log/log0log.c b/innobase/log/log0log.c
---- a/innobase/log/log0log.c	2008-12-19 02:19:36.000000000 +0900
-+++ b/innobase/log/log0log.c	2009-01-09 15:40:46.000000000 +0900
+--- a/innobase/log/log0log.c	2009-01-30 06:42:21.000000000 +0900
++++ b/innobase/log/log0log.c	2009-05-06 10:06:28.000000000 +0900
 @@ -3326,6 +3326,15 @@
  			(ulong) ut_dulint_get_high(log_sys->last_checkpoint_lsn),
  			(ulong) ut_dulint_get_low(log_sys->last_checkpoint_lsn));
@@ -136,8 +137,8 @@
  			
  	time_elapsed = 0.001 + difftime(current_time,
 diff -ruN a/innobase/os/os0file.c b/innobase/os/os0file.c
---- a/innobase/os/os0file.c	2009-01-09 15:40:23.000000000 +0900
-+++ b/innobase/os/os0file.c	2009-01-09 15:40:46.000000000 +0900
+--- a/innobase/os/os0file.c	2009-05-06 10:04:12.000000000 +0900
++++ b/innobase/os/os0file.c	2009-05-06 10:06:28.000000000 +0900
 @@ -2877,8 +2877,10 @@
  /*========*/
  	ulint	n,		/* in: maximum number of pending aio operations
@@ -211,8 +212,8 @@
  	array->n_reserved++;
  
 diff -ruN a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
---- a/innobase/srv/srv0srv.c	2009-01-09 15:40:23.000000000 +0900
-+++ b/innobase/srv/srv0srv.c	2009-01-09 15:58:36.000000000 +0900
+--- a/innobase/srv/srv0srv.c	2009-05-06 10:04:12.000000000 +0900
++++ b/innobase/srv/srv0srv.c	2009-05-06 10:20:45.000000000 +0900
 @@ -167,6 +167,8 @@
  ulint	srv_lock_table_size	= ULINT_MAX;
  
@@ -222,7 +223,7 @@
  
  #ifdef UNIV_LOG_ARCHIVE
  ibool	srv_log_archive_on	= FALSE;
-@@ -324,6 +326,22 @@
+@@ -324,6 +326,24 @@
  ibool	srv_use_awe			= FALSE;
  ibool	srv_use_adaptive_hash_indexes 	= TRUE;
  
@@ -240,12 +241,14 @@
 +
 +ulint	srv_flush_neighbor_pages = 1; /* 0:disable 1:enable */
 +
++ulint	srv_enable_unsafe_group_commit = 0; /* 0:disable 1:enable */
++
 +uint	srv_read_ahead = 3; /* 1: random  2: linear  3: Both */
 +ulint	srv_adaptive_checkpoint = 0; /* 0:disable 1:enable */
  /*-------------------------------------------*/
  ulong	srv_n_spin_wait_rounds	= 20;
  ulong	srv_n_free_tickets_to_enter = 500;
-@@ -2214,6 +2232,8 @@
+@@ -2223,6 +2243,8 @@
  	ibool		skip_sleep	= FALSE;
  	ulint		i;
  	
@@ -254,7 +257,7 @@
  #ifdef UNIV_DEBUG_THREAD_CREATION
  	fprintf(stderr, "Master thread starts, id %lu\n",
  			      os_thread_pf(os_thread_get_curr_id()));
-@@ -2302,9 +2322,9 @@
+@@ -2311,9 +2333,9 @@
  						+ log_sys->n_pending_writes;
  		n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
  						+ buf_pool->n_pages_written;
@@ -266,7 +269,7 @@
  
  			srv_main_thread_op_info = "flushing log";
  
-@@ -2317,7 +2337,7 @@
+@@ -2326,7 +2348,7 @@
  			/* Try to keep the number of modified pages in the
  			buffer pool under the limit wished by the user */
  			
@@ -275,7 +278,7 @@
  							  ut_dulint_max);
  
  		        /* If we had to do the flush, it may have taken
-@@ -2326,6 +2346,49 @@
+@@ -2335,6 +2357,49 @@
  			iteration of this loop. */
  			     
  			skip_sleep = TRUE;
@@ -325,7 +328,7 @@
  		}
  
  		if (srv_activity_count == old_activity_count) {
-@@ -2352,10 +2415,10 @@
+@@ -2361,10 +2426,10 @@
  	n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes;
  	n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
  						+ buf_pool->n_pages_written;
@@ -338,7 +341,7 @@
  
  		srv_main_thread_op_info = "flushing log";
  		log_buffer_flush_to_disk();
-@@ -2365,7 +2428,7 @@
+@@ -2374,7 +2439,7 @@
  	even if the server were active */
  
  	srv_main_thread_op_info = "doing insert buffer merge";
@@ -347,7 +350,7 @@
  
  	srv_main_thread_op_info = "flushing log";
  	log_buffer_flush_to_disk();
-@@ -2407,14 +2470,14 @@
+@@ -2416,14 +2481,14 @@
  		(> 70 %), we assume we can afford reserving the disk(s) for
  		the time it requires to flush 100 pages */
  
@@ -364,7 +367,7 @@
  							ut_dulint_max);
  	}
  
-@@ -2503,7 +2566,7 @@
+@@ -2512,7 +2577,7 @@
  	if (srv_fast_shutdown && srv_shutdown_state > 0) {
  	        n_bytes_merged = 0;
  	} else {
@@ -373,7 +376,7 @@
  	}
  
  	srv_main_thread_op_info = "reserving kernel mutex";
-@@ -2520,7 +2583,7 @@
+@@ -2529,7 +2594,7 @@
  
  	if (srv_fast_shutdown < 2) {
  		n_pages_flushed =
@@ -383,8 +386,8 @@
  		/* In the fastest shutdown we do not flush the buffer pool
  		to data files: we set n_pages_flushed to 0 artificially. */
 diff -ruN a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
---- a/innobase/srv/srv0start.c	2008-12-19 02:19:37.000000000 +0900
-+++ b/innobase/srv/srv0start.c	2009-01-09 15:40:46.000000000 +0900
+--- a/innobase/srv/srv0start.c	2009-01-30 06:42:23.000000000 +0900
++++ b/innobase/srv/srv0start.c	2009-05-06 10:06:28.000000000 +0900
 @@ -1205,24 +1205,28 @@
  		return(DB_ERROR);
  	}
@@ -420,7 +423,7 @@
  	
 diff -ruN a/patch_info/innodb_io_patches.info b/patch_info/innodb_io_patches.info
 --- /dev/null	1970-01-01 09:00:00.000000000 +0900
-+++ b/patch_info/innodb_io_patches.info	2009-01-09 15:59:05.000000000 +0900
++++ b/patch_info/innodb_io_patches.info	2009-05-06 10:06:28.000000000 +0900
 @@ -0,0 +1,11 @@
 +File=innodb_io_patches.patch
 +Name=Cluster of past InnoDB IO patches
@@ -434,8 +437,8 @@
 +2009-01-09
 +YK: Some parameters are added
 diff -ruN a/sql/ha_innodb.cc b/sql/ha_innodb.cc
---- a/sql/ha_innodb.cc	2009-01-09 15:40:23.000000000 +0900
-+++ b/sql/ha_innodb.cc	2009-01-09 15:40:46.000000000 +0900
+--- a/sql/ha_innodb.cc	2009-05-06 10:04:19.000000000 +0900
++++ b/sql/ha_innodb.cc	2009-05-06 10:52:16.000000000 +0900
 @@ -149,6 +149,7 @@
       innobase_lock_wait_timeout, innobase_force_recovery,
       innobase_open_files;
@@ -453,9 +456,20 @@
  
  	srv_lock_wait_timeout = (ulint) innobase_lock_wait_timeout;
  	srv_force_recovery = (ulint) innobase_force_recovery;
+@@ -7317,6 +7320,10 @@
+         trx_t* trx = check_trx_exists(thd);
+ 
+         if (thd->lex->sql_command != SQLCOM_XA_PREPARE) {
++		if (srv_enable_unsafe_group_commit && !thd->variables.innodb_support_xa) {
++			/* choose group commit rather than binlog order */
++			return(0);
++		}
+ 
+                 /* For ibbackup to work the order of transactions in binlog
+                 and InnoDB must be the same. Consider the situation
 diff -ruN a/sql/ha_innodb.h b/sql/ha_innodb.h
---- a/sql/ha_innodb.h	2009-01-09 15:40:23.000000000 +0900
-+++ b/sql/ha_innodb.h	2009-01-09 15:59:41.000000000 +0900
+--- a/sql/ha_innodb.h	2009-05-06 10:04:12.000000000 +0900
++++ b/sql/ha_innodb.h	2009-05-06 10:22:01.000000000 +0900
 @@ -204,6 +204,7 @@
  extern long innobase_additional_mem_pool_size;
  extern long innobase_buffer_pool_awe_mem_mb;
@@ -464,7 +478,7 @@
  extern long innobase_force_recovery;
  extern long innobase_open_files;
  extern char *innobase_data_home_dir, *innobase_data_file_path;
-@@ -234,6 +235,13 @@
+@@ -234,6 +235,14 @@
  extern ulong srv_thread_concurrency;
  extern ulong srv_commit_concurrency;
  extern ulong srv_flush_log_at_trx_commit;
@@ -473,15 +487,16 @@
 +extern ulong srv_ibuf_active_contract;
 +extern ulong srv_ibuf_accel_rate;
 +extern ulong srv_flush_neighbor_pages;
++extern ulong srv_enable_unsafe_group_commit;
 +extern uint srv_read_ahead;
 +extern ulong srv_adaptive_checkpoint;
  }
  
  bool innobase_init(void);
 diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
---- a/sql/mysqld.cc	2009-01-09 15:40:23.000000000 +0900
-+++ b/sql/mysqld.cc	2009-01-09 16:01:25.000000000 +0900
-@@ -5036,6 +5036,15 @@
+--- a/sql/mysqld.cc	2009-05-06 10:04:19.000000000 +0900
++++ b/sql/mysqld.cc	2009-05-06 10:33:23.000000000 +0900
+@@ -5080,6 +5080,16 @@
    OPT_INNODB_ROLLBACK_ON_TIMEOUT,
    OPT_SECURE_FILE_PRIV,
    OPT_KEEP_FILES_ON_CREATE,
@@ -490,6 +505,7 @@
 +  OPT_INNODB_IBUF_ACTIVE_CONTRACT,
 +  OPT_INNODB_IBUF_ACCEL_RATE,
 +  OPT_INNODB_FLUSH_NEIGHBOR_PAGES,
++  OPT_INNODB_ENABLE_UNSAFE_GROUP_COMMIT,
 +  OPT_INNODB_READ_AHEAD,
 +  OPT_INNODB_ADAPTIVE_CHECKPOINT,
 +  OPT_INNODB_READ_IO_THREADS,
@@ -497,7 +513,7 @@
    OPT_INNODB_ADAPTIVE_HASH_INDEX,
    OPT_FEDERATED
  };
-@@ -5344,6 +5353,41 @@
+@@ -5388,6 +5398,45 @@
     (gptr*) &global_system_variables.innodb_table_locks,
     (gptr*) &global_system_variables.innodb_table_locks,
     0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
@@ -528,6 +544,10 @@
 +   "Enable/Diasable flushing along modified age. 0:disable 1:enable",
 +   (gptr*) &srv_adaptive_checkpoint, (gptr*) &srv_adaptive_checkpoint,
 +   0, GET_ULONG, REQUIRED_ARG, 0, 0, 1, 0, 0, 0},
++  {"innodb_enable_unsafe_group_commit", OPT_INNODB_ENABLE_UNSAFE_GROUP_COMMIT,
++   "Enable/Disable unsafe group commit when support_xa=OFF and use with binlog or other XA storage engine.",
++   (gptr*) &srv_enable_unsafe_group_commit, (gptr*) &srv_enable_unsafe_group_commit,
++   0, GET_ULONG, REQUIRED_ARG, 0, 0, 1, 0, 0, 0},
 +  {"innodb_read_io_threads", OPT_INNODB_READ_IO_THREADS,
 +   "Number of background read I/O threads in InnoDB.",
 +   (gptr*) &innobase_read_io_threads, (gptr*) &innobase_read_io_threads,
@@ -539,7 +559,7 @@
  #endif /* End HAVE_INNOBASE_DB */
    {"isam", OPT_ISAM, "Obsolete. ISAM storage engine is no longer supported.",
     (gptr*) &opt_isam, (gptr*) &opt_isam, 0, GET_BOOL, NO_ARG, 0, 0, 0,
-@@ -7637,6 +7636,22 @@
+@@ -7607,6 +7656,22 @@
    case OPT_INNODB_LOG_ARCHIVE:
      innobase_log_archive= argument ? test(atoi(argument)) : 1;
      break;
@@ -563,9 +583,9 @@
    case OPT_MYISAM_RECOVER:
    {
 diff -ruN a/sql/set_var.cc b/sql/set_var.cc
---- a/sql/set_var.cc	2009-01-09 15:40:23.000000000 +0900
-+++ b/sql/set_var.cc	2009-01-09 16:05:22.000000000 +0900
-@@ -484,6 +484,37 @@
+--- a/sql/set_var.cc	2009-05-06 10:04:19.000000000 +0900
++++ b/sql/set_var.cc	2009-05-06 10:40:03.000000000 +0900
+@@ -486,6 +486,39 @@
  sys_var_long_ptr  sys_innodb_flush_log_at_trx_commit(
                                          "innodb_flush_log_at_trx_commit",
                                          &srv_flush_log_at_trx_commit);
@@ -598,12 +618,14 @@
 +};
 +sys_var_enum	sys_innodb_read_ahead("innodb_read_ahead", &srv_read_ahead,
 +                                      &innodb_read_ahead_typelib, fix_innodb_read_ahead);
++sys_var_long_ptr	sys_innodb_enable_unsafe_group_commit("innodb_enable_unsafe_group_commit",
++                                                             &srv_enable_unsafe_group_commit);
 +sys_var_long_ptr	sys_innodb_adaptive_checkpoint("innodb_adaptive_checkpoint",
 +                                                      &srv_adaptive_checkpoint);
  sys_var_const_os_str_ptr sys_innodb_data_file_path("innodb_data_file_path", 
                                                 &innobase_data_file_path);
  sys_var_const_os_str_ptr sys_innodb_data_home_dir("innodb_data_home_dir", 
-@@ -847,6 +859,12 @@
+@@ -850,6 +883,13 @@
    &sys_innodb_thread_concurrency,
    &sys_innodb_commit_concurrency,
    &sys_innodb_flush_log_at_trx_commit,
@@ -612,11 +634,12 @@
 +  &sys_innodb_ibuf_accel_rate,
 +  &sys_innodb_flush_neighbor_pages,
 +  &sys_innodb_read_ahead,
++  &sys_innodb_enable_unsafe_group_commit,
 +  &sys_innodb_adaptive_checkpoint,
  #endif
    &sys_trust_routine_creators,
    &sys_trust_function_creators,
-@@ -982,6 +1000,15 @@
+@@ -985,6 +1025,16 @@
    {sys_innodb_table_locks.name, (char*) &sys_innodb_table_locks, SHOW_SYS},
    {sys_innodb_thread_concurrency.name, (char*) &sys_innodb_thread_concurrency, SHOW_SYS},
    {sys_innodb_thread_sleep_delay.name, (char*) &sys_innodb_thread_sleep_delay, SHOW_SYS},
@@ -626,16 +649,17 @@
 +  {sys_innodb_ibuf_accel_rate.name, (char*) &sys_innodb_ibuf_accel_rate, SHOW_SYS},
 +  {sys_innodb_flush_neighbor_pages.name, (char*) &sys_innodb_flush_neighbor_pages, SHOW_SYS},
 +  {sys_innodb_read_ahead.name, (char*) &sys_innodb_read_ahead, SHOW_SYS},
++  {sys_innodb_enable_unsafe_group_commit.name, (char*) &sys_innodb_enable_unsafe_group_commit, SHOW_SYS},
 +  {sys_innodb_adaptive_checkpoint.name, (char*) &sys_innodb_adaptive_checkpoint, SHOW_SYS},
 +  {"innodb_read_io_threads", (char*) &innobase_read_io_threads, SHOW_LONG},
 +  {"innodb_write_io_threads", (char*) &innobase_write_io_threads, SHOW_LONG},
  #endif
    {sys_interactive_timeout.name,(char*) &sys_interactive_timeout,   SHOW_SYS},
    {sys_join_buffer_size.name,   (char*) &sys_join_buffer_size,	    SHOW_SYS},
-@@ -1482,6 +1501,13 @@
+@@ -1443,6 +1493,13 @@
    }
  }
-
+ 
 +#ifdef HAVE_INNOBASE_DB
 +extern void fix_innodb_read_ahead(THD *thd, enum_var_type type)
 +{
@@ -647,12 +671,12 @@
  {
    DBUG_ENTER("fix_max_binlog_size");
 diff -ruN a/sql/set_var.h b/sql/set_var.h
---- a/sql/set_var.h	2009-01-12 11:20:31.000000000 +0900
-+++ b/sql/set_var.h	2009-01-12 15:26:35.000000000 +0900
+--- a/sql/set_var.h	2009-05-06 10:04:12.000000000 +0900
++++ b/sql/set_var.h	2009-05-06 10:06:28.000000000 +0900
 @@ -31,6 +31,10 @@
-
+ 
  extern TYPELIB bool_typelib, delay_key_write_typelib, sql_mode_typelib;
-
+ 
 +#ifdef HAVE_INNOBASE_DB
 +extern TYPELIB innodb_read_ahead_typelib;
 +#endif /* HAVE_INNOBASE_DB */
@@ -660,7 +684,7 @@
  typedef int (*sys_check_func)(THD *,  set_var *);
  typedef bool (*sys_update_func)(THD *, set_var *);
  typedef void (*sys_after_update_func)(THD *,enum_var_type);
-@@ -1114,6 +1118,9 @@
+@@ -1148,6 +1152,9 @@
  int sql_set_variables(THD *thd, List<set_var_base> *var_list);
  bool not_all_support_one_shot(List<set_var_base> *var_list);
  void fix_delay_key_write(THD *thd, enum_var_type type);

=== modified file 'innodb_rw_lock.patch'
--- innodb_rw_lock.patch	2009-02-12 01:54:35 +0000
+++ innodb_rw_lock.patch	2009-05-06 09:53:18 +0000
@@ -1,159 +1,6 @@
-diff -r 962aec0d731c innobase/configure
---- a/innobase/configure	Thu Oct 09 08:28:53 2008 -0700
-+++ b/innobase/configure	Thu Oct 09 08:30:28 2008 -0700
-@@ -20519,6 +20519,88 @@
- 
- fi
- done
-+
-+
-+# as http://lists.mysql.com/commits/40686 does
-+{ echo "$as_me:$LINENO: checking whether the compiler provides atomic builtins" >&5
-+echo $ECHO_N "checking whether the compiler provides atomic builtins... $ECHO_C" >&6; }
-+if test "${mysql_cv_atomic_builtins+set}" = set; then
-+  echo $ECHO_N "(cached) $ECHO_C" >&6
-+else
-+  if test "$cross_compiling" = yes; then
-+  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
-+See \`config.log' for more details." >&5
-+echo "$as_me: error: cannot run test program while cross compiling
-+See \`config.log' for more details." >&2;}
-+   { (exit 1); exit 1; }; }
-+else
-+  cat >conftest.$ac_ext <<_ACEOF
-+/* confdefs.h.  */
-+_ACEOF
-+cat confdefs.h >>conftest.$ac_ext
-+cat >>conftest.$ac_ext <<_ACEOF
-+/* end confdefs.h.  */
-+
-+  int main()
-+  {
-+    int foo= -10; int bar= 10;
-+    __sync_fetch_and_add(&foo, bar);
-+    if (foo)
-+      return -1;
-+    bar= __sync_lock_test_and_set(&foo, bar);
-+    if (bar || foo != 10)
-+      return -1;
-+    bar= __sync_val_compare_and_swap(&bar, foo, 15);
-+    if (bar)
-+      return -1;
-+    return 0;
-+  }
-+
-+_ACEOF
-+rm -f conftest$ac_exeext
-+if { (ac_try="$ac_link"
-+case "(($ac_try" in
-+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-+  *) ac_try_echo=$ac_try;;
-+esac
-+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-+  (eval "$ac_link") 2>&5
-+  ac_status=$?
-+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
-+  { (case "(($ac_try" in
-+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
-+  *) ac_try_echo=$ac_try;;
-+esac
-+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
-+  (eval "$ac_try") 2>&5
-+  ac_status=$?
-+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
-+  (exit $ac_status); }; }; then
-+  mysql_cv_atomic_builtins=yes
-+else
-+  echo "$as_me: program exited with status $ac_status" >&5
-+echo "$as_me: failed program was:" >&5
-+sed 's/^/| /' conftest.$ac_ext >&5
-+
-+( exit $ac_status )
-+mysql_cv_atomic_builtins=no
-+fi
-+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
-+fi
-+
-+
-+fi
-+{ echo "$as_me:$LINENO: result: $mysql_cv_atomic_builtins" >&5
-+echo "${ECHO_T}$mysql_cv_atomic_builtins" >&6; }
-+
-+if test "x$mysql_cv_atomic_builtins" = xyes; then
-+
-+cat >>confdefs.h <<\_ACEOF
-+#define HAVE_ATOMIC_BUILTINS 1
-+_ACEOF
-+
-+fi
- 
- #AC_CHECK_FUNCS(readdir_r) MySQL checks that it has also the right args.
- # Some versions of Unix only take 2 arguments.
-diff -r 962aec0d731c innobase/configure.in
---- a/innobase/configure.in	Thu Oct 09 08:28:53 2008 -0700
-+++ b/innobase/configure.in	Thu Oct 09 08:30:28 2008 -0700
-@@ -42,6 +42,31 @@
- AC_CHECK_FUNCS(sched_yield)
- AC_CHECK_FUNCS(fdatasync)
- AC_CHECK_FUNCS(localtime_r)
-+
-+# as http://lists.mysql.com/commits/40686 does
-+AC_CACHE_CHECK([whether the compiler provides atomic builtins],
-+               [mysql_cv_atomic_builtins], [AC_TRY_RUN([
-+  int main()
-+  {
-+    int foo= -10; int bar= 10;
-+    __sync_fetch_and_add(&foo, bar);
-+    if (foo)
-+      return -1;
-+    bar= __sync_lock_test_and_set(&foo, bar);
-+    if (bar || foo != 10)
-+      return -1;
-+    bar= __sync_val_compare_and_swap(&bar, foo, 15);
-+    if (bar)
-+      return -1;
-+    return 0;
-+  }
-+], [mysql_cv_atomic_builtins=yes], [mysql_cv_atomic_builtins=no])])
-+
-+if test "x$mysql_cv_atomic_builtins" = xyes; then
-+  AC_DEFINE(HAVE_ATOMIC_BUILTINS, 1,
-+            [Define to 1 if compiler provides atomic builtins.])
-+fi
-+
- #AC_CHECK_FUNCS(readdir_r) MySQL checks that it has also the right args.
- # Some versions of Unix only take 2 arguments.
- #AC_C_INLINE  Already checked in MySQL
-diff -r 962aec0d731c innobase/ib_config.h
---- a/innobase/ib_config.h	Thu Oct 09 08:28:53 2008 -0700
-+++ b/innobase/ib_config.h	Thu Oct 09 08:30:28 2008 -0700
-@@ -3,6 +3,9 @@
- 
- /* Define to 1 if you have the <aio.h> header file. */
- #define HAVE_AIO_H 1
-+
-+/* Define to 1 if compiler provides atomic builtins. */
-+#define HAVE_ATOMIC_BUILTINS 1
- 
- /* Define to 1 if you have the <dlfcn.h> header file. */
- #define HAVE_DLFCN_H 1
-diff -r 962aec0d731c innobase/ib_config.h.in
---- a/innobase/ib_config.h.in	Thu Oct 09 08:28:53 2008 -0700
-+++ b/innobase/ib_config.h.in	Thu Oct 09 08:30:28 2008 -0700
-@@ -2,6 +2,9 @@
- 
- /* Define to 1 if you have the <aio.h> header file. */
- #undef HAVE_AIO_H
-+
-+/* Define to 1 if compiler provides atomic builtins. */
-+#undef HAVE_ATOMIC_BUILTINS
- 
- /* Define to 1 if you have the <dlfcn.h> header file. */
- #undef HAVE_DLFCN_H
-diff -r 962aec0d731c innobase/include/sync0rw.h
---- a/innobase/include/sync0rw.h	Thu Oct 09 08:28:53 2008 -0700
-+++ b/innobase/include/sync0rw.h	Thu Oct 09 08:30:28 2008 -0700
+diff -ruN a/innobase/include/sync0rw.h b/innobase/include/sync0rw.h
+--- a/innobase/include/sync0rw.h	2009-01-30 06:42:20.000000000 +0900
++++ b/innobase/include/sync0rw.h	2009-04-16 16:15:28.000000000 +0900
 @@ -325,7 +325,17 @@
  Accessor functions for rw lock. */
  UNIV_INLINE
@@ -191,7 +38,7 @@
  /* 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
-@@ -417,9 +432,9 @@
+@@ -417,9 +438,9 @@
  field. Then no new readers are allowed in. */
  
  struct rw_lock_struct {
@@ -204,7 +51,7 @@
  	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
-@@ -427,31 +442,35 @@
+@@ -427,31 +448,35 @@
  				thread will be the next one to proceed
  				once the current the event gets
  				signalled. See LEMMA 2 in sync0sync.c */
@@ -249,10 +96,10 @@
  				/* 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 -r 962aec0d731c innobase/include/sync0rw.ic
---- a/innobase/include/sync0rw.ic	Thu Oct 09 08:28:53 2008 -0700
-+++ b/innobase/include/sync0rw.ic	Thu Oct 09 08:30:28 2008 -0700
-@@ -47,20 +47,52 @@
+diff -ruN a/innobase/include/sync0rw.ic b/innobase/include/sync0rw.ic
+--- a/innobase/include/sync0rw.ic	2009-01-30 06:42:20.000000000 +0900
++++ b/innobase/include/sync0rw.ic	2009-04-16 17:06:53.000000000 +0900
+@@ -47,20 +47,64 @@
  Accessor functions for rw lock. */
  UNIV_INLINE
  ulint
@@ -263,11 +110,13 @@
  {
 -	return(lock->waiters);
 +	return(lock->s_waiters);
-+}
-+UNIV_INLINE
+ }
+ UNIV_INLINE
+-void
+-rw_lock_set_waiters(
 +ulint
 +rw_lock_get_x_waiters(
-+/*================*/
+ /*================*/
 +	rw_lock_t*	lock)
 +{
 +	return(lock->x_waiters);
@@ -279,17 +128,19 @@
 +	rw_lock_t*      lock)
 +{
 +	return(lock->wait_ex_waiters);
- }
- UNIV_INLINE
- void
--rw_lock_set_waiters(
--/*================*/
++}
++UNIV_INLINE
++void
 +rw_lock_set_s_waiters(
  	rw_lock_t*	lock,
  	ulint		flag)
  {
 -	lock->waiters = flag;
++#ifdef HAVE_ATOMIC_BUILTINS
++	__sync_lock_test_and_set(&lock->s_waiters, flag);
++#else
 +	lock->s_waiters = flag;
++#endif
 +}
 +UNIV_INLINE
 +void
@@ -297,7 +148,11 @@
 +	rw_lock_t*	lock,
 +	ulint		flag)
 +{
++#ifdef HAVE_ATOMIC_BUILTINS
++	__sync_lock_test_and_set(&lock->x_waiters, flag);
++#else
 +	lock->x_waiters = flag;
++#endif
 +}
 +UNIV_INLINE
 +void
@@ -306,11 +161,15 @@
 +	rw_lock_t*      lock,
 +	ulint           flag)
 +{
++#ifdef HAVE_ATOMIC_BUILTINS
++	__sync_lock_test_and_set(&lock->wait_ex_waiters, flag);
++#else
 +	lock->wait_ex_waiters = flag;
++#endif
  }
  UNIV_INLINE
  ulint
-@@ -68,7 +100,19 @@
+@@ -68,7 +112,19 @@
  /*===============*/
  	rw_lock_t*	lock)
  {
@@ -330,7 +189,7 @@
  }
  UNIV_INLINE
  void
-@@ -96,6 +140,7 @@
+@@ -96,6 +152,7 @@
  {
  	lock->reader_count = count;
  }
@@ -338,7 +197,7 @@
  UNIV_INLINE
  mutex_t*
  rw_lock_get_mutex(
-@@ -104,6 +149,7 @@
+@@ -104,6 +161,7 @@
  {
  	return(&(lock->mutex));
  }
@@ -346,7 +205,7 @@
  
  /**********************************************************************
  Returns the value of writer_count for the lock. Does not reserve the lock
-@@ -133,14 +179,26 @@
+@@ -133,14 +191,26 @@
  	const char*	file_name, /* in: file name where lock requested */
  	ulint		line)	/* in: line where requested */
  {
@@ -374,7 +233,7 @@
  
  #ifdef UNIV_SYNC_DEBUG
  		rw_lock_add_debug_info(lock, pass, RW_LOCK_SHARED, file_name,
-@@ -167,11 +225,15 @@
+@@ -167,11 +237,15 @@
  	const char*	file_name,	/* in: file name where requested */
  	ulint		line)		/* in: line where lock requested */
  {
@@ -391,7 +250,7 @@
  
  	lock->last_s_file_name = file_name;
  	lock->last_s_line = line;
-@@ -199,7 +261,11 @@
+@@ -199,7 +273,11 @@
  
  	rw_lock_set_writer(lock, RW_LOCK_EX);
  	lock->writer_thread = os_thread_get_curr_id();
@@ -403,7 +262,7 @@
  	lock->pass = 0;
  			
  	lock->last_x_file_name = file_name;
-@@ -241,15 +307,21 @@
+@@ -241,15 +319,21 @@
  	ut_ad(!rw_lock_own(lock, RW_LOCK_SHARED)); /* see NOTE above */
  #endif /* UNIV_SYNC_DEBUG */
  
@@ -425,7 +284,7 @@
  
  		rw_lock_s_lock_spin(lock, pass, file_name, line);
  
-@@ -272,11 +344,23 @@
+@@ -272,11 +356,23 @@
  {
  	ibool	success	= FALSE;
  
@@ -449,7 +308,7 @@
  
  #ifdef UNIV_SYNC_DEBUG
  		rw_lock_add_debug_info(lock, 0, RW_LOCK_SHARED, file_name,
-@@ -289,7 +373,9 @@
+@@ -289,7 +385,9 @@
  		success = TRUE;
  	}
  
@@ -459,20 +318,20 @@
  
  	return(success);
  }
-@@ -309,6 +395,55 @@
+@@ -309,6 +407,54 @@
  {
  	ibool		success		= FALSE;
  	os_thread_id_t	curr_thread	= os_thread_get_curr_id();
 +#ifdef HAVE_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) {
++	if (lock->reader_count == 0) {
++		/* try to lock writer */
++		if(__sync_lock_test_and_set(&(lock->writer),RW_LOCK_EX)
++				== RW_LOCK_NOT_LOCKED) {
 +			/* success */
-+			/* try to lock writer */
-+			if(__sync_lock_test_and_set(&(lock->writer),RW_LOCK_EX)
-+					== RW_LOCK_NOT_LOCKED) {
++retry_x_lock:
++			/* try x-lock */
++			if(__sync_sub_and_fetch(&(lock->lock_word),
++					RW_LOCK_BIAS) == 0) {
 +				/* success */
 +				lock->writer_thread = curr_thread;
 +				lock->pass = 0;
@@ -492,30 +351,29 @@
 +
 +				return(TRUE);
 +			} else {
-+				/* x-unlock */
-+				__sync_fetch_and_add(&(lock->lock_word),
-+					RW_LOCK_BIAS);
++				/* fail (x-lock) */
++				if (__sync_fetch_and_add(&(lock->lock_word),RW_LOCK_BIAS)
++						== 0)
++					goto retry_x_lock;
 +			}
-+		} else {
-+			/* fail (x-lock) */
-+			__sync_fetch_and_add(&(lock->lock_word),RW_LOCK_BIAS);
++
++			__sync_lock_test_and_set(&(lock->writer),RW_LOCK_NOT_LOCKED);
 +		}
 +	}
 +
 +	if (lock->pass == 0
-+			&& os_thread_eq(lock->writer_thread, curr_thread)
-+			&& rw_lock_get_writer(lock) == RW_LOCK_EX) {
++			&& os_thread_eq(lock->writer_thread, curr_thread)) {
 +		goto relock;
 +	}
 +
-+	ut_ad(rw_lock_validate(lock));
++	//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)) {
-@@ -339,6 +474,7 @@
+@@ -339,6 +485,7 @@
          ut_ad(rw_lock_validate(lock));
  
  	return(success);
@@ -523,7 +381,7 @@
  }
  
  /**********************************************************************
-@@ -354,16 +490,33 @@
+@@ -354,16 +501,33 @@
  #endif
  	)
  {
@@ -558,37 +416,37 @@
  
  #ifdef UNIV_SYNC_DEBUG
  	rw_lock_remove_debug_info(lock, pass, RW_LOCK_SHARED);
-@@ -372,20 +525,36 @@
+@@ -372,22 +536,39 @@
  	/* If there may be waiters and this was the last s-lock,
  	signal the object */
  
 -	if (UNIV_UNLIKELY(lock->waiters)
 +#ifdef HAVE_ATOMIC_BUILTINS
-+	if (UNIV_UNLIKELY(last && lock->wait_ex_waiters)) {
++	if (UNIV_UNLIKELY(last && __sync_lock_test_and_set(&lock->wait_ex_waiters, 0))) {
++		os_event_set(lock->wait_ex_event);
++		sync_array_object_signalled(sync_primary_wait_array);
++	}
++	else if (UNIV_UNLIKELY(last && __sync_lock_test_and_set(&lock->x_waiters, 0))) {
++		os_event_set(lock->x_event);
++		sync_array_object_signalled(sync_primary_wait_array);
++	}
 +#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_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_ATOMIC_BUILTINS
  	mutex_exit(mutex);
-+#endif
  
 -	if (UNIV_UNLIKELY(sg)) {
 -#ifdef __WIN__
@@ -601,8 +459,11 @@
 +		os_event_set(lock->x_event);
  		sync_array_object_signalled(sync_primary_wait_array);
  	}
- 
-@@ -409,13 +578,22 @@
++#endif
+ 
+         ut_ad(rw_lock_validate(lock));
+ 
+@@ -409,13 +590,22 @@
  
  	ut_ad(lock->reader_count > 0);
  
@@ -625,7 +486,7 @@
          ut_ad(rw_lock_validate(lock));
  #ifdef UNIV_SYNC_PERF_STAT
  	rw_s_exit_count++;
-@@ -435,41 +613,81 @@
+@@ -435,41 +625,83 @@
  #endif
  	)
  {
@@ -658,10 +519,7 @@
 +		/* 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();
++		__sync_lock_test_and_set(&(lock->writer),RW_LOCK_NOT_LOCKED);
 +	}
 +#else
  	lock->writer_count--;
@@ -683,9 +541,15 @@
 -		rw_lock_set_waiters(lock, 0);
 +#ifdef HAVE_ATOMIC_BUILTINS
 +	if (last) {
++		if(__sync_lock_test_and_set(&lock->s_waiters, 0)){
++			s_sg = TRUE;
++		}
++		if(__sync_lock_test_and_set(&lock->x_waiters, 0)){
++			x_sg = TRUE;
++		}
++	}
 +#else
 +	if (lock->writer_count == 0) {
-+#endif
 +		if(lock->s_waiters){
 +			s_sg = TRUE;
 +			rw_lock_set_s_waiters(lock, 0);
@@ -696,7 +560,6 @@
 +		}
  	}
  	
-+#ifndef HAVE_ATOMIC_BUILTINS
  	mutex_exit(&(lock->mutex));
 +#endif
  
@@ -715,7 +578,7 @@
  		sync_array_object_signalled(sync_primary_wait_array);
  	}
  
-@@ -494,9 +712,13 @@
+@@ -494,9 +726,13 @@
  
  	ut_ad(lock->writer_count > 0);
  
@@ -729,7 +592,7 @@
  		rw_lock_set_writer(lock, RW_LOCK_NOT_LOCKED);
  	}
  
-@@ -504,7 +726,12 @@
+@@ -504,7 +740,12 @@
  	rw_lock_remove_debug_info(lock, 0, RW_LOCK_EX);
  #endif
  
@@ -742,9 +605,9 @@
          ut_ad(rw_lock_validate(lock));
  
  #ifdef UNIV_SYNC_PERF_STAT
-diff -r 962aec0d731c innobase/sync/sync0arr.c
---- a/innobase/sync/sync0arr.c	Thu Oct 09 08:28:53 2008 -0700
-+++ b/innobase/sync/sync0arr.c	Thu Oct 09 08:30:28 2008 -0700
+diff -ruN a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c
+--- a/innobase/sync/sync0arr.c	2009-01-30 06:42:24.000000000 +0900
++++ b/innobase/sync/sync0arr.c	2009-04-16 16:15:28.000000000 +0900
 @@ -309,13 +309,13 @@
  {
  	if (type == SYNC_MUTEX) {
@@ -877,9 +740,9 @@
  				}
                          }
                  }
-diff -r 962aec0d731c innobase/sync/sync0rw.c
---- a/innobase/sync/sync0rw.c	Thu Oct 09 08:28:53 2008 -0700
-+++ b/innobase/sync/sync0rw.c	Thu Oct 09 08:30:28 2008 -0700
+diff -ruN a/innobase/sync/sync0rw.c b/innobase/sync/sync0rw.c
+--- a/innobase/sync/sync0rw.c	2009-01-30 06:42:24.000000000 +0900
++++ b/innobase/sync/sync0rw.c	2009-04-16 17:33:59.000000000 +0900
 @@ -99,6 +99,7 @@
  	object is created, then the following call initializes
  	the sync system. */
@@ -1036,7 +899,7 @@
  
 -		rw_lock_set_waiters(lock, 1);
 +		rw_lock_set_s_waiters(lock, 1);
- 
++
 +#ifdef HAVE_ATOMIC_BUILTINS
 +		/* like sync0sync.c doing */
 +		for (i = 0; i < 4; i++) {
@@ -1045,10 +908,10 @@
 +				return; /* Success */
 +			}
 +		}
-+
+ 
 +		/* If wait_ex_waiter stalls, wakes it. */
-+		if (lock->wait_ex_waiters && lock->lock_word == RW_LOCK_BIAS) {
-+			rw_lock_set_wx_waiters(lock, 0);
++		if (lock->reader_count == 0
++		    && __sync_lock_test_and_set(&lock->wait_ex_waiters, 0)) {
 +			os_event_set(lock->wait_ex_event);
 +			sync_array_object_signalled(sync_primary_wait_array);
 +		}
@@ -1058,7 +921,7 @@
  
  		if (srv_print_latch_waits) {
  			fprintf(stderr,
-@@ -318,13 +358,19 @@
+@@ -318,13 +365,19 @@
  {
  	ut_ad(rw_lock_is_locked(lock, RW_LOCK_EX));
  
@@ -1078,13 +941,13 @@
  }
  
  /**********************************************************************
-@@ -342,6 +388,89 @@
+@@ -342,6 +395,89 @@
  	const char*	file_name,/* in: file name where lock requested */
  	ulint		line)	/* in: line where requested */
  {
 +#ifdef HAVE_ATOMIC_BUILTINS
 +	os_thread_id_t	curr_thread	= os_thread_get_curr_id();
-+
++retry_writer:
 +	/* try to lock writer */
 +	if(__sync_lock_test_and_set(&(lock->writer),RW_LOCK_EX)
 +			== RW_LOCK_NOT_LOCKED) {
@@ -1160,15 +1023,15 @@
 +
 +		break;
 +
-+	    default: /* ??? */
-+		return(RW_LOCK_NOT_LOCKED);
++	    default: /* RW_LOCK_NOT_LOCKED? maybe impossible */
++		goto retry_writer;
 +	}
 +#else /* HAVE_ATOMIC_BUILTINS */
 +
  #ifdef UNIV_SYNC_DEBUG
  	ut_ad(mutex_own(rw_lock_get_mutex(lock)));
  #endif /* UNIV_SYNC_DEBUG */
-@@ -423,6 +552,7 @@
+@@ -423,6 +559,7 @@
  		/* Locking succeeded, we may return */
  		return(RW_LOCK_EX);
  	}
@@ -1176,7 +1039,7 @@
  
  	/* Locking did not succeed */
  	return(RW_LOCK_NOT_LOCKED);
-@@ -448,19 +578,33 @@
+@@ -448,19 +585,33 @@
  	ulint		line)	/* in: line where requested */
  {
          ulint	index;  /* index of the reserved wait cell */
@@ -1211,7 +1074,7 @@
  	if (state == RW_LOCK_EX) {
  
  		return;	/* Locking succeeded */
-@@ -468,10 +612,9 @@
+@@ -468,10 +619,9 @@
  	} else if (state == RW_LOCK_NOT_LOCKED) {
  
   		/* Spin waiting for the writer field to become free */
@@ -1220,11 +1083,11 @@
 -        	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) {
++			&& lock->lock_word != RW_LOCK_BIAS) {
          		if (srv_spin_wait_delay) {
  				ut_delay(ut_rnd_interval(0,
  							srv_spin_wait_delay));
-@@ -485,9 +628,12 @@
+@@ -485,9 +635,12 @@
          } else if (state == RW_LOCK_WAIT_EX) {
  
   		/* Spin waiting for the reader count field to become zero */
@@ -1238,7 +1101,7 @@
                 					&& i < SYNC_SPIN_ROUNDS) {
          		if (srv_spin_wait_delay) {
  				ut_delay(ut_rnd_interval(0,
-@@ -500,7 +646,6 @@
+@@ -500,7 +653,6 @@
  			os_thread_yield();
  		}
          } else {
@@ -1246,7 +1109,7 @@
  		ut_error;
  	}	
  
-@@ -516,34 +661,69 @@
+@@ -516,34 +668,69 @@
          /* We try once again to obtain the lock. Acquire the mutex protecting
  	the rw-lock fields */
  
@@ -1269,7 +1132,7 @@
  
  		return;	/* Locking succeeded */
  	}
-+
+ 
 +#ifdef HAVE_ATOMIC_BUILTINS
 +	/* like sync0sync.c doing */
 +	i++;
@@ -1278,7 +1141,7 @@
 +		goto spin_loop;
 +	}
 +#endif
- 
++
  	rw_x_system_call_count++;
  
          sync_array_reserve_cell(sync_primary_wait_array,
@@ -1322,7 +1185,7 @@
  
  	if (srv_print_latch_waits) {
  		fprintf(stderr,
-@@ -718,7 +898,9 @@
+@@ -718,7 +905,9 @@
  	ut_ad(lock);
  	ut_ad(rw_lock_validate(lock));
  
@@ -1332,7 +1195,7 @@
  
  	info = UT_LIST_GET_FIRST(lock->debug_list);
  
-@@ -728,7 +910,9 @@
+@@ -728,7 +917,9 @@
  		    && (info->pass == 0)
  		    && (info->lock_type == lock_type)) {
  
@@ -1342,7 +1205,7 @@
  		    	/* Found! */
  
  		    	return(TRUE);
-@@ -736,7 +920,9 @@
+@@ -736,7 +927,9 @@
  
  		info = UT_LIST_GET_NEXT(list, info);
  	}
@@ -1352,7 +1215,7 @@
  
  	return(FALSE);
  }
-@@ -758,21 +944,25 @@
+@@ -758,21 +951,25 @@
  	ut_ad(lock);
  	ut_ad(rw_lock_validate(lock));
  	
@@ -1379,7 +1242,7 @@
  
  	return(ret);
  }
-@@ -801,16 +991,26 @@
+@@ -801,16 +998,26 @@
  
  		count++;
  
@@ -1409,7 +1272,7 @@
  			} else {
  				putc('\n', stderr);
  			}
-@@ -822,7 +1022,9 @@
+@@ -822,7 +1029,9 @@
  			}
  		}
  
@@ -1419,7 +1282,7 @@
  		lock = UT_LIST_GET_NEXT(list, lock);
  	}
  
-@@ -847,10 +1049,18 @@
+@@ -847,10 +1056,18 @@
  
  	if ((rw_lock_get_writer(lock) != RW_LOCK_NOT_LOCKED)
  	    || (rw_lock_get_reader_count(lock) != 0)
@@ -1441,7 +1304,7 @@
  		} else {
  			putc('\n', stderr);
  		}
-@@ -909,14 +1119,18 @@
+@@ -909,14 +1126,18 @@
  	lock = UT_LIST_GET_FIRST(rw_lock_list);
  
  	while (lock != NULL) {
@@ -1460,9 +1323,9 @@
  		lock = UT_LIST_GET_NEXT(list, lock);
  	}
  
-diff -r 962aec0d731c patch_info/innodb_rw_lock.info
---- /dev/null	Thu Jan 01 00:00:00 1970 +0000
-+++ b/patch_info/innodb_rw_lock.info	Thu Oct 09 08:30:28 2008 -0700
+diff -ruN a/patch_info/innodb_rw_lock.info b/patch_info/innodb_rw_lock.info
+--- a/patch_info/innodb_rw_lock.info	1970-01-01 09:00:00.000000000 +0900
++++ b/patch_info/innodb_rw_lock.info	2009-04-16 16:15:28.000000000 +0900
 @@ -0,0 +1,6 @@
 +File=innodb_rw_lock.patch
 +Name=Fix of InnoDB rw_locks

=== added file 'innodb_thread_concurrency_timer_based.patch'
--- innodb_thread_concurrency_timer_based.patch	1970-01-01 00:00:00 +0000
+++ innodb_thread_concurrency_timer_based.patch	2009-05-06 09:53:18 +0000
@@ -0,0 +1,389 @@
+diff -ruN a/innobase/configure b/innobase/configure
+--- a/innobase/configure	2009-01-30 06:56:31.000000000 +0900
++++ b/innobase/configure	2009-05-06 15:40:47.000000000 +0900
+@@ -21306,6 +21306,88 @@
+ fi
+ done
+ 
++
++# as http://lists.mysql.com/commits/40686 does
++{ echo "$as_me:$LINENO: checking whether the compiler provides atomic builtins" >&5
++echo $ECHO_N "checking whether the compiler provides atomic builtins... $ECHO_C" >&6; }
++if test "${mysql_cv_atomic_builtins+set}" = set; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++  if test "$cross_compiling" = yes; then
++  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
++See \`config.log' for more details." >&5
++echo "$as_me: error: cannot run test program while cross compiling
++See \`config.log' for more details." >&2;}
++   { (exit 1); exit 1; }; }
++else
++  cat >conftest.$ac_ext <<_ACEOF
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
++
++  int main()
++  {
++    int foo= -10; int bar= 10;
++    __sync_fetch_and_add(&foo, bar);
++    if (foo)
++      return -1;
++    bar= __sync_lock_test_and_set(&foo, bar);
++    if (bar || foo != 10)
++      return -1;
++    bar= __sync_val_compare_and_swap(&bar, foo, 15);
++    if (bar)
++      return -1;
++    return 0;
++  }
++
++_ACEOF
++rm -f conftest$ac_exeext
++if { (ac_try="$ac_link"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
++  (eval "$ac_link") 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
++  { (case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
++  (eval "$ac_try") 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; }; then
++  mysql_cv_atomic_builtins=yes
++else
++  echo "$as_me: program exited with status $ac_status" >&5
++echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++( exit $ac_status )
++mysql_cv_atomic_builtins=no
++fi
++rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
++fi
++
++
++fi
++{ echo "$as_me:$LINENO: result: $mysql_cv_atomic_builtins" >&5
++echo "${ECHO_T}$mysql_cv_atomic_builtins" >&6; }
++
++if test "x$mysql_cv_atomic_builtins" = xyes; then
++
++cat >>confdefs.h <<\_ACEOF
++#define HAVE_ATOMIC_BUILTINS 1
++_ACEOF
++
++fi
++
+ #AC_CHECK_FUNCS(readdir_r) MySQL checks that it has also the right args.
+ # Some versions of Unix only take 2 arguments.
+ #AC_C_INLINE  Already checked in MySQL
+diff -ruN a/innobase/configure.in b/innobase/configure.in
+--- a/innobase/configure.in	2009-01-30 06:42:15.000000000 +0900
++++ b/innobase/configure.in	2009-05-06 15:40:47.000000000 +0900
+@@ -42,6 +42,31 @@
+ AC_CHECK_FUNCS(sched_yield)
+ AC_CHECK_FUNCS(fdatasync)
+ AC_CHECK_FUNCS(localtime_r)
++
++# as http://lists.mysql.com/commits/40686 does
++AC_CACHE_CHECK([whether the compiler provides atomic builtins],
++               [mysql_cv_atomic_builtins], [AC_TRY_RUN([
++  int main()
++  {
++    int foo= -10; int bar= 10;
++    __sync_fetch_and_add(&foo, bar);
++    if (foo)
++      return -1;
++    bar= __sync_lock_test_and_set(&foo, bar);
++    if (bar || foo != 10)
++      return -1;
++    bar= __sync_val_compare_and_swap(&bar, foo, 15);
++    if (bar)
++      return -1;
++    return 0;
++  }
++], [mysql_cv_atomic_builtins=yes], [mysql_cv_atomic_builtins=no])])
++
++if test "x$mysql_cv_atomic_builtins" = xyes; then
++  AC_DEFINE(HAVE_ATOMIC_BUILTINS, 1,
++            [Define to 1 if compiler provides atomic builtins.])
++fi
++
+ #AC_CHECK_FUNCS(readdir_r) MySQL checks that it has also the right args.
+ # Some versions of Unix only take 2 arguments.
+ #AC_C_INLINE  Already checked in MySQL
+diff -ruN a/innobase/ib_config.h b/innobase/ib_config.h
+--- a/innobase/ib_config.h	2009-01-30 07:05:03.000000000 +0900
++++ b/innobase/ib_config.h	2009-05-06 15:40:47.000000000 +0900
+@@ -7,6 +7,9 @@
+ /* Define to 1 if you have the <aio.h> header file. */
+ #define HAVE_AIO_H 1
+ 
++/* Define to 1 if compiler provides atomic builtins. */
++#define HAVE_ATOMIC_BUILTINS 1
++
+ /* Define to 1 if you have the <dlfcn.h> header file. */
+ #define HAVE_DLFCN_H 1
+ 
+diff -ruN a/innobase/ib_config.h.in b/innobase/ib_config.h.in
+--- a/innobase/ib_config.h.in	2009-01-30 06:56:11.000000000 +0900
++++ b/innobase/ib_config.h.in	2009-05-06 15:40:47.000000000 +0900
+@@ -6,6 +6,9 @@
+ /* Define to 1 if you have the <aio.h> header file. */
+ #undef HAVE_AIO_H
+ 
++/* Define to 1 if compiler provides atomic builtins. */
++#undef HAVE_ATOMIC_BUILTINS
++
+ /* Define to 1 if you have the <dlfcn.h> header file. */
+ #undef HAVE_DLFCN_H
+ 
+diff -ruN a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
+--- a/innobase/include/srv0srv.h	2009-05-06 15:38:01.000000000 +0900
++++ b/innobase/include/srv0srv.h	2009-05-06 16:04:36.000000000 +0900
+@@ -90,6 +90,8 @@
+ extern ulint	srv_mem_pool_size;
+ extern ulint	srv_lock_table_size;
+ 
++extern ibool	srv_thread_concurrency_timer_based;
++
+ extern ulint	srv_n_file_io_threads;
+ extern ulint	srv_n_read_io_threads;
+ extern ulint	srv_n_write_io_threads;
+diff -ruN a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
+--- a/innobase/srv/srv0srv.c	2009-05-06 15:38:01.000000000 +0900
++++ b/innobase/srv/srv0srv.c	2009-05-06 17:12:54.000000000 +0900
+@@ -267,6 +267,7 @@
+ computer. Bigger computers need bigger values. Value 0 will disable the
+ concurrency check. */
+ 
++ibool	srv_thread_concurrency_timer_based = TRUE;
+ ulong	srv_thread_concurrency	= 0;
+ ulong   srv_commit_concurrency  = 0;
+ 
+@@ -1020,6 +1021,74 @@
+ Puts an OS thread to wait if there are too many concurrent threads
+ (>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */
+ 
++#ifdef HAVE_ATOMIC_BUILTINS
++static void
++enter_innodb_with_tickets(trx_t* trx)
++{
++	trx->declared_to_be_inside_innodb = TRUE;
++	trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER;
++	return;
++}
++
++static void
++srv_conc_enter_innodb_timer_based(trx_t* trx)
++{
++	lint	conc_n_threads;
++	ibool	has_yielded = FALSE;
++	ulint	has_slept = 0;
++
++	if (trx->declared_to_be_inside_innodb) {
++		ut_print_timestamp(stderr);
++		fputs(
++"  InnoDB: Error: trying to declare trx to enter InnoDB, but\n"
++"InnoDB: it already is declared.\n", stderr);
++		trx_print(stderr, trx, 0);
++		putc('\n', stderr);
++	}
++retry:
++	if (srv_conc_n_threads < (lint) srv_thread_concurrency) {
++		conc_n_threads = __sync_add_and_fetch(&srv_conc_n_threads, 1);
++		if (conc_n_threads <= (lint) srv_thread_concurrency) {
++			enter_innodb_with_tickets(trx);
++			return;
++		}
++		__sync_add_and_fetch(&srv_conc_n_threads, -1);
++	}
++	if (!has_yielded)
++	{
++		has_yielded = TRUE;
++		os_thread_yield();
++		goto retry;
++	}
++	if (trx->has_search_latch
++	    || NULL != UT_LIST_GET_FIRST(trx->trx_locks)) {
++
++		conc_n_threads = __sync_add_and_fetch(&srv_conc_n_threads, 1);
++		enter_innodb_with_tickets(trx);
++		return;
++	}
++	if (has_slept < 2)
++	{
++		trx->op_info = "sleeping before entering InnoDB";
++		os_thread_sleep(10000);
++		trx->op_info = "";
++		has_slept++;
++	}
++	conc_n_threads = __sync_add_and_fetch(&srv_conc_n_threads, 1);
++	enter_innodb_with_tickets(trx);
++	return;
++}
++
++static void
++srv_conc_exit_innodb_timer_based(trx_t* trx)
++{
++	__sync_add_and_fetch(&srv_conc_n_threads, -1);
++	trx->declared_to_be_inside_innodb = FALSE;
++	trx->n_tickets_to_enter_innodb = 0;
++	return;
++}
++#endif
++
+ void
+ srv_conc_enter_innodb(
+ /*==================*/
+@@ -1043,6 +1112,13 @@
+ 		return;
+ 	}
+ 
++#ifdef HAVE_ATOMIC_BUILTINS
++	if (srv_thread_concurrency_timer_based) {
++		srv_conc_enter_innodb_timer_based(trx);
++		return;
++	}
++#endif
++
+ 	os_fast_mutex_lock(&srv_conc_mutex);
+ retry:
+ 	if (trx->declared_to_be_inside_innodb) {
+@@ -1196,6 +1272,15 @@
+ 		return;
+ 	}
+ 
++	ut_ad(srv_conc_n_threads >= 0);
++#ifdef HAVE_ATOMIC_BUILTINS
++	if (srv_thread_concurrency_timer_based) {
++		__sync_add_and_fetch(&srv_conc_n_threads, 1);
++		trx->declared_to_be_inside_innodb = TRUE;
++		trx->n_tickets_to_enter_innodb = 1;
++		return;
++	}
++#endif
+ 	os_fast_mutex_lock(&srv_conc_mutex);
+ 
+ 	srv_conc_n_threads++;
+@@ -1227,8 +1312,16 @@
+ 		return;
+ 	}
+ 
++#ifdef HAVE_ATOMIC_BUILTINS
++	if (srv_thread_concurrency_timer_based) {
++		srv_conc_exit_innodb_timer_based(trx);
++		return;
++	}
++#endif
++
+ 	os_fast_mutex_lock(&srv_conc_mutex);
+ 
++	ut_ad(srv_conc_n_threads > 0);
+ 	srv_conc_n_threads--;
+ 	trx->declared_to_be_inside_innodb = FALSE;
+ 	trx->n_tickets_to_enter_innodb = 0;
+diff -ruN a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
+--- a/innobase/srv/srv0start.c	2009-05-06 15:38:01.000000000 +0900
++++ b/innobase/srv/srv0start.c	2009-05-06 17:22:26.000000000 +0900
+@@ -1040,6 +1040,11 @@
+ 		return(DB_ERROR);
+ 	}
+ 
++#ifdef HAVE_ATOMIC_BUILTINS
++	fprintf(stderr,
++		"InnoDB: use atomic builtins.\n");
++#endif
++
+ 	/* Since InnoDB does not currently clean up all its internal data
+ 	   structures in MySQL Embedded Server Library server_end(), we
+ 	   print an error message if someone tries to start up InnoDB a
+diff -ruN a/patch_info/innodb_thread_concurrency_timer_based.info b/patch_info/innodb_thread_concurrency_timer_based.info
+--- /dev/null	1970-01-01 09:00:00.000000000 +0900
++++ b/patch_info/innodb_thread_concurrency_timer_based.info	2009-05-06 17:17:12.000000000 +0900
+@@ -0,0 +1,6 @@
++File=thread_concurrency_timer_based.patch
++Name=Use InnoDB timer based concurrency throttling (backport from MySQL 5.4.0)
++Version=1.0
++Author=Percona <info@xxxxxxxxxxx>
++License=GPL
++Comment
+diff -ruN a/sql/ha_innodb.cc b/sql/ha_innodb.cc
+--- a/sql/ha_innodb.cc	2009-05-06 15:38:01.000000000 +0900
++++ b/sql/ha_innodb.cc	2009-05-06 15:54:08.000000000 +0900
+@@ -152,6 +152,7 @@
+      innobase_open_files;
+ 
+ long innobase_read_io_threads, innobase_write_io_threads;
++my_bool innobase_thread_concurrency_timer_based;
+ long innobase_extra_rsegments;
+ longlong innobase_buffer_pool_size, innobase_log_file_size;
+ 
+@@ -1477,6 +1478,9 @@
+ 	srv_n_log_files = (ulint) innobase_log_files_in_group;
+ 	srv_log_file_size = (ulint) innobase_log_file_size;
+ 
++	srv_thread_concurrency_timer_based =
++		(ibool) innobase_thread_concurrency_timer_based;
++
+ #ifdef UNIV_LOG_ARCHIVE
+ 	srv_log_archive_on = (ulint) innobase_log_archive;
+ #endif /* UNIV_LOG_ARCHIVE */
+diff -ruN a/sql/ha_innodb.h b/sql/ha_innodb.h
+--- a/sql/ha_innodb.h	2009-05-06 15:38:01.000000000 +0900
++++ b/sql/ha_innodb.h	2009-05-06 15:55:50.000000000 +0900
+@@ -205,6 +205,7 @@
+ extern long innobase_buffer_pool_awe_mem_mb;
+ extern long innobase_file_io_threads, innobase_lock_wait_timeout;
+ extern long innobase_read_io_threads, innobase_write_io_threads;
++extern my_bool innobase_thread_concurrency_timer_based;
+ extern long innobase_extra_rsegments;
+ extern long innobase_force_recovery;
+ extern long innobase_open_files;
+diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
+--- a/sql/mysqld.cc	2009-05-06 15:38:01.000000000 +0900
++++ b/sql/mysqld.cc	2009-05-06 16:22:06.000000000 +0900
+@@ -5096,6 +5096,7 @@
+   OPT_INNODB_ADAPTIVE_CHECKPOINT,
+   OPT_INNODB_READ_IO_THREADS,
+   OPT_INNODB_WRITE_IO_THREADS,
++  OPT_INNODB_THREAD_CONCURRENCY_TIMER_BASED,
+   OPT_INNODB_EXTRA_RSEGMENTS,
+   OPT_INNODB_DICT_SIZE_LIMIT,
+   OPT_INNODB_ADAPTIVE_HASH_INDEX,
+@@ -5455,6 +5456,11 @@
+    "Number of background write I/O threads in InnoDB.",
+    (gptr*) &innobase_write_io_threads, (gptr*) &innobase_write_io_threads,
+    0, GET_LONG, REQUIRED_ARG, 1, 1, 64, 0, 0, 0},
++  {"innodb_thread_concurrency_timer_based", OPT_INNODB_THREAD_CONCURRENCY_TIMER_BASED,
++   "Use InnoDB timer based concurrency throttling. ",
++   (gptr*) &innobase_thread_concurrency_timer_based,
++   (gptr*) &innobase_thread_concurrency_timer_based,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+   {"innodb_extra_rsegments", OPT_INNODB_EXTRA_RSEGMENTS,
+    "Number of extra user rollback segments when create new database.",
+    (gptr*) &innobase_extra_rsegments, (gptr*) &innobase_extra_rsegments,
+diff -ruN a/sql/set_var.cc b/sql/set_var.cc
+--- a/sql/set_var.cc	2009-05-06 15:38:01.000000000 +0900
++++ b/sql/set_var.cc	2009-05-06 16:02:27.000000000 +0900
+@@ -1063,6 +1063,7 @@
+   {sys_innodb_adaptive_checkpoint.name, (char*) &sys_innodb_adaptive_checkpoint, SHOW_SYS},
+   {"innodb_read_io_threads", (char*) &innobase_read_io_threads, SHOW_LONG},
+   {"innodb_write_io_threads", (char*) &innobase_write_io_threads, SHOW_LONG},
++  {"innodb_thread_concurrency_timer_based", (char*) &innobase_thread_concurrency_timer_based, SHOW_MY_BOOL},
+   {"innodb_extra_rsegments", (char*) &innobase_extra_rsegments, SHOW_LONG},
+   {sys_innodb_dict_size_limit.name, (char*) &sys_innodb_dict_size_limit, SHOW_SYS},
+   {sys_innodb_io_pattern_trace.name, (char*) &sys_innodb_io_pattern_trace, SHOW_SYS},

=== modified file 'series'
--- series	2009-01-26 08:43:23 +0000
+++ series	2009-05-06 09:53:18 +0000
@@ -12,5 +12,7 @@
 innodb_fsync_source.patch
 innodb_show_hashed_memory.patch
 innodb_dict_size_limit.patch
+innodb_extra_rseg.patch
+innodb_thread_concurrency_timer_based.patch
 split_buf_pool_mutex_fixed_optimistic_safe.patch
 innodb_rw_lock.patch


Follow ups