Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 29 Dec 2006 23:06:43 +0100
From:      usleepless@gmail.com
To:        "Derrick Ryalls" <ryallsd@gmail.com>
Cc:        freebsd-multimedia@freebsd.org
Subject:   Re: MythTV port - status report
Message-ID:  <c39ec84c0612291406v60c6c8edgda86a19c3f4c5806@mail.gmail.com>
In-Reply-To: <d5eb95fc0612281453n7cd2de31t92ca7a88ed67599b@mail.gmail.com>
References:  <20061224230155.fc0a6c6a.torfinn.ingolfsen@broadpark.no> <c39ec84c0612241431n6f3e66e7n9a1a38f4258097e3@mail.gmail.com> <20061225001321.5dfb2975.torfinn.ingolfsen@broadpark.no> <d5eb95fc0612280230u66b81742od4f4435490b1bf5c@mail.gmail.com> <20061228145909.bbb6d193.torfinn.ingolfsen@broadpark.no> <d5eb95fc0612281435k1357d907p99adad9912313368@mail.gmail.com> <c39ec84c0612281449q6e62ac56pb54d42cd790fadd5@mail.gmail.com> <d5eb95fc0612281453n7cd2de31t92ca7a88ed67599b@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
Torfinn, Derrick, List,

> > i will try to package my latest version of the pvrxxx asap.
> >  - it downloads the firmware images from ivtv
> >  - it supports the v4l2 interface you need ( or you'll need to tweak
> > mythtv to support the bsdstyle of accessing the device )
> >
> > i hope to have it ready tomorrow.
> >
> > regards,
> >
> > usleep
> >
>
> Thanks!
>
> I look forward to trying it out.

well, here is the first try. files:

pvrxxx.tgz:
  the port, extract in /usr/ports/multimedia
pvrxxx_gpl.tgz:
  some gpl-ivtv-files, put it in /usr/ports/distfiles
sys/kern/subr_taskqueue.c(.diff):
  this is how my subr_taskqueue.c looks like. it was taken from 7.0?,
and it is the code that supports the new if_em and now pvrxxx too. it
is needed to implement fast interrupts.
sys/sys/taskqueue.h(.diff)
  idem dito.

i can imagine very well that there might be problems. please let me know.

regards,

usleep

[-- Attachment #2 --]
--- subr_taskqueue.c.bkp	Mon Oct 23 20:01:42 2006
+++ subr_taskqueue.c	Thu Oct 26 12:44:35 2006
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/kern/subr_taskqueue.c,v 1.27.2.3 2006/04/02 00:14:57 sam Exp $");
+__FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/kern/subr_taskqueue.c,v 1.27.2.5 2006/09/02 15:28:09 sam Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -37,8 +37,10 @@
 #include <sys/malloc.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
+#include <sys/sched.h>
 #include <sys/taskqueue.h>
 #include <sys/unistd.h>
+#include <machine/stdarg.h>
 
 static MALLOC_DEFINE(M_TASKQUEUE, "taskqueue", "Task Queues");
 static void	*taskqueue_giant_ih;
@@ -55,10 +57,42 @@
 	struct task		*tq_running;
 	struct mtx		tq_mutex;
 	struct proc		**tq_pproc;
+	int			tq_pcount;
+	int			tq_spin;
+	int			tq_flags;
 };
 
+#define	TQ_FLAGS_ACTIVE		(1 << 0)
+
+static __inline void
+TQ_LOCK(struct taskqueue *tq)
+{
+	if (tq->tq_spin)
+		mtx_lock_spin(&tq->tq_mutex);
+	else
+		mtx_lock(&tq->tq_mutex);
+}
+
+static __inline void
+TQ_UNLOCK(struct taskqueue *tq)
+{
+	if (tq->tq_spin)
+		mtx_unlock_spin(&tq->tq_mutex);
+	else
+		mtx_unlock(&tq->tq_mutex);
+}
+
 static void	init_taskqueue_list(void *data);
 
+static __inline int
+TQ_SLEEP(struct taskqueue *tq, void *p, struct mtx *m, int pri, const char *wm,
+    int t)
+{
+	if (tq->tq_spin)
+		return (msleep_spin(p, m, wm, t));
+	return (msleep(p, m, pri, wm, t));
+}
+
 static void
 init_taskqueue_list(void *data __unused)
 {
@@ -69,10 +103,10 @@
 SYSINIT(taskqueue_list, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_taskqueue_list,
     NULL);
 
-struct taskqueue *
-taskqueue_create(const char *name, int mflags,
+static struct taskqueue *
+_taskqueue_create(const char *name, int mflags,
 		 taskqueue_enqueue_fn enqueue, void *context,
-		 struct proc **pp)
+		 int mtxflags, const char *mtxname)
 {
 	struct taskqueue *queue;
 
@@ -84,8 +118,9 @@
 	queue->tq_name = name;
 	queue->tq_enqueue = enqueue;
 	queue->tq_context = context;
-	queue->tq_pproc = pp;
-	mtx_init(&queue->tq_mutex, "taskqueue", NULL, MTX_DEF);
+	queue->tq_spin = (mtxflags & MTX_SPIN) != 0;
+	queue->tq_flags |= TQ_FLAGS_ACTIVE;
+	mtx_init(&queue->tq_mutex, mtxname, NULL, mtxflags);
 
 	mtx_lock(&taskqueue_queues_mutex);
 	STAILQ_INSERT_TAIL(&taskqueue_queues, queue, tq_link);
@@ -94,23 +129,26 @@
 	return queue;
 }
 
+struct taskqueue *
+taskqueue_create(const char *name, int mflags,
+		 taskqueue_enqueue_fn enqueue, void *context,
+		 struct proc **pp)
+{
+	(void) pp;
+	return _taskqueue_create(name, mflags, enqueue, context,
+			MTX_DEF, "taskqueue");
+}
+
 /*
  * Signal a taskqueue thread to terminate.
  */
 static void
 taskqueue_terminate(struct proc **pp, struct taskqueue *tq)
 {
-	struct proc *p;
 
-	p = *pp;
-	*pp = NULL;
-	if (p) {
-		wakeup_one(tq);
-		PROC_LOCK(p);		   /* NB: insure we don't miss wakeup */
-		mtx_unlock(&tq->tq_mutex); /* let taskqueue thread run */
-		msleep(p, &p->p_mtx, PWAIT, "taskqueue_destroy", 0);
-		PROC_UNLOCK(p);
-		mtx_lock(&tq->tq_mutex);
+	while (tq->tq_pcount > 0) {
+		wakeup(tq);
+		TQ_SLEEP(tq, pp, &tq->tq_mutex, PWAIT, "taskqueue_destroy", 0);
 	}
 }
 
@@ -122,10 +160,12 @@
 	STAILQ_REMOVE(&taskqueue_queues, queue, taskqueue, tq_link);
 	mtx_unlock(&taskqueue_queues_mutex);
 
-	mtx_lock(&queue->tq_mutex);
+	TQ_LOCK(queue);
+	queue->tq_flags &= ~TQ_FLAGS_ACTIVE;
 	taskqueue_run(queue);
 	taskqueue_terminate(queue->tq_pproc, queue);
 	mtx_destroy(&queue->tq_mutex);
+	free(queue->tq_pproc, M_TASKQUEUE);
 	free(queue, M_TASKQUEUE);
 }
 
@@ -140,7 +180,7 @@
 	mtx_lock(&taskqueue_queues_mutex);
 	STAILQ_FOREACH(queue, &taskqueue_queues, tq_link) {
 		if (strcmp(queue->tq_name, name) == 0) {
-			mtx_lock(&queue->tq_mutex);
+			TQ_LOCK(queue);
 			mtx_unlock(&taskqueue_queues_mutex);
 			return queue;
 		}
@@ -155,14 +195,14 @@
 	struct task *ins;
 	struct task *prev;
 
-	mtx_lock(&queue->tq_mutex);
+	TQ_LOCK(queue);
 
 	/*
 	 * Count multiple enqueues.
 	 */
 	if (task->ta_pending) {
 		task->ta_pending++;
-		mtx_unlock(&queue->tq_mutex);
+		TQ_UNLOCK(queue);
 		return 0;
 	}
 
@@ -188,7 +228,7 @@
 	task->ta_pending = 1;
 	queue->tq_enqueue(queue->tq_context);
 
-	mtx_unlock(&queue->tq_mutex);
+	TQ_UNLOCK(queue);
 
 	return 0;
 }
@@ -201,7 +241,7 @@
 
 	owned = mtx_owned(&queue->tq_mutex);
 	if (!owned)
-		mtx_lock(&queue->tq_mutex);
+		TQ_LOCK(queue);
 	while (STAILQ_FIRST(&queue->tq_queue)) {
 		/*
 		 * Carefully remove the first task from the queue and
@@ -212,11 +252,11 @@
 		pending = task->ta_pending;
 		task->ta_pending = 0;
 		queue->tq_running = task;
-		mtx_unlock(&queue->tq_mutex);
+		TQ_UNLOCK(queue);
 
 		task->ta_func(task->ta_context, pending);
 
-		mtx_lock(&queue->tq_mutex);
+		TQ_LOCK(queue);
 		queue->tq_running = NULL;
 		wakeup(task);
 	}
@@ -226,18 +266,30 @@
 	 * on entry, although this opens a race window.
 	 */
 	if (!owned)
-		mtx_unlock(&queue->tq_mutex);
+		TQ_UNLOCK(queue);
 }
 
 void
 taskqueue_drain(struct taskqueue *queue, struct task *task)
 {
-	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "taskqueue_drain");
+	if (queue->tq_spin) {		/* XXX */
+		mtx_lock_spin(&queue->tq_mutex);
+		if(task)
+		while (task->ta_pending != 0 || task == queue->tq_running)
+			msleep_spin(task, &queue->tq_mutex, "-", 0);
+		else
+		while(!STAILQ_EMPTY(&queue->tq_queue))
+			msleep_spin(STAILQ_FIRST(&queue->tq_queue), &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 == queue->tq_running)
-		msleep(task, &queue->tq_mutex, PWAIT, "-", 0);
-	mtx_unlock(&queue->tq_mutex);
+		mtx_lock(&queue->tq_mutex);
+		while (task->ta_pending != 0 || task == queue->tq_running)
+			msleep(task, &queue->tq_mutex, PWAIT, "-", 0);
+		mtx_unlock(&queue->tq_mutex);
+	}
 }
 
 static void
@@ -264,6 +316,59 @@
 	taskqueue_run(taskqueue_swi_giant);
 }
 
+int
+taskqueue_start_threads(struct taskqueue **tqp, int count, int pri,
+			const char *name, ...)
+{
+	va_list ap;
+	struct taskqueue *tq;
+	struct thread *td;
+	char ktname[MAXCOMLEN];
+	int i, error;
+
+	if (count <= 0)
+		return (EINVAL);
+	tq = *tqp;
+
+	va_start(ap, name);
+	vsnprintf(ktname, MAXCOMLEN, name, ap);
+	va_end(ap);
+
+	tq->tq_pproc = malloc(sizeof(struct proc *) * count, M_TASKQUEUE,
+	    M_NOWAIT | M_ZERO);
+	if (tq->tq_pproc == NULL) {
+		printf("%s: no memory for %s threads\n", __func__, ktname);
+		return (ENOMEM);
+	}
+
+	for (i = 0; i < count; i++) {
+		if (count == 1)
+			error = kthread_create(taskqueue_thread_loop, tqp,
+			    &tq->tq_pproc[i], RFSTOPPED, 0, ktname);
+		else
+			error = kthread_create(taskqueue_thread_loop, tqp,
+			    &tq->tq_pproc[i], RFSTOPPED, 0, "%s_%d", ktname, i);
+		if (error) {
+			/* should be ok to continue, taskqueue_free will dtrt */
+			printf("%s: kthread_create(%s): error %d",
+				__func__, ktname, error);
+			tq->tq_pproc[i] = NULL;		/* paranoid */
+		} else
+			tq->tq_pcount++;
+	}
+	mtx_lock_spin(&sched_lock);
+	for (i = 0; i < count; i++) {
+		if (tq->tq_pproc[i] == NULL)
+			continue;
+		td = FIRST_THREAD_IN_PROC(tq->tq_pproc[i]);
+		sched_prio(td, pri);
+		setrunqueue(td, SRQ_BORING);
+	}
+	mtx_unlock_spin(&sched_lock);
+
+	return (0);
+}
+
 void
 taskqueue_thread_loop(void *arg)
 {
@@ -271,15 +376,16 @@
 
 	tqp = arg;
 	tq = *tqp;
-	mtx_lock(&tq->tq_mutex);
+	TQ_LOCK(tq);
 	do {
 		taskqueue_run(tq);
-		msleep(tq, &tq->tq_mutex, PWAIT, "-", 0); 
-	} while (*tq->tq_pproc != NULL);
+		TQ_SLEEP(tq, tq, &tq->tq_mutex, 0, "-", 0);
+	} while ((tq->tq_flags & TQ_FLAGS_ACTIVE) != 0);
 
 	/* rendezvous with thread that asked us to terminate */
-	wakeup_one(tq);
-	mtx_unlock(&tq->tq_mutex);
+	tq->tq_pcount--;
+	wakeup_one(tq->tq_pproc);
+	TQ_UNLOCK(tq);
 	kthread_exit(0);
 }
 
@@ -300,85 +406,30 @@
 		     INTR_MPSAFE, &taskqueue_ih)); 
 
 TASKQUEUE_DEFINE(swi_giant, taskqueue_swi_giant_enqueue, 0,
-		 swi_add(NULL, "Giant task queue", taskqueue_swi_giant_run,
+		 swi_add(NULL, "Giant taskq", taskqueue_swi_giant_run,
 		     NULL, SWI_TQ_GIANT, 0, &taskqueue_giant_ih)); 
 
 TASKQUEUE_DEFINE_THREAD(thread);
 
-int
-taskqueue_enqueue_fast(struct taskqueue *queue, struct task *task)
+struct taskqueue *
+taskqueue_create_fast(const char *name, int mflags,
+		 taskqueue_enqueue_fn enqueue, void *context)
 {
-	struct task *ins;
-	struct task *prev;
-
-	mtx_lock_spin(&queue->tq_mutex);
-
-	/*
-	 * Count multiple enqueues.
-	 */
-	if (task->ta_pending) {
-		task->ta_pending++;
-		mtx_unlock_spin(&queue->tq_mutex);
-		return 0;
-	}
-
-	/*
-	 * Optimise the case when all tasks have the same priority.
-	 */
-	prev = STAILQ_LAST(&queue->tq_queue, task, ta_link);
-	if (!prev || prev->ta_priority >= task->ta_priority) {
-		STAILQ_INSERT_TAIL(&queue->tq_queue, task, ta_link);
-	} else {
-		prev = 0;
-		for (ins = STAILQ_FIRST(&queue->tq_queue); ins;
-		     prev = ins, ins = STAILQ_NEXT(ins, ta_link))
-			if (ins->ta_priority < task->ta_priority)
-				break;
-
-		if (prev)
-			STAILQ_INSERT_AFTER(&queue->tq_queue, prev, task, ta_link);
-		else
-			STAILQ_INSERT_HEAD(&queue->tq_queue, task, ta_link);
-	}
-
-	task->ta_pending = 1;
-	queue->tq_enqueue(queue->tq_context);
-
-	mtx_unlock_spin(&queue->tq_mutex);
-
-	return 0;
+	return _taskqueue_create(name, mflags, enqueue, context,
+			MTX_SPIN, "fast_taskqueue");
 }
 
-static void
-taskqueue_run_fast(struct taskqueue *queue)
+/* NB: for backwards compatibility */
+int
+taskqueue_enqueue_fast(struct taskqueue *queue, struct task *task)
 {
-	struct task *task;
-	int pending;
-
-	mtx_lock_spin(&queue->tq_mutex);
-	while (STAILQ_FIRST(&queue->tq_queue)) {
-		/*
-		 * Carefully remove the first task from the queue and
-		 * zero its pending count.
-		 */
-		task = STAILQ_FIRST(&queue->tq_queue);
-		STAILQ_REMOVE_HEAD(&queue->tq_queue, ta_link);
-		pending = task->ta_pending;
-		task->ta_pending = 0;
-		mtx_unlock_spin(&queue->tq_mutex);
-
-		task->ta_func(task->ta_context, pending);
-
-		mtx_lock_spin(&queue->tq_mutex);
-	}
-	mtx_unlock_spin(&queue->tq_mutex);
+	return taskqueue_enqueue(queue, task);
 }
 
-struct taskqueue *taskqueue_fast;
 static void	*taskqueue_fast_ih;
 
 static void
-taskqueue_fast_schedule(void *context)
+taskqueue_fast_enqueue(void *context)
 {
 	swi_sched(taskqueue_fast_ih, 0);
 }
@@ -386,31 +437,9 @@
 static void
 taskqueue_fast_run(void *dummy)
 {
-	taskqueue_run_fast(taskqueue_fast);
+	taskqueue_run(taskqueue_fast);
 }
 
-static void
-taskqueue_define_fast(void *arg)
-{
-
-	taskqueue_fast = malloc(sizeof(struct taskqueue), M_TASKQUEUE,
-	    M_NOWAIT | M_ZERO);
-	if (!taskqueue_fast) {
-		printf("%s: Unable to allocate fast task queue!\n", __func__);
-		return;
-	}
-
-	STAILQ_INIT(&taskqueue_fast->tq_queue);
-	taskqueue_fast->tq_name = "fast";
-	taskqueue_fast->tq_enqueue = taskqueue_fast_schedule;
-	mtx_init(&taskqueue_fast->tq_mutex, "taskqueue_fast", NULL, MTX_SPIN);
-
-	mtx_lock(&taskqueue_queues_mutex);
-	STAILQ_INSERT_TAIL(&taskqueue_queues, taskqueue_fast, tq_link);
-	mtx_unlock(&taskqueue_queues_mutex);
-
-	swi_add(NULL, "Fast task queue", taskqueue_fast_run,
-		NULL, SWI_TQ_FAST, INTR_MPSAFE, &taskqueue_fast_ih);
-}
-SYSINIT(taskqueue_fast, SI_SUB_CONFIGURE, SI_ORDER_SECOND,
-    taskqueue_define_fast, NULL);
+TASKQUEUE_FAST_DEFINE(fast, taskqueue_fast_enqueue, 0,
+	swi_add(NULL, "Fast task queue", taskqueue_fast_run, NULL,
+	SWI_TQ_FAST, INTR_MPSAFE, &taskqueue_fast_ih));

[-- Attachment #3 --]
--- taskqueue.h.bkp	Mon Oct 23 20:09:35 2006
+++ taskqueue.h	Mon Oct 23 20:09:41 2006
@@ -23,7 +23,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/sys/taskqueue.h,v 1.14.2.2 2006/04/02 00:14:57 sam Exp $
+ * $FreeBSD: /repoman/r/ncvs/src/sys/sys/taskqueue.h,v 1.14.2.3 2006/07/06 08:32:50 glebius Exp $
  */
 
 #ifndef _SYS_TASKQUEUE_H_
@@ -51,6 +51,8 @@
 struct taskqueue *taskqueue_create(const char *name, int mflags,
 				    taskqueue_enqueue_fn enqueue,
 				    void *context, struct proc **);
+int	taskqueue_start_threads(struct taskqueue **tqp, int count, int pri,
+				const char *name, ...) __printflike(4, 5);
 int	taskqueue_enqueue(struct taskqueue *queue, struct task *task);
 void	taskqueue_drain(struct taskqueue *queue, struct task *task);
 struct taskqueue *taskqueue_find(const char *name);
@@ -80,7 +82,7 @@
 extern struct taskqueue *taskqueue_##name
 
 /*
- * Define and initialise a taskqueue.
+ * Define and initialise a global taskqueue that uses sleep mutexes.
  */
 #define TASKQUEUE_DEFINE(name, enqueue, context, init)			\
 									\
@@ -89,10 +91,8 @@
 static void								\
 taskqueue_define_##name(void *arg)					\
 {									\
-	static struct proc *taskqueue_##name##_proc;			\
 	taskqueue_##name =						\
-	    taskqueue_create(#name, M_NOWAIT, (enqueue), (context),	\
-	    &taskqueue_##name##_proc);					\
+	    taskqueue_create(#name, M_NOWAIT, (enqueue), (context), NULL);\
 	init;								\
 }									\
 									\
@@ -102,8 +102,33 @@
 struct __hack
 #define TASKQUEUE_DEFINE_THREAD(name)					\
 TASKQUEUE_DEFINE(name, taskqueue_thread_enqueue, &taskqueue_##name,	\
-	kthread_create(taskqueue_thread_loop, &taskqueue_##name,	\
-	&taskqueue_##name##_proc, 0, 0, #name " taskq"))
+	taskqueue_start_threads(&taskqueue_##name, 1, PWAIT,		\
+	"%s taskq", #name))
+
+/*
+ * Define and initialise a global taskqueue that uses spin mutexes.
+ */
+#define TASKQUEUE_FAST_DEFINE(name, enqueue, context, init)		\
+									\
+struct taskqueue *taskqueue_##name;					\
+									\
+static void								\
+taskqueue_define_##name(void *arg)					\
+{									\
+	taskqueue_##name =						\
+	    taskqueue_create_fast(#name, M_NOWAIT, (enqueue),		\
+	    (context));							\
+	init;								\
+}									\
+									\
+SYSINIT(taskqueue_##name, SI_SUB_CONFIGURE, SI_ORDER_SECOND,		\
+	taskqueue_define_##name, NULL)					\
+									\
+struct __hack
+#define TASKQUEUE_FAST_DEFINE_THREAD(name)				\
+TASKQUEUE_FAST_DEFINE(name, taskqueue_thread_enqueue,			\
+	&taskqueue_##name, taskqueue_start_threads(&taskqueue_##name	\
+	1, PWAIT, "%s taskq", #name))
 
 /*
  * These queues are serviced by software interrupt handlers.  To enqueue
@@ -127,5 +152,8 @@
  */
 TASKQUEUE_DECLARE(fast);
 int	taskqueue_enqueue_fast(struct taskqueue *queue, struct task *task);
+struct taskqueue *taskqueue_create_fast(const char *name, int mflags,
+				    taskqueue_enqueue_fn enqueue,
+				    void *context);
 
 #endif /* !_SYS_TASKQUEUE_H_ */

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