projects
/
fio.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
workqueue: Fix race conditions in the workqueue mechanism
[fio.git]
/
workqueue.c
diff --git
a/workqueue.c
b/workqueue.c
index 254bf6b6505fd8e047021fc819b99e567d5722e4..9e6c41ff2f399172703b6e438061236670962df8 100644
(file)
--- a/
workqueue.c
+++ b/
workqueue.c
@@
-170,26
+170,32
@@
static void *worker_thread(void *data)
workqueue_pre_sleep(sw);
pthread_mutex_lock(&sw->lock);
}
workqueue_pre_sleep(sw);
pthread_mutex_lock(&sw->lock);
}
-
- /*
- * We dropped and reaquired the lock, check
- * state again.
- */
- if (!flist_empty(&sw->work_list))
- goto handle_work;
-
+ }
+ /*
+ * We may have dropped and reaquired the lock, check state
+ * again.
+ */
+ if (flist_empty(&sw->work_list)) {
if (sw->flags & SW_F_EXIT) {
break;
if (sw->flags & SW_F_EXIT) {
break;
- } else if (!(sw->flags & SW_F_IDLE)) {
+ }
+ if (!(sw->flags & SW_F_IDLE)) {
sw->flags |= SW_F_IDLE;
wq->next_free_worker = sw->index;
sw->flags |= SW_F_IDLE;
wq->next_free_worker = sw->index;
+ pthread_mutex_unlock(&sw->lock);
+ pthread_mutex_lock(&wq->flush_lock);
if (wq->wake_idle)
pthread_cond_signal(&wq->flush_cond);
if (wq->wake_idle)
pthread_cond_signal(&wq->flush_cond);
+ pthread_mutex_unlock(&wq->flush_lock);
+ pthread_mutex_lock(&sw->lock);
+ }
+ }
+ if (flist_empty(&sw->work_list)) {
+ if (sw->flags & SW_F_EXIT) {
+ break;
}
}
-
pthread_cond_wait(&sw->cond, &sw->lock);
} else {
pthread_cond_wait(&sw->cond, &sw->lock);
} else {
-handle_work:
flist_splice_init(&sw->work_list, &local_list);
}
pthread_mutex_unlock(&sw->lock);
flist_splice_init(&sw->work_list, &local_list);
}
pthread_mutex_unlock(&sw->lock);