summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrishnan Parthasarathi <kparthas@redhat.com>2013-05-11 14:36:38 +0530
committerVijay Bellur <vbellur@redhat.com>2013-05-15 22:21:41 -0700
commit4c0b149d8e7c574186a1ccefd9c74b79f8a06267 (patch)
treec4b764cda3e67a08d48e4ecd2d5ea0e766db889d
parent845aeb709e0e7e037a5b5afc7bc084d58e7e97ee (diff)
syncop: Remove task from synclock's waitq before 'wake'
Removing task from synclock's waitq after wake could result in a subsequent unlock, wake'ing up the already running task. This fix makes the removal from waitq and wake 'atomic'. Change-Id: Ie51ccf9d38f2cee84471097644aab95496f488b1 BUG: 948686 Signed-off-by: Krishnan Parthasarathi <kparthas@redhat.com> Reviewed-on: http://review.gluster.org/4987 Reviewed-by: Jeff Darcy <jdarcy@redhat.com> Tested-by: Gluster Build System <jenkins@build.gluster.com>
-rw-r--r--libglusterfs/src/syncop.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/libglusterfs/src/syncop.c b/libglusterfs/src/syncop.c
index 7dcdf3fefcb..98aee98dd85 100644
--- a/libglusterfs/src/syncop.c
+++ b/libglusterfs/src/syncop.c
@@ -529,12 +529,11 @@ __synclock_lock (struct synclock *lock)
if (task) {
/* called within a synctask */
list_add_tail (&task->waitq, &lock->waitq);
- {
- pthread_mutex_unlock (&lock->guard);
- synctask_yield (task);
- pthread_mutex_lock (&lock->guard);
- }
- list_del_init (&task->waitq);
+ pthread_mutex_unlock (&lock->guard);
+ synctask_yield (task);
+ /* task is removed from waitq in unlock,
+ * under lock->guard.*/
+ pthread_mutex_lock (&lock->guard);
} else {
/* called by a non-synctask */
pthread_cond_wait (&lock->cond, &lock->guard);
@@ -616,6 +615,7 @@ __synclock_unlock (synclock_t *lock)
pthread_cond_signal (&lock->cond);
if (!list_empty (&lock->waitq)) {
task = list_entry (lock->waitq.next, struct synctask, waitq);
+ list_del_init (&task->waitq);
synctask_wake (task);
}