Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 28 May 2010 18:15:28 +0000 (UTC)
From:      Zachary Loafman <zml@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r208623 - in head/sys: kern sys
Message-ID:  <201005281815.o4SIFSWr070281@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: zml
Date: Fri May 28 18:15:28 2010
New Revision: 208623
URL: http://svn.freebsd.org/changeset/base/208623

Log:
  Revert r207439 and solve the problem differently. The task handler
  ta_func may free the task structure, so no references to its members
  are valid after the handler has been called. Using a per-queue member
  and having waits longer than strictly necessary was suggested by jhb.
  
  Submitted by:       Matthew Fleming <matthew.fleming@isilon.com>
  Reviewed by:        zml, jhb

Modified:
  head/sys/kern/subr_taskqueue.c
  head/sys/sys/_task.h
  head/sys/sys/taskqueue.h

Modified: head/sys/kern/subr_taskqueue.c
==============================================================================
--- head/sys/kern/subr_taskqueue.c	Fri May 28 17:50:35 2010	(r208622)
+++ head/sys/kern/subr_taskqueue.c	Fri May 28 18:15:28 2010	(r208623)
@@ -56,6 +56,7 @@ struct taskqueue {
 	int			tq_tcount;
 	int			tq_spin;
 	int			tq_flags;
+	int			tq_tasks_running;
 };
 
 #define	TQ_FLAGS_ACTIVE		(1 << 0)
@@ -232,13 +233,13 @@ taskqueue_run(struct taskqueue *queue)
 		STAILQ_REMOVE_HEAD(&queue->tq_queue, ta_link);
 		pending = task->ta_pending;
 		task->ta_pending = 0;
-		task->ta_flags |= TA_FLAGS_RUNNING;
+		queue->tq_tasks_running++;
 		TQ_UNLOCK(queue);
 
 		task->ta_func(task->ta_context, pending);
 
 		TQ_LOCK(queue);
-		task->ta_flags &= ~TA_FLAGS_RUNNING;
+		queue->tq_tasks_running--;
 		wakeup(task);
 	}
 
@@ -255,16 +256,14 @@ taskqueue_drain(struct taskqueue *queue,
 {
 	if (queue->tq_spin) {		/* XXX */
 		mtx_lock_spin(&queue->tq_mutex);
-		while (task->ta_pending != 0 ||
-		    (task->ta_flags & TA_FLAGS_RUNNING) != 0)
+		while (task->ta_pending != 0 || queue->tq_tasks_running > 0)
 			msleep_spin(task, &queue->tq_mutex, "-", 0);
 		mtx_unlock_spin(&queue->tq_mutex);
 	} else {
 		WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, __func__);
 
 		mtx_lock(&queue->tq_mutex);
-		while (task->ta_pending != 0 ||
-		    (task->ta_flags & TA_FLAGS_RUNNING) != 0)
+		while (task->ta_pending != 0 || queue->tq_tasks_running > 0)
 			msleep(task, &queue->tq_mutex, PWAIT, "-", 0);
 		mtx_unlock(&queue->tq_mutex);
 	}

Modified: head/sys/sys/_task.h
==============================================================================
--- head/sys/sys/_task.h	Fri May 28 17:50:35 2010	(r208622)
+++ head/sys/sys/_task.h	Fri May 28 18:15:28 2010	(r208623)
@@ -45,8 +45,6 @@ typedef void task_fn_t(void *context, in
 
 struct task {
 	STAILQ_ENTRY(task) ta_link;	/* (q) link for queue */
-	u_int	ta_flags;		/* (q) state of this task */
-#define	TA_FLAGS_RUNNING	0x01
 	u_short	ta_pending;		/* (q) count times queued */
 	u_short	ta_priority;		/* (c) Priority */
 	task_fn_t *ta_func;		/* (c) task handler */

Modified: head/sys/sys/taskqueue.h
==============================================================================
--- head/sys/sys/taskqueue.h	Fri May 28 17:50:35 2010	(r208622)
+++ head/sys/sys/taskqueue.h	Fri May 28 18:15:28 2010	(r208623)
@@ -75,7 +75,6 @@ void	taskqueue_thread_enqueue(void *cont
 	(task)->ta_priority = (priority);		\
 	(task)->ta_func = (func);			\
 	(task)->ta_context = (context);			\
-	(task)->ta_flags = 0;				\
 } while (0)
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201005281815.o4SIFSWr070281>