svn commit: r254763 - projects/camlock/sys/kern

Alexander Motin mav at FreeBSD.org
Sat Aug 24 08:06:58 UTC 2013


Author: mav
Date: Sat Aug 24 08:06:57 2013
New Revision: 254763
URL: http://svnweb.freebsd.org/changeset/base/254763

Log:
  Move tq_enqueue() call out of the queue lock for known handlers (actually
  I have found no others in the base system).  This reduces queue lock hold
  time and congestion spinning under active multithreaded enqueuing.
  
  According to hwpmc, for ZFS benchmark doing 100K disk IOPS this moved 10% of
  CPU time spent on lock spinning from this lock to UMA locks.  Hope that side
  also can be addressed somehow sometimes.

Modified:
  projects/camlock/sys/kern/subr_taskqueue.c

Modified: projects/camlock/sys/kern/subr_taskqueue.c
==============================================================================
--- projects/camlock/sys/kern/subr_taskqueue.c	Sat Aug 24 07:19:57 2013	(r254762)
+++ projects/camlock/sys/kern/subr_taskqueue.c	Sat Aug 24 08:06:57 2013	(r254763)
@@ -46,6 +46,9 @@ __FBSDID("$FreeBSD$");
 static MALLOC_DEFINE(M_TASKQUEUE, "taskqueue", "Task Queues");
 static void	*taskqueue_giant_ih;
 static void	*taskqueue_ih;
+static void	 taskqueue_fast_enqueue(void *);
+static void	 taskqueue_swi_enqueue(void *);
+static void	 taskqueue_swi_giant_enqueue(void *);
 
 struct taskqueue_busy {
 	struct task	*tb_running;
@@ -69,6 +72,7 @@ struct taskqueue {
 
 #define	TQ_FLAGS_ACTIVE		(1 << 0)
 #define	TQ_FLAGS_BLOCKED	(1 << 1)
+#define	TQ_FLAGS_UNLOCKED_ENQUEUE	(1 << 2)
 
 #define	DT_CALLOUT_ARMED	(1 << 0)
 
@@ -96,7 +100,8 @@ _timeout_task_init(struct taskqueue *que
 {
 
 	TASK_INIT(&timeout_task->t, priority, func, context);
-	callout_init_mtx(&timeout_task->c, &queue->tq_mutex, 0);
+	callout_init_mtx(&timeout_task->c, &queue->tq_mutex,
+	    CALLOUT_RETURNUNLOCKED);
 	timeout_task->q = queue;
 	timeout_task->f = 0;
 }
@@ -127,6 +132,11 @@ _taskqueue_create(const char *name __unu
 	queue->tq_context = context;
 	queue->tq_spin = (mtxflags & MTX_SPIN) != 0;
 	queue->tq_flags |= TQ_FLAGS_ACTIVE;
+	if (enqueue == taskqueue_fast_enqueue ||
+	    enqueue == taskqueue_swi_enqueue ||
+	    enqueue == taskqueue_swi_giant_enqueue ||
+	    enqueue == taskqueue_thread_enqueue)
+		queue->tq_flags |= TQ_FLAGS_UNLOCKED_ENQUEUE;
 	mtx_init(&queue->tq_mutex, mtxname, NULL, mtxflags);
 
 	return queue;
@@ -196,6 +206,7 @@ taskqueue_enqueue_locked(struct taskqueu
 	if (task->ta_pending) {
 		if (task->ta_pending < USHRT_MAX)
 			task->ta_pending++;
+		TQ_UNLOCK(queue);
 		return (0);
 	}
 
@@ -219,8 +230,12 @@ taskqueue_enqueue_locked(struct taskqueu
 	}
 
 	task->ta_pending = 1;
+	if ((queue->tq_flags & TQ_FLAGS_UNLOCKED_ENQUEUE) != 0)
+		TQ_UNLOCK(queue);
 	if ((queue->tq_flags & TQ_FLAGS_BLOCKED) == 0)
 		queue->tq_enqueue(queue->tq_context);
+	if ((queue->tq_flags & TQ_FLAGS_UNLOCKED_ENQUEUE) == 0)
+		TQ_UNLOCK(queue);
 
 	return (0);
 }
@@ -231,7 +246,6 @@ taskqueue_enqueue(struct taskqueue *queu
 
 	TQ_LOCK(queue);
 	res = taskqueue_enqueue_locked(queue, task);
-	TQ_UNLOCK(queue);
 
 	return (res);
 }
@@ -277,8 +291,8 @@ taskqueue_enqueue_timeout(struct taskque
 			callout_reset(&timeout_task->c, ticks,
 			    taskqueue_timeout_func, timeout_task);
 		}
+		TQ_UNLOCK(queue);
 	}
-	TQ_UNLOCK(queue);
 	return (res);
 }
 
@@ -563,7 +577,6 @@ taskqueue_thread_enqueue(void *context)
 	tqp = context;
 	tq = *tqp;
 
-	TQ_ASSERT_LOCKED(tq);
 	wakeup_one(tq);
 }
 


More information about the svn-src-projects mailing list