List:Commits« Previous MessageNext Message »
From:dlenev Date:August 5 2007 11:17am
Subject:bk commit into 5.0 tree (dlenev:1.2489) BUG#21281
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of dlenev. When dlenev does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-08-05 13:17:07+04:00, dlenev@stripped +1 -0
  Fix for bug #21281 "Pending write lock is incorrectly removed when its
  statement being KILLed".
  
  When statement which was trying to obtain write lock on then table and
  which was blocked by existing read lock was killed, concurrent statements
  that were trying to obtain read locks on the same table and that were
  blocked by the presence of this pending write lock were not woken up and
  had to wait until this first read lock goes away.
  
  This problem was caused by the fact that we forgot to wake up threads
  which pending requests could have been satisfied after removing lock
  request for the killed thread.
  
  The patch solves the problem by waking up those threads in such situation.
  
  Test for this bug will be added to 5.1 only as it has much better
  facilities for its implementation. Particularly, by using I_S.PROCESSLIST
  and wait_condition.inc script we can wait until thread will be blocked on
  certain table lock without relying on unconditional sleep (which usage
  increases time needed for test runs and might cause spurious test
  failures on slower platforms).

  mysys/thr_lock.c@stripped, 2007-08-05 13:16:59+04:00, dlenev@stripped +32 -8
    After removing lock request from the list of waiting lock requests
    (e.g. when we discover that current thread was killed) we should
    wake up other threads waiting for the same lock which pending
    requests now can be satisfied. To implement this behavior we
    move code responsible for waking up threads which pending requests
    can be satisfied from thr_unlock() to new wake_up_waiters() procedure
    and use it in wait_for_lock() and hr_abort_locks_for_thread().

diff -Nrup a/mysys/thr_lock.c b/mysys/thr_lock.c
--- a/mysys/thr_lock.c	2007-03-28 21:46:37 +04:00
+++ b/mysys/thr_lock.c	2007-08-05 13:16:59 +04:00
@@ -383,6 +383,9 @@ static inline my_bool have_specific_lock
 }
 
 
+static void wake_up_waiters(THR_LOCK *lock);
+
+
 static enum enum_thr_lock_result
 wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
               my_bool in_wait_list)
@@ -444,8 +447,13 @@ wait_for_lock(struct st_lock_list *wait,
       else
 	wait->last=data->prev;
       data->type= TL_UNLOCK;                    /* No lock */
+      check_locks(data->lock, "killed or timed out wait_for_lock", 1);
+      wake_up_waiters(data->lock);
+    }
+    else
+    {
+      check_locks(data->lock, "aborted wait_for_lock", 0);
     }
-    check_locks(data->lock,"failed wait_for_lock",0);
   }
   else
   {
@@ -771,6 +779,26 @@ void thr_unlock(THR_LOCK_DATA *data)
     lock->read_no_write_count--;
   data->type=TL_UNLOCK;				/* Mark unlocked */
   check_locks(lock,"after releasing lock",1);
+  wake_up_waiters(lock);
+  pthread_mutex_unlock(&lock->mutex);
+  DBUG_VOID_RETURN;
+}
+
+
+/**
+  @brief  Wake up all threads which pending requests for the lock
+          can be satisfied.
+
+  @param  lock  Lock for which threads should be woken up
+
+*/
+
+static void wake_up_waiters(THR_LOCK *lock)
+{
+  THR_LOCK_DATA *data;
+  enum thr_lock_type lock_type;
+
+  DBUG_ENTER("wake_up_waiters");
 
   if (!lock->write.data)			/* If no active write locks */
   {
@@ -820,11 +848,7 @@ void thr_unlock(THR_LOCK_DATA *data)
 	  data=lock->write_wait.data;		/* Free this too */
 	}
 	if (data->type >= TL_WRITE_LOW_PRIORITY)
-	{
-	  check_locks(lock,"giving write lock",0);
-	  pthread_mutex_unlock(&lock->mutex);
-	  DBUG_VOID_RETURN;
-	}
+          goto end;
 	/* Release possible read locks together with the write lock */
       }
       if (lock->read_wait.data)
@@ -879,8 +903,7 @@ void thr_unlock(THR_LOCK_DATA *data)
       free_all_read_locks(lock,0);
   }
 end:
-  check_locks(lock,"thr_unlock",0);
-  pthread_mutex_unlock(&lock->mutex);
+  check_locks(lock, "after waking up waiters", 0);
   DBUG_VOID_RETURN;
 }
 
@@ -1094,6 +1117,7 @@ my_bool thr_abort_locks_for_thread(THR_L
 	lock->write_wait.last= data->prev;
     }
   }
+  wake_up_waiters(lock);
   pthread_mutex_unlock(&lock->mutex);
   DBUG_RETURN(found);
 }
Thread
bk commit into 5.0 tree (dlenev:1.2489) BUG#21281dlenev5 Aug