summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/syncop.c
diff options
context:
space:
mode:
authorKrishnan Parthasarathi <kparthas@redhat.com>2013-05-20 17:17:05 +0530
committerAnand Avati <avati@redhat.com>2013-05-20 21:08:24 -0700
commit277fabf577f95b20c61d65b28f8269e6abca6fee (patch)
tree5a4ec5e13864573c677a1a983923a5c9a8613615 /libglusterfs/src/syncop.c
parent27b457fad288cc896db3151bf3bc71cce72f5499 (diff)
syncop: Remove task from syncbarrier's waitq before 'wake'
Removing task from syncbarrier's waitq after wake could result in a subsequent syncbarrier_wake, wake'ing up the already running task. This fix makes the removal from waitq and wake 'atomic' The root cause and the fix are similar in spirit to what was observed in synclock's waitq implementation. Change-Id: I7dd9e6ad5945742bcda20eb5a06a9376bb18528e BUG: 948686 Signed-off-by: Krishnan Parthasarathi <kparthas@redhat.com> Reviewed-on: http://review.gluster.org/5047 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Anand Avati <avati@redhat.com>
Diffstat (limited to 'libglusterfs/src/syncop.c')
-rw-r--r--libglusterfs/src/syncop.c12
1 files changed, 5 insertions, 7 deletions
diff --git a/libglusterfs/src/syncop.c b/libglusterfs/src/syncop.c
index 275180575c4..ef9acfc6d83 100644
--- a/libglusterfs/src/syncop.c
+++ b/libglusterfs/src/syncop.c
@@ -688,13 +688,10 @@ __syncbarrier_wait (struct syncbarrier *barrier, int waitfor)
if (task) {
/* called within a synctask */
list_add_tail (&task->waitq, &barrier->waitq);
- {
- pthread_mutex_unlock (&barrier->guard);
- synctask_yawn (task);
- synctask_yield (task);
- pthread_mutex_lock (&barrier->guard);
- }
- list_del_init (&task->waitq);
+ pthread_mutex_unlock (&barrier->guard);
+ synctask_yawn (task);
+ synctask_yield (task);
+ pthread_mutex_lock (&barrier->guard);
} else {
/* called by a non-synctask */
pthread_cond_wait (&barrier->cond, &barrier->guard);
@@ -737,6 +734,7 @@ __syncbarrier_wake (struct syncbarrier *barrier)
pthread_cond_signal (&barrier->cond);
if (!list_empty (&barrier->waitq)) {
task = list_entry (barrier->waitq.next, struct synctask, waitq);
+ list_del_init (&task->waitq);
synctask_wake (task);
}