Index: storage/innobase/lock/lock0wait.cc
===================================================================
--- storage/innobase/lock/lock0wait.cc	(revision 4442)
+++ storage/innobase/lock/lock0wait.cc	(working copy)
@@ -301,6 +301,22 @@
 		srv_conc_force_exit_innodb(trx);
 	}
 
+	/* Release the exec_lock for that hash bucket, so the next thread in
+	   that bucket queue could continue */
+
+	if (trx->holds_exec_lock == 1) {
+
+		ut_a(trx->queue_rescheduled == 1);
+
+		int lock_fold = trx->lock.req_wait_lock->rec_hv;
+
+		pthread_mutex_unlock(wait_lock_sys->exec_lock_mutexes+lock_fold);
+
+		trx->holds_exec_lock = 0;
+
+		os_event_set(wait_lock_sys->exec_lock_events[lock_fold]);
+	}
+
 	os_event_wait(slot->event);
 
 	/* After resuming, reacquire the data dictionary latch if
Index: storage/innobase/lock/lock0lock.cc
===================================================================
--- storage/innobase/lock/lock0lock.cc	(revision 4442)
+++ storage/innobase/lock/lock0lock.cc	(working copy)
@@ -385,6 +385,9 @@
 UNIV_INTERN mysql_pfs_key_t	lock_sys_mutex_key;
 /* Key to register mutex with performance schema */
 UNIV_INTERN mysql_pfs_key_t	lock_sys_wait_mutex_key;
+
+/* Key to register mutex with performance schema */
+UNIV_INTERN mysql_pfs_key_t	wait_lock_sys_mutex_key;
 #endif /* UNIV_PFS_MUTEX */
 
 #ifdef UNIV_DEBUG
@@ -412,6 +415,14 @@
 /* The lock system */
 UNIV_INTERN lock_sys_t*	lock_sys	= NULL;
 
+UNIV_INTERN wait_lock_sys_t*  wait_lock_sys   = NULL;
+
+#ifdef UNIV_PFS_RWLOCK
+UNIV_INTERN mysql_pfs_key_t     lock_wait_hash_key;
+UNIV_INTERN mysql_pfs_key_t     lock_exec_hash_key;
+PSI_mutex_key lock_exec_mutexes_key;
+#endif /* UNIV_PFS_RWLOCK */
+
 /** We store info on the latest deadlock error to this buffer. InnoDB
 Monitor will then fetch it and print */
 UNIV_INTERN ibool	lock_deadlock_found = FALSE;
@@ -614,6 +625,43 @@
 
 	lock_sys->rec_hash = hash_create(n_cells);
 
+
+	/* Create and initialize the wait_lock_sys */
+
+	wait_lock_sys =  (wait_lock_sys_t*)mem_alloc(sizeof(wait_lock_sys_t));
+
+	mutex_create(wait_lock_sys_mutex_key,
+			&wait_lock_sys->mutex, NULL/*SYNC_LOCK_WAIT_SYS*/);
+
+	wait_lock_sys->lock_ref_hash = hash_create(n_cells);
+
+	wait_lock_sys->wait_lock_latch = (rw_lock_t**)mem_alloc(
+			sizeof(rw_lock_t*)* srv_wait_lock_latches);
+
+	wait_lock_sys->exec_lock_mutexes = static_cast<pthread_mutex_t*>(
+			mem_alloc(srv_wait_lock_latches * sizeof(pthread_mutex_t)));
+
+	wait_lock_sys->exec_lock_events = static_cast<os_event_t*>(
+			ut_malloc(srv_wait_lock_latches * 
+				sizeof *wait_lock_sys->exec_lock_events));
+
+	uint i;
+	for (i=0; i<srv_wait_lock_latches; i++) {
+
+		wait_lock_sys->wait_lock_latch[i] = 
+			(rw_lock_t*)mem_alloc(sizeof(rw_lock_t));
+
+		rw_lock_t *rwlock = wait_lock_sys->wait_lock_latch[i];
+
+		rw_lock_create(lock_wait_hash_key, rwlock, SYNC_WAIT_LOCK_LATCH);
+
+		pthread_mutex_init(wait_lock_sys->exec_lock_mutexes+i, MY_MUTEX_INIT_FAST);
+
+		rw_lock_create(lock_exec_hash_key, rwlock, SYNC_EXEC_LOCK_LATCH);
+
+		wait_lock_sys->exec_lock_events[i] = os_event_create();
+	}
+
 	if (!srv_read_only_mode) {
 		lock_latest_err_file = os_file_create_tmpfile();
 		ut_a(lock_latest_err_file);
@@ -642,6 +690,21 @@
 
 	lock_sys = NULL;
 	lock_stack = NULL;
+
+	/* Free wait lock sys */
+	uint i;
+	for (i=0; i<srv_wait_lock_latches; i++) {
+
+		rw_lock_free(wait_lock_sys->wait_lock_latch[i]);
+
+		mem_free(wait_lock_sys->wait_lock_latch[i]);
+	}
+
+	mem_free(wait_lock_sys->wait_lock_latch);
+	hash_table_free(wait_lock_sys->lock_ref_hash);
+
+	mem_free(wait_lock_sys);
+	wait_lock_sys = NULL;
 }
 
 /*********************************************************************//**
@@ -1784,12 +1847,16 @@
 
 	lock->trx = trx;
 
+	lock->block = (buf_block_t*)block;
+	lock->is_waiting = 0;
+
 	lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC;
 	lock->index = index;
 
 	lock->un_member.rec_lock.space = space;
 	lock->un_member.rec_lock.page_no = page_no;
 	lock->un_member.rec_lock.n_bits = n_bytes * 8;
+	lock->magic_num = 123456;
 
 	/* Reset to zero the bitmap which resides immediately after the
 	lock struct */
@@ -1814,6 +1881,70 @@
 	if (lock_is_wait_not_by_other(type_mode)) {
 
 		lock_set_lock_and_trx_wait(lock, trx);
+
+		/* Set the lock wait info for block controling purpose */
+
+		lock->magic_num = 654321;
+
+		/* Set block wide ref count */	
+		lock->block->n_ref_count++;
+		lock->is_waiting = 1;
+
+		//fprintf(stderr, "ref_count add =%ld\n", lock->block->n_ref_count);
+
+		ut_a(heap_no != 0);
+
+		ut_a(trx->is_lock_wait == 0);
+		trx->is_lock_wait = 1;
+		ut_a(lock_get_type_low(lock) == LOCK_REC);
+
+		char key[512] = {0};
+		snprintf(key, 512, "%ld%ld%ld", space, page_no, heap_no);
+
+		wait_lock_t* req_lock =  trx->lock.req_wait_lock;
+		req_lock->space   = space;
+		req_lock->page_no = page_no;
+		req_lock->heap_no = heap_no;
+		req_lock->rec_hv  = ut_fold_string(key) % MAX_WAIT_LOCK_LATCHES;
+
+		lock_ref_table_t* table; 
+
+		mutex_enter(&wait_lock_sys->mutex);
+
+		HASH_SEARCH(key_hash, wait_lock_sys->lock_ref_hash, 
+				ut_fold_string(key),
+				lock_ref_table_t*, table, 
+				NULL,
+				!strncmp(table->key, key, strlen(key)));
+
+		if (!table) {
+
+			table = (lock_ref_table_t*) my_malloc(
+					sizeof(lock_ref_table_t),
+					MYF(MY_FAE | MY_ZEROFILL));
+
+			table->ref_count = 1;
+			table->key = (char*) my_malloc(strlen(key)+1, 
+					MYF(MY_FAE | MY_ZEROFILL));
+			memcpy(table->key, key, strlen(key));
+
+			HASH_INSERT(lock_ref_table_t, key_hash,
+					wait_lock_sys->lock_ref_hash,
+					ut_fold_string(key), table);
+			//fprintf(stderr, "insert %p (%s %ld)\n", table, table->key, table->ref_count);
+
+
+
+		} else {
+
+			ut_a (table->ref_count > 0);
+
+			table->ref_count++;
+
+		}
+
+		mutex_exit(&wait_lock_sys->mutex);
+
 	}
 
 	UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock);
@@ -2150,6 +2281,56 @@
 	return(status);
 }
 
+
+static
+bool
+lock_wait_update_block_if_over_threshold(
+/*===============*/
+                const buf_block_t*      block,
+		trx_t* trx,
+                ulint heap_no)
+{
+	if (block->n_ref_count < srv_lock_wait_threshold) 
+		return FALSE;
+
+	lock_ref_table_t* table;
+
+
+	bool ret = 0;
+	char key[512] = {0};
+
+	ulint space = buf_block_get_space(block);
+	ulint page_no = buf_block_get_page_no(block);
+
+	snprintf(key, 512, "%ld%ld%ld", space,
+			page_no, 
+			heap_no);
+
+	wait_lock_t* req_lock = trx->lock.req_wait_lock;
+	req_lock->space = space;
+	req_lock->page_no = page_no;
+	req_lock->heap_no = heap_no;
+	req_lock->rec_hv = ut_fold_string(key) % MAX_WAIT_LOCK_LATCHES;
+
+	mutex_enter(&wait_lock_sys->mutex);
+	HASH_SEARCH(key_hash, wait_lock_sys->lock_ref_hash,
+			ut_fold_string(key),
+			lock_ref_table_t*, table, 
+			NULL,
+			!strncmp(table->key, key, strlen(key)));
+
+
+
+	if (table && table->ref_count >= srv_lock_wait_threshold) {
+		ret = 1;
+	} 
+
+	mutex_exit(&wait_lock_sys->mutex);
+
+	return ret;
+}
+
+
 /*********************************************************************//**
 This is the general, and slower, routine for locking a record. This is a
 low-level function which does NOT look at implicit locks! Checks lock
@@ -2229,6 +2410,24 @@
 
 		ut_ad(lock == NULL);
 enqueue_waiting:
+
+
+
+		if (srv_lock_wait_threshold > 0 && 
+		    lock_wait_update_block_if_over_threshold(block, trx, heap_no) &&
+		    trx->lock.ignore_wait_lock==0) {
+
+			/* In this case the lock waiting for the same record
+			   is too much, and we let current thread not enter 
+			   into innodb inside with DB_LOCK_WAIT_THRESHOLD 
+			   returned. */
+		
+
+			trx_mutex_exit(trx);
+
+			return DB_LOCK_WAIT_THRESHOLD;
+		}
+
 		err = lock_rec_enqueue_waiting(
 			mode, block, heap_no, lock, index, thr);
 
@@ -2471,6 +2670,13 @@
 
 	UT_LIST_REMOVE(trx_locks, trx_lock->trx_locks, in_lock);
 
+	/* Decrease the block lock waiting ref */
+	ut_a(lock_get_type_low(in_lock) == LOCK_REC);
+	if (in_lock->is_waiting == 1) {
+		in_lock->block->n_ref_count--;
+		in_lock->is_waiting = 0;
+	}
+
 	MONITOR_INC(MONITOR_RECLOCK_REMOVED);
 	MONITOR_DEC(MONITOR_NUM_RECLOCK);
 
@@ -2519,6 +2725,14 @@
 	HASH_DELETE(lock_t, hash, lock_sys->rec_hash,
 		    lock_rec_fold(space, page_no), in_lock);
 
+	/* Decrease the block lock waiting ref */
+
+	ut_a(lock_get_type_low(in_lock) == LOCK_REC);
+	if (in_lock->is_waiting == 1) {
+		in_lock->block->n_ref_count--;
+		in_lock->is_waiting = 0;
+	}
+
 	UT_LIST_REMOVE(trx_locks, trx_lock->trx_locks, in_lock);
 
 	MONITOR_INC(MONITOR_RECLOCK_REMOVED);
@@ -4631,6 +4845,8 @@
 	     lock != NULL;
 	     lock = UT_LIST_GET_LAST(trx->lock.trx_locks)) {
 
+	
+
 		if (lock_get_type_low(lock) == LOCK_REC) {
 
 #ifdef UNIV_DEBUG
@@ -4646,6 +4862,7 @@
 #endif /* UNIV_DEBUG */
 
 			lock_rec_dequeue_from_page(lock);
+			
 		} else {
 			dict_table_t*	table;
 
@@ -4704,6 +4921,95 @@
 	mem_heap_empty(trx->lock.lock_heap);
 }
 
+bool 
+lock_wait_over_threshold(
+/*=========*/
+                trx_t *trx)
+{
+	trx_mutex_enter(trx);
+
+	char key[512] = {0};
+	lock_ref_table_t* table;
+	wait_lock_t* req_lock =  trx->lock.req_wait_lock;
+
+	snprintf(key, 512, "%ld%ld%ld", 
+			req_lock->space, 
+			req_lock->page_no, 
+			req_lock->heap_no);
+
+	mutex_enter(&wait_lock_sys->mutex);
+	HASH_SEARCH(key_hash, wait_lock_sys->lock_ref_hash,
+			ut_fold_string(key),
+			lock_ref_table_t*, table,
+			NULL,
+			!strncmp(table->key, key, strlen(key)));
+
+	mutex_exit(&wait_lock_sys->mutex);
+
+
+	trx_mutex_exit(trx);
+
+	/* In case of entry is deleted by other threads */
+	if(table == NULL)
+		return FALSE;
+
+	if (srv_lock_wait_threshold == 0 ||  
+			(table &&
+			 table->ref_count < srv_lock_wait_threshold))
+		return FALSE;
+	else
+		return TRUE;
+}
+
+void 
+lock_wait_ref_release(
+/*=========*/
+		trx_t *trx)
+{
+	trx_mutex_enter(trx);
+
+	lock_ref_table_t* table;
+
+	if (trx->is_lock_wait == 1) {
+		trx->is_lock_wait = 0;
+
+		char key[512] = {0};
+		wait_lock_t* req_lock =  trx->lock.req_wait_lock;
+		snprintf(key, 512, "%ld%ld%ld",
+				req_lock->space, 
+				req_lock->page_no, 
+				req_lock->heap_no);
+
+		mutex_enter(&wait_lock_sys->mutex);
+
+		HASH_SEARCH(key_hash, wait_lock_sys->lock_ref_hash, 
+				ut_fold_string(key),
+				lock_ref_table_t*, table,
+				NULL,
+				!strncmp(table->key, key, strlen(key)));
+
+		ut_a(table);
+
+		table->ref_count--;
+
+		if (table->ref_count  ==  0) {
+
+			HASH_DELETE(lock_ref_table_t, key_hash, 
+					wait_lock_sys->lock_ref_hash,
+					ut_fold_string(key), table);
+
+			my_free(table->key);
+			my_free(table);
+		}
+
+		//fprintf(stderr, "delete %p (%s %ld\n", table, table->key, table->ref_count);
+
+		mutex_exit(&wait_lock_sys->mutex);
+	}
+	trx_mutex_exit(trx);
+}
+
+
 /* True if a lock mode is S or X */
 #define IS_LOCK_S_OR_X(lock) \
 	(lock_get_mode(lock) == LOCK_S \
Index: storage/innobase/ut/ut0ut.cc
===================================================================
--- storage/innobase/ut/ut0ut.cc	(revision 4442)
+++ storage/innobase/ut/ut0ut.cc	(working copy)
@@ -1,3 +1,4 @@
+
 /*****************************************************************************
 
 Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
@@ -720,6 +721,8 @@
 		return("Out of disk space");
 	case DB_LOCK_WAIT:
 		return("Lock wait");
+	case DB_LOCK_WAIT_THRESHOLD:
+		return ("Over lock wait threshold");
 	case DB_DEADLOCK:
 		return("Deadlock");
 	case DB_ROLLBACK:
Index: storage/innobase/srv/srv0conc.cc
===================================================================
--- storage/innobase/srv/srv0conc.cc	(revision 4442)
+++ storage/innobase/srv/srv0conc.cc	(working copy)
@@ -47,14 +47,14 @@
 SQL query after it has once got the ticket. */
 UNIV_INTERN ulong	srv_n_free_tickets_to_enter = 500;
 
-#ifdef HAVE_ATOMIC_BUILTINS
+#if defined(HAVE_ATOMIC_BUILTINS) && !defined USE_DEFAULT_CONC
 /** Maximum sleep delay (in micro-seconds), value of 0 disables it. */
 UNIV_INTERN ulong	srv_adaptive_max_sleep_delay = 150000;
 #endif /* HAVE_ATOMIC_BUILTINS */
 
 UNIV_INTERN ulong	srv_thread_sleep_delay	= 10000;
+UNIV_INTERN ulong	srv_conc_retry_loops    = 5;
 
-
 /** We are prepared for a situation that we have this many threads waiting for
 a semaphore inside InnoDB. innobase_start_or_create_for_mysql() sets the
 value. */
@@ -66,8 +66,12 @@
 we could get a deadlock. Value of 0 will disable the concurrency check. */
 
 UNIV_INTERN ulong	srv_thread_concurrency	= 0;
+UNIV_INTERN ulong	srv_wait_lock_latches	= MAX_WAIT_LOCK_LATCHES;
+UNIV_INTERN ulint	srv_lock_wait_retry	= 0;
+UNIV_INTERN ulint	srv_lock_wait_retry_force = 0;
+UNIV_INTERN ulong	srv_lock_wait_threshold	  = 0;
 
-#ifndef HAVE_ATOMIC_BUILTINS
+#if !defined(HAVE_ATOMIC_BUILTINS)  ||  defined(USE_DEFAULT_CONC)
 
 /** This mutex protects srv_conc data structures */
 static os_fast_mutex_t	srv_conc_mutex;
@@ -122,13 +126,15 @@
 /* Control variables for tracking concurrency. */
 static srv_conc_t	srv_conc;
 
+extern wait_lock_sys_t*  wait_lock_sys;
+
 /*********************************************************************//**
 Initialise the concurrency management data structures */
 void
 srv_conc_init(void)
 /*===============*/
 {
-#ifndef HAVE_ATOMIC_BUILTINS
+#if !defined(HAVE_ATOMIC_BUILTINS)  ||  defined(USE_DEFAULT_CONC)
 	ulint		i;
 
 	/* Init the server concurrency restriction data structures */
@@ -155,14 +161,14 @@
 srv_conc_free(void)
 /*===============*/
 {
-#ifndef HAVE_ATOMIC_BUILTINS
+#if !defined HAVE_ATOMIC_BUILTINS || defined USE_DEFAULT_CONC
 	os_fast_mutex_free(&srv_conc_mutex);
 	mem_free(srv_conc_slots);
 	srv_conc_slots = NULL;
 #endif /* !HAVE_ATOMIC_BUILTINS */
 }
 
-#ifdef HAVE_ATOMIC_BUILTINS
+#if defined HAVE_ATOMIC_BUILTINS && !defined USE_DEFAULT_CONC
 /*********************************************************************//**
 Note that a user thread is entering InnoDB. */
 static
@@ -312,10 +318,21 @@
 	os_fast_mutex_lock(&srv_conc_mutex);
 
 	ut_ad(srv_conc.n_active > 0);
+	
 	srv_conc.n_active--;
-	trx->declared_to_be_inside_innodb = FALSE;
-	trx->n_tickets_to_enter_innodb = 0;
 
+	if ( trx->fake_force_exit == 1) {
+		srv_conc.n_active++; 
+		trx->fake_force_exit = 0; 
+	}
+
+	if (trx->queue_rescheduled == 0) {
+		trx->declared_to_be_inside_innodb = FALSE;
+		trx->n_tickets_to_enter_innodb = 0;
+		
+	}
+
+
 	slot = NULL;
 
 	if (srv_conc.n_active < (lint) srv_thread_concurrency) {
@@ -360,6 +377,11 @@
 	ibool			has_slept = FALSE;
 
 	os_fast_mutex_lock(&srv_conc_mutex);
+
+	/* Reset current rescheduled thread to be outside of innodb */
+
+	if (trx->queue_rescheduled)
+		trx->declared_to_be_inside_innodb = FALSE;
 retry:
 	if (UNIV_UNLIKELY(trx->declared_to_be_inside_innodb)) {
 		os_fast_mutex_unlock(&srv_conc_mutex);
@@ -507,7 +529,7 @@
 	ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch));
 #endif /* UNIV_SYNC_DEBUG */
 
-#ifdef HAVE_ATOMIC_BUILTINS
+#if defined (HAVE_ATOMIC_BUILTINS) && !defined (USE_DEFAULT_CONC)
 	srv_conc_enter_innodb_with_atomics(trx);
 #else
 	srv_conc_enter_innodb_without_atomics(trx);
@@ -535,7 +557,7 @@
 
 	ut_ad(srv_conc.n_active >= 0);
 
-#ifdef HAVE_ATOMIC_BUILTINS
+#if defined HAVE_ATOMIC_BUILTINS && !defined USE_DEFAULT_CONC
 	(void) os_atomic_increment_lint(&srv_conc.n_active, 1);
 #else
 	os_fast_mutex_lock(&srv_conc_mutex);
@@ -543,7 +565,9 @@
 	os_fast_mutex_unlock(&srv_conc_mutex);
 #endif /* HAVE_ATOMIC_BUILTINS */
 
-	trx->n_tickets_to_enter_innodb = 1;
+	if (trx->queue_rescheduled == 0)
+		trx->n_tickets_to_enter_innodb = 1;
+
 	trx->declared_to_be_inside_innodb = TRUE;
 }
 
@@ -564,7 +588,7 @@
 		return;
 	}
 
-#ifdef HAVE_ATOMIC_BUILTINS
+#if defined HAVE_ATOMIC_BUILTINS && !defined USE_DEFAULT_CONC
 	srv_conc_exit_innodb_with_atomics(trx);
 #else
 	srv_conc_exit_innodb_without_atomics(trx);
@@ -575,6 +599,7 @@
 #endif /* UNIV_SYNC_DEBUG */
 }
 
+
 /*********************************************************************//**
 Get the count of threads waiting inside InnoDB. */
 UNIV_INTERN
Index: storage/innobase/handler/ha_innodb.cc
===================================================================
--- storage/innobase/handler/ha_innodb.cc	(revision 4442)
+++ storage/innobase/handler/ha_innodb.cc	(working copy)
@@ -153,6 +153,7 @@
 /* The default values for the following char* start-up parameters
 are determined in innobase_init below: */
 
+static int      n_item[MAX_WAIT_LOCK_LATCHES] = {0};
 static char*	innobase_data_home_dir			= NULL;
 static char*	innobase_data_file_path			= NULL;
 static char*	innobase_file_format_name		= NULL;
@@ -348,6 +349,7 @@
 	{&srv_sys_mutex_key, "srv_sys_mutex", 0},
 	{&lock_sys_mutex_key, "lock_mutex", 0},
 	{&lock_sys_wait_mutex_key, "lock_wait_mutex", 0},
+	{&wait_lock_sys_mutex_key, "wait_lock_mutex", 0},
 	{&trx_mutex_key, "trx_mutex", 0},
 	{&srv_sys_tasks_mutex_key, "srv_threads_mutex", 0},
 	/* mutex with os_fast_mutex_ interfaces */
@@ -1353,6 +1355,8 @@
 {
 	switch (error) {
 	case DB_SUCCESS:
+		/* fall through */
+	case DB_LOCK_WAIT_THRESHOLD:
 		return(0);
 
 	case DB_INTERRUPTED:
@@ -7596,7 +7600,6 @@
 overwrap, we use this test only as a secondary way of determining the
 start of a new SQL statement. */
 
-
 /**********************************************************************//**
 Positions an index cursor to the index specified in the handle. Fetches the
 row if any.
@@ -7691,14 +7694,138 @@
 
 	last_match_mode = (uint) match_mode;
 
+	ulint n_switch = 0;
+	ret = DB_SUCCESS;
+
+	trx_t *trx = prebuilt->trx;
+	prebuilt->trx->queue_rescheduled = 0;
+
 	if (mode != PAGE_CUR_UNSUPP) {
 
+		trx->lock.ignore_wait_lock = 0;
+
+		trx->holds_exec_lock = 0;
+
 		innobase_srv_conc_enter_innodb(prebuilt->trx);
 
 		ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
-					   match_mode, 0);
+				match_mode, 0);
 
-		innobase_srv_conc_exit_innodb(prebuilt->trx);
+		int lock_fold = -1;
+		int n_waiting = 0;
+
+		if (ret == DB_LOCK_WAIT_THRESHOLD) {
+
+			lock_fold = trx->lock.req_wait_lock->rec_hv % MAX_WAIT_LOCK_LATCHES;
+
+			ut_a(lock_fold >= 0 && lock_fold < MAX_WAIT_LOCK_LATCHES);
+
+
+			rw_lock_x_lock(wait_lock_sys->wait_lock_latch[lock_fold]);
+
+			/* Must Set after the exit/force_exit logics */	
+			trx->queue_rescheduled = 1;
+
+			trx->is_queue_head = 0;
+
+			n_waiting = n_item[lock_fold]++;
+			if (n_waiting == 0)  {
+			
+				trx->is_queue_head = 1;
+				innobase_srv_conc_exit_innodb(prebuilt->trx);
+			}
+			else {
+				innobase_srv_conc_force_exit_innodb(trx);
+				trx->fake_force_exit = 1;
+			}
+			
+			rw_lock_x_unlock(wait_lock_sys->wait_lock_latch[lock_fold]); 
+
+		} else {
+
+			innobase_srv_conc_exit_innodb(prebuilt->trx);
+
+		} //end of if (ret==DB_LOCK_WAIT_THRESHOLD)
+
+
+		if (lock_fold != -1) {
+			
+			pthread_mutex_lock(wait_lock_sys->exec_lock_mutexes+lock_fold);
+			trx->holds_exec_lock = 1;
+		} 
+
+		/* Avoid the case: current thread is scheduled to FIFO as
+		   tickets are used out, but holding the exec lock, caused 
+		   hanging in scheluding */
+
+		if (trx->n_tickets_to_enter_innodb < srv_conc_retry_loops)
+			trx->n_tickets_to_enter_innodb = srv_conc_retry_loops + 2;
+
+		while (ret == DB_LOCK_WAIT_THRESHOLD) {
+
+			/* In the case of deadlock caused by the scheduling, let
+			 the thread foce enter and just like the behavior as it
+			 should be without rescheduling */
+
+			if (n_switch++ >= srv_conc_retry_loops)
+				trx->lock.ignore_wait_lock = 1;
+
+			if (lock_wait_over_threshold(trx) &&
+					trx->lock.ignore_wait_lock != 1) {
+
+				os_event_wait_time(wait_lock_sys->exec_lock_events[lock_fold],
+						10001000); 
+
+				os_event_reset(wait_lock_sys->exec_lock_events[lock_fold]);
+
+				continue;
+			}
+
+			innobase_srv_conc_enter_innodb(prebuilt->trx);
+
+			ret = row_search_for_mysql((byte*) buf, mode, prebuilt,
+					match_mode, 0);
+			innobase_srv_conc_exit_innodb(prebuilt->trx);
+
+
+		} //end of while (ret == DB_LOCK_WAIT_THRESHOLD)
+
+		if (lock_fold != -1) {
+			if (trx->holds_exec_lock == 1) {
+				pthread_mutex_unlock(wait_lock_sys->exec_lock_mutexes+lock_fold);
+			}
+		
+		}
+
+
+		if (trx->queue_rescheduled) {
+
+			ut_a(lock_fold >= 0 && lock_fold < MAX_WAIT_LOCK_LATCHES);
+
+			rw_lock_x_lock(wait_lock_sys->wait_lock_latch[lock_fold]);
+			n_item[lock_fold]--;
+			rw_lock_x_unlock(wait_lock_sys->wait_lock_latch[lock_fold]);
+
+			//fprintf(stderr, " <--- switched %ld ---->\n", n_switch);
+
+			os_event_set(wait_lock_sys->exec_lock_events[lock_fold]); 
+
+
+		}
+
+
+		{
+			lock_wait_ref_release(trx);
+
+			prebuilt->trx->queue_rescheduled = 0;
+
+			n_switch = 0;
+		}
+
+		ut_a(trx->is_lock_wait==0);
+
+
+
 	} else {
 
 		ret = DB_UNSUPPORTED;
@@ -16178,7 +16305,7 @@
   "Helps in performance tuning in heavily concurrent environments. Sets the maximum number of threads allowed inside InnoDB. Value 0 will disable the thread throttling.",
   NULL, NULL, 0, 0, 1000, 0);
 
-#ifdef HAVE_ATOMIC_BUILTINS
+#if defined HAVE_ATOMIC_BUILTINS && !defined USE_DEFAULT_CONC
 static MYSQL_SYSVAR_ULONG(
   adaptive_max_sleep_delay, srv_adaptive_max_sleep_delay,
   PLUGIN_VAR_RQCMDARG,
@@ -16410,6 +16537,12 @@
   NULL, NULL, FALSE);
 #endif /* UNIV_DEBUG */
 
+static MYSQL_SYSVAR_ULONG(lock_wait_threshold, srv_lock_wait_threshold,
+  PLUGIN_VAR_RQCMDARG,
+  "Hot key access control for the enter/exit innodb when the waiting locks"
+  "to the same page is over the threshold. 0 to disable this feature.",
+  NULL, NULL, 12, 0, 256, 0);
+
 static struct st_mysql_sys_var* innobase_system_variables[]= {
   MYSQL_SYSVAR(additional_mem_pool_size),
   MYSQL_SYSVAR(api_trx_level),
@@ -16463,6 +16596,7 @@
   MYSQL_SYSVAR(force_load_corrupted),
   MYSQL_SYSVAR(locks_unsafe_for_binlog),
   MYSQL_SYSVAR(lock_wait_timeout),
+  MYSQL_SYSVAR(lock_wait_threshold),
 #ifdef UNIV_LOG_ARCHIVE
   MYSQL_SYSVAR(log_arch_dir),
   MYSQL_SYSVAR(log_archive),
@@ -16508,7 +16642,7 @@
   MYSQL_SYSVAR(spin_wait_delay),
   MYSQL_SYSVAR(table_locks),
   MYSQL_SYSVAR(thread_concurrency),
-#ifdef HAVE_ATOMIC_BUILTINS
+#if defined HAVE_ATOMIC_BUILTINS && !defined USE_DEFAULT_CONC
   MYSQL_SYSVAR(adaptive_max_sleep_delay),
 #endif /* HAVE_ATOMIC_BUILTINS */
   MYSQL_SYSVAR(thread_sleep_delay),
Index: storage/innobase/trx/trx0trx.cc
===================================================================
--- storage/innobase/trx/trx0trx.cc	(revision 4442)
+++ storage/innobase/trx/trx0trx.cc	(working copy)
@@ -102,6 +102,7 @@
 	mutex_create(trx_mutex_key, &trx->mutex, SYNC_TRX);
 
 	trx->magic_n = TRX_MAGIC_N;
+	trx->is_lock_wait = 0;
 
 	trx->state = TRX_STATE_NOT_STARTED;
 
@@ -147,6 +148,9 @@
 	trx->lock.table_locks = ib_vector_create(
 		heap_alloc, sizeof(void**), 32);
 
+	trx->lock.req_wait_lock = (wait_lock_t*)mem_zalloc(
+			sizeof(wait_lock_t));
+
 	return(trx);
 }
 
@@ -236,6 +240,9 @@
 
 	mutex_free(&trx->mutex);
 
+	mem_free(trx->lock.req_wait_lock);
+	trx->lock.req_wait_lock = NULL;
+
 	mem_free(trx);
 }
 
Index: storage/innobase/include/lock0lock.h
===================================================================
--- storage/innobase/include/lock0lock.h	(revision 4442)
+++ storage/innobase/include/lock0lock.h	(working copy)
@@ -801,6 +801,21 @@
 /*===================*/
 	const dict_table_t*	table)	/*!< in: table */
 	__attribute__((nonnull));
+
+/*********************************************************************//**
+Release the lock wait reference for current trx.
+@return void */
+void lock_wait_ref_release(
+/*=====================*/
+		trx_t *trx);
+
+/*********************************************************************//**
+Check lock wait is over the threshold for current lock required by trx
+@return TRUE is over threshold */
+bool lock_wait_over_threshold(
+/*=====================*/
+		trx_t *trx);
+
 #ifdef UNIV_DEBUG
 /*********************************************************************//**
 Checks that a transaction id is sensible, i.e., not in the future.
@@ -924,11 +939,23 @@
 
 	bool		timeout_thread_active;	/*!< True if the timeout thread
 						is running */
+        hash_table_t*	rec_wait_hash;		/*!< hash table of the record
+						locks in waiting status */
+
 };
 
+struct wait_lock_struct {
+	ulint space;	/*!< stored space number */
+	ulint page_no;	/*!< stored page_no */
+	ulint heap_no;  /*!< saved heap_no  */
+	ulint rec_hv;   /*!< Calculated record hash value */
+};
+
 /** The lock system */
 extern lock_sys_t*	lock_sys;
 
+extern wait_lock_sys_t* wait_lock_sys;
+
 /** Test if lock_sys->mutex can be acquired without waiting. */
 #define lock_mutex_enter_nowait() mutex_enter_nowait(&lock_sys->mutex)
 
@@ -962,4 +989,32 @@
 #include "lock0lock.ic"
 #endif
 
+/* Use for control the lock waiting threads rescheduling */
+struct wait_lock_sys_struct{
+        ib_mutex_t      mutex;         /*!< Mutex protecting the
+                                        locks */
+        rw_lock_t** wait_lock_latch;   /*!< rwlock protecting the waiting
+                                         threads in scheduled queue */
+	pthread_mutex_t *exec_lock_mutexes;   /*!< mutex protecting the executing
+					      threads in scheduled queue.
+					      Why we don't use rwlock is due to the 
+					      spin lock wait with ut_delay */
+
+	os_event_t*	  exec_lock_events; /*!< os_event to wait/siganl the thread
+					      holds the exec_mutex */
+
+        hash_table_t* lock_ref_hash;   /*!< hash table stating the lock ref
+                                         when it waits for some lock */
+};
+
+/* Hash table for lock reference stating */
+struct lock_ref_table_struct {
+        char          *key;           /*!< Hash key for that record */
+        ulint         ref_count;      /*!< Reference value in lock waiting */
+        hash_node_t   key_hash;       /*!< hash chain node */
+};
+
+typedef struct lock_ref_table_struct lock_ref_table_t;
+
+
 #endif
Index: storage/innobase/include/srv0srv.h
===================================================================
--- storage/innobase/include/srv0srv.h	(revision 4442)
+++ storage/innobase/include/srv0srv.h	(working copy)
@@ -192,7 +192,7 @@
 extern my_bool	srv_file_per_table;
 /** Sleep delay for threads waiting to enter InnoDB. In micro-seconds. */
 extern	ulong	srv_thread_sleep_delay;
-#if defined(HAVE_ATOMIC_BUILTINS)
+#if defined(HAVE_ATOMIC_BUILTINS) && !defined USE_DEFAULT_CONC
 /** Maximum sleep delay (in micro-seconds), value of 0 disables it.*/
 extern	ulong	srv_adaptive_max_sleep_delay;
 #endif /* HAVE_ATOMIC_BUILTINS */
@@ -417,7 +417,7 @@
 #define SRV_SEMAPHORE_WAIT_EXTENSION	7200
 extern ulint	srv_dml_needed_delay;
 
-#ifndef HAVE_ATOMIC_BUILTINS
+#if !defined HAVE_ATOMIC_BUILTINS || defined USE_DEFAULT_CONC
 /** Mutex protecting some server global variables. */
 extern ib_mutex_t	server_mutex;
 #endif /* !HAVE_ATOMIC_BUILTINS */
Index: storage/innobase/include/buf0buf.h
===================================================================
--- storage/innobase/include/buf0buf.h	(revision 4442)
+++ storage/innobase/include/buf0buf.h	(working copy)
@@ -1619,6 +1619,7 @@
 					contention on the buffer pool mutex */
 	rw_lock_t	lock;		/*!< read-write lock of the buffer
 					frame */
+	ulint		n_ref_count;	 /* waiting locks on the block */
 	unsigned	lock_hash_val:32;/*!< hashed value of the page address
 					in the record lock hash table;
 					protected by buf_block_t::lock
Index: storage/innobase/include/lock0types.h
===================================================================
--- storage/innobase/include/lock0types.h	(revision 4442)
+++ storage/innobase/include/lock0types.h	(working copy)
@@ -30,6 +30,9 @@
 struct lock_t;
 struct lock_sys_t;
 
+typedef struct wait_lock_struct	      wait_lock_t;
+typedef struct wait_lock_sys_struct   wait_lock_sys_t;
+
 /* Basic lock modes */
 enum lock_mode {
 	LOCK_IS = 0,	/* intention shared */
Index: storage/innobase/include/lock0priv.h
===================================================================
--- storage/innobase/include/lock0priv.h	(revision 4442)
+++ storage/innobase/include/lock0priv.h	(working copy)
@@ -76,6 +76,9 @@
 		lock_table_t	tab_lock;/*!< table lock */
 		lock_rec_t	rec_lock;/*!< record lock */
 	} un_member;			/*!< lock details */
+	buf_block_t*  block;		/*!< ref buf block for the lock */
+	bool          is_waiting;	/*!< waiter threads number */
+	int magic_num;
 };
 
 /*********************************************************************//**
Index: storage/innobase/include/db0err.h
===================================================================
--- storage/innobase/include/db0err.h	(revision 4442)
+++ storage/innobase/include/db0err.h	(working copy)
@@ -38,6 +38,7 @@
 	DB_OUT_OF_MEMORY,
 	DB_OUT_OF_FILE_SPACE,
 	DB_LOCK_WAIT,
+	DB_LOCK_WAIT_THRESHOLD,
 	DB_DEADLOCK,
 	DB_ROLLBACK,
 	DB_DUPLICATE_KEY,
Index: storage/innobase/include/srv0conc.h
===================================================================
--- storage/innobase/include/srv0conc.h	(revision 4442)
+++ storage/innobase/include/srv0conc.h	(working copy)
@@ -52,6 +52,13 @@
 
 extern ulong	srv_thread_concurrency;
 
+extern ulong	srv_wait_lock_latches;
+extern ulint 	srv_lock_wait_retry;
+extern ulint 	srv_lock_wait_retry_force;
+ 
+extern ulong   srv_lock_wait_threshold;
+extern ulong   srv_conc_retry_loops;
+
 /*********************************************************************//**
 Initialise the concurrency management data structures */
 void
Index: storage/innobase/include/trx0trx.h
===================================================================
--- storage/innobase/include/trx0trx.h	(revision 4442)
+++ storage/innobase/include/trx0trx.h	(working copy)
@@ -560,6 +560,11 @@
 					== TRX_STATE_ACTIVE: TRX_QUE_RUNNING,
 					TRX_QUE_LOCK_WAIT, ... */
 
+	wait_lock_t*  req_wait_lock;	/*!< requestd failed lock that needs
+					  waiting for */
+	ibool         ignore_wait_lock;	/*!< ignore the wait lock controlling
+					  and rescheduling */
+
 	lock_t*		wait_lock;	/*!< if trx execution state is
 					TRX_QUE_LOCK_WAIT, this points to
 					the lock request, otherwise this is
@@ -990,6 +995,15 @@
 	/*------------------------------*/
 	char detailed_error[256];	/*!< detailed error message for last
 					error, or empty. */
+
+        bool    queue_rescheduled; /*!< TRUE if current trx is rescheduled into 
+				      the lock waiting queue */
+        int     is_lock_wait; /*!< TRUE is current trx registed the lock info, and it
+				 must unregist later */
+        bool    holds_exec_lock; /*!< TRUE if it holds the exec_lock */
+	bool	is_queue_head;	/*!< TRUE it is the head of that queue */
+	bool	fake_force_exit;  /*!< TRUE if it's the non-head of that 
+				    scheduled queue */
 };
 
 /* Transaction isolation levels (trx->isolation_level) */
Index: storage/innobase/include/sync0sync.h
===================================================================
--- storage/innobase/include/sync0sync.h	(revision 4442)
+++ storage/innobase/include/sync0sync.h	(working copy)
@@ -116,6 +116,7 @@
 extern mysql_pfs_key_t	trx_mutex_key;
 extern mysql_pfs_key_t	lock_sys_mutex_key;
 extern mysql_pfs_key_t	lock_sys_wait_mutex_key;
+extern mysql_pfs_key_t	wait_lock_sys_mutex_key;
 extern mysql_pfs_key_t	trx_sys_mutex_key;
 extern mysql_pfs_key_t	srv_sys_mutex_key;
 extern mysql_pfs_key_t	srv_sys_tasks_mutex_key;
@@ -729,6 +730,10 @@
 #define	SYNC_MEM_HASH		131
 #define	SYNC_MEM_POOL		130
 
+#define SYNC_WAIT_LOCK_LATCH	120
+#define SYNC_EXEC_LOCK_LATCH	119
+
+
 /* Codes used to designate lock operations */
 #define RW_LOCK_NOT_LOCKED	350
 #define RW_LOCK_EX		351
@@ -737,6 +742,8 @@
 #define RW_LOCK_WAIT_EX		353
 #define SYNC_MUTEX		354
 
+#define MAX_WAIT_LOCK_LATCHES 1024
+
 /* 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 mutual exclusion semaphore. */
Index: storage/innobase/row/row0sel.cc
===================================================================
--- storage/innobase/row/row0sel.cc	(revision 4442)
+++ storage/innobase/row/row0sel.cc	(working copy)
@@ -4471,6 +4471,9 @@
 			err = DB_SUCCESS;
 		case DB_SUCCESS:
 			break;
+		case DB_LOCK_WAIT_THRESHOLD:
+			btr_pcur_store_position(pcur, &mtr);
+			goto normal_return;
 		case DB_LOCK_WAIT:
 			/* Never unlock rows that were part of a conflict. */
 			prebuilt->new_rec_locks = 0;
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 4442)
+++ CMakeLists.txt	(working copy)
@@ -157,7 +157,12 @@
 IF(DISABLE_SHARED)
   SET(WITHOUT_DYNAMIC_PLUGINS 1)
 ENDIF()
+OPTION(USE_DEFAULT_CONC "use default conc" ON)
 OPTION(ENABLED_PROFILING "Enable profiling" ON)
+        IF(USE_DEFAULT_CONC)
+        ADD_DEFINITIONS(-DUSE_DEFAULT_CONC)
+ENDIF()
+
 OPTION(CYBOZU "" OFF)
 OPTION(BACKUP_TEST "" OFF)
 OPTION(WITHOUT_SERVER OFF)
