svn commit: r283551 - head/sys/kern
Xin LI
delphij at FreeBSD.org
Tue May 26 01:40:34 UTC 2015
Author: delphij
Date: Tue May 26 01:40:33 2015
New Revision: 283551
URL: https://svnweb.freebsd.org/changeset/base/283551
Log:
MFuser/delphij/zfs-arc-rebase at r281754:
In r256613, taskqueue_enqueue_locked() have been modified to release the
task queue lock before returning. In r276665, taskqueue_drain_all() will
call taskqueue_enqueue_locked() to insert the barrier task into the queue,
but did not reacquire the lock after it but later code expects the lock
still being held (e.g. TQ_SLEEP()).
The barrier task is special and if we release then reacquire the lock,
there would be a small race window where a high priority task could sneak
into the queue. Looking more closely, the race seems to be tolerable but
is undesirable from semantics standpoint.
To solve this, in taskqueue_drain_tq_queue(), instead of directly calling
taskqueue_enqueue_locked(), insert the barrier task directly without
releasing the lock.
Modified:
head/sys/kern/subr_taskqueue.c
Directory Properties:
head/ (props changed)
head/sys/ (props changed)
Modified: head/sys/kern/subr_taskqueue.c
==============================================================================
--- head/sys/kern/subr_taskqueue.c Tue May 26 01:30:09 2015 (r283550)
+++ head/sys/kern/subr_taskqueue.c Tue May 26 01:40:33 2015 (r283551)
@@ -323,17 +323,16 @@ taskqueue_drain_tq_queue(struct taskqueu
return;
/*
- * Enqueue our barrier with the lowest possible priority
- * so we are inserted after all current tasks.
+ * Enqueue our barrier after all current tasks, but with
+ * the highest priority so that newly queued tasks cannot
+ * pass it. Because of the high priority, we can not use
+ * taskqueue_enqueue_locked directly (which drops the lock
+ * anyway) so just insert it at tail while we have the
+ * queue lock.
*/
- TASK_INIT(&t_barrier, 0, taskqueue_task_nop_fn, &t_barrier);
- taskqueue_enqueue_locked(queue, &t_barrier);
-
- /*
- * Raise the barrier's priority so newly queued tasks cannot
- * pass it.
- */
- t_barrier.ta_priority = USHRT_MAX;
+ TASK_INIT(&t_barrier, USHRT_MAX, taskqueue_task_nop_fn, &t_barrier);
+ STAILQ_INSERT_TAIL(&queue->tq_queue, &t_barrier, ta_link);
+ t_barrier.ta_pending = 1;
/*
* Once the barrier has executed, all previously queued tasks
More information about the svn-src-head
mailing list