Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 1 Nov 2010 13:07:29 -0700
From:      Matthew Fleming <mdf356@gmail.com>
To:        Hans Petter Selasky <hselasky@c2i.net>
Cc:        freebsd-current@freebsd.org, Weongyo Jeong <weongyo.jeong@gmail.com>, freebsd-usb@freebsd.org, Andrew Thompson <thompsa@freebsd.org>, freebsd-arch@freebsd.org
Subject:   Re: [RFC] Outline of USB process integration in the kernel taskqueue system
Message-ID:  <AANLkTi=uA3t8YHNWU_D37c57E=dvbxBQ7FdgRK4h3h5O@mail.gmail.com>
In-Reply-To: <201011012054.59551.hselasky@c2i.net>
References:  <201011012054.59551.hselasky@c2i.net>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, Nov 1, 2010 at 12:54 PM, Hans Petter Selasky <hselasky@c2i.net> wro=
te:
> Hi!
>
> I've wrapped up an outline patch for what needs to be done to integrate t=
he
> USB process framework into the kernel taskqueue system in a more direct w=
ay
> that to wrap it.
>
> The limitation of the existing taskqueue system is that it only guarantee=
s
> execution at a given priority level. USB requires more. USB also requires=
 a
> guarantee that the last task queued task also gets executed last. This is=
 for
> example so that a deferred USB detach event does not happen before any pe=
nding
> deferred I/O for example in case of multiple occurring events.
>
> Mostly this new feature is targeted for GPIO-alike system using slow buss=
es
> like the USB. Typical use case:
>
> 2 tasks to program GPIO on.
> 2 tasks to program GPIO off.
>
> Example:
>
> a) taskqueue_enqueue_odd(&sc->sc_taskqueue, &sc->sc_task_on[0], &sc-
>>sc_task_on[1]);
>
>
> b) taskqueue_enqueue_odd(&sc->sc_taskqueue, &sc->sc_task_off[0], &sc-
>>sc_task_off[1]);
>
>
> No matter how the call ordering of code-line a) and b), we are always
> guaranteed that the last queued state "on" or "off" is reached before the=
 head
> of the taskqueue empties.
>
>
> In lack of a better name, the new function was called taskqueue_enqueue_o=
dd
> [some people obviously think that USB processes are odd, but not taskqueu=
es
> :-)]

I'd like to make sure I understand the USB requirements.

(1) does USB need the task priority field?  Many taskqueue(9) consumers do =
not.

(2) if there was a working taskqueue_remove(9) that removed the task
if pending or returned error if the task was currently running, would
that be sufficient to implement the required USB functionality?
(assuming that taskqueue_enqueue(9) put all tasks with equal priority
in order of queueing).

Thanks,
matthew

> Manpage:
>
> .Ft int
> .Fn taskqueue_enqueue_odd "struct taskqueue *queue" "struct task *t0" "st=
ruct
> task *t1"
>
> ..
>
> The function
> .Fn taskqueue_enqueue_odd
> should be used if it is important that the last queued task is also
> executed last in the task queue at the given priority level. This
> function requires two valid task pointers. Depending on which of the
> tasks passed are queued at the calling moment, the last queued task of
> the two will get dequeued and put last in the task queue, while not
> touching the first queued task. If no tasks are queued at the calling
> moment, this function behaves like
> .Fn taskqueue_enqueue .
> This function returns zero if the first task was queued last, one if
> the second task was queued last.
>
> Preliminary patch - see e-mail attachment.
>
> Comments are welcome!
>
> --HPS
>
> More docs: Also see talk about the new USB stack in FreeBSD on Youtube.
>
> =3D=3D=3D share/man/man9/taskqueue.9
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- share/man/man9/taskqueue.9 =A0(revision 214211)
> +++ share/man/man9/taskqueue.9 =A0(local)
> @@ -46,11 +46,15 @@
> =A0typedef void (*taskqueue_enqueue_fn)(void *context);
>
> =A0struct task {
> - =A0 =A0 =A0 STAILQ_ENTRY(task) =A0 =A0 =A0ta_link; =A0 =A0 =A0 =A0/* li=
nk for queue */
> - =A0 =A0 =A0 u_short =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ta_pending; =A0 =A0=
 /* count times queued */
> - =A0 =A0 =A0 u_short =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ta_priority; =A0 =
=A0/* priority of task in queue */
> - =A0 =A0 =A0 task_fn_t =A0 =A0 =A0 =A0 =A0 =A0 =A0 ta_func; =A0 =A0 =A0 =
=A0/* task handler */
> - =A0 =A0 =A0 void =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*ta_context; =
=A0 =A0/* argument for handler */
> + =A0 =A0 =A0 TAILQ_ENTRY(task) ta_link; =A0 =A0 =A0/* link for queue */
> +#define =A0 =A0 =A0 =A0TASKQUEUE_SEQUENCE_MAX =A0255
> + =A0 =A0 =A0 u_char =A0ta_sequence; =A0 =A0 =A0 =A0 =A0 =A0/* sequence n=
umber */
> +#define =A0 =A0 =A0 =A0TASKQUEUE_PENDING_MAX =A0 255
> + =A0 =A0 =A0 u_char =A0ta_pending; =A0 =A0 =A0 =A0 =A0 =A0 /* count time=
s queued */
> +#define =A0 =A0 =A0 =A0TASKQUEUE_PRIORITY_MAX =A065535U
> + =A0 =A0 =A0 u_short ta_priority; =A0 =A0 =A0 =A0 =A0 =A0/* priority of =
task in queue */
> + =A0 =A0 =A0 task_fn_t *ta_func; =A0 =A0 =A0 =A0 =A0 =A0 /* task handler=
 */
> + =A0 =A0 =A0 void =A0 =A0*ta_context; =A0 =A0 =A0 =A0 =A0 =A0/* argument=
 for handler */
> =A0};
> =A0.Ed
> =A0.Ft struct taskqueue *
> @@ -62,6 +66,8 @@
> =A0.Ft int
> =A0.Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task"
> =A0.Ft int
> +.Fn taskqueue_enqueue_odd "struct taskqueue *queue" "struct task *t0" "s=
truct task *t1"
> +.Ft int
> =A0.Fn taskqueue_enqueue_fast "struct taskqueue *queue" "struct task *tas=
k"
> =A0.Ft void
> =A0.Fn taskqueue_drain "struct taskqueue *queue" "struct task *task"
> @@ -134,6 +140,19 @@
> =A0if the queue is being freed.
> =A0.Pp
> =A0The function
> +.Fn taskqueue_enqueue_odd
> +should be used if it is important that the last queued task is also
> +executed last in the task queue at the given priority level. This
> +function requires two valid task pointers. Depending on which of the
> +tasks passed are queued at the calling moment, the last queued task of
> +the two will get dequeued and put last in the task queue, while not
> +touching the first queued task. If no tasks are queued at the calling
> +moment, this function behaves like
> +.Fn taskqueue_enqueue .
> +This function returns zero if the first task was queued last, one if
> +the second task was queued last.
> +.Pp
> +The function
> =A0.Fn taskqueue_enqueue_fast
> =A0should be used in place of
> =A0.Fn taskqueue_enqueue
> =3D=3D=3D sys/sys/_task.h
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- sys/sys/_task.h =A0 =A0 (revision 214433)
> +++ sys/sys/_task.h =A0 =A0 (local)
> @@ -44,9 +44,13 @@
> =A0typedef void task_fn_t(void *context, int pending);
>
> =A0struct task {
> - =A0 =A0 =A0 STAILQ_ENTRY(task) ta_link; =A0 =A0 /* (q) link for queue *=
/
> - =A0 =A0 =A0 u_short ta_pending; =A0 =A0 =A0 =A0 =A0 =A0 /* (q) count ti=
mes queued */
> - =A0 =A0 =A0 u_short ta_priority; =A0 =A0 =A0 =A0 =A0 =A0/* (c) Priority=
 */
> + =A0 =A0 =A0 TAILQ_ENTRY(task) ta_link; =A0 =A0 =A0/* (q) link for queue=
 */
> +#define =A0 =A0 =A0 =A0TASKQUEUE_SEQUENCE_MAX =A0255U
> + =A0 =A0 =A0 u_char =A0ta_sequence; =A0 =A0 =A0 =A0 =A0 =A0/* (q) sequen=
ce number */
> +#define =A0 =A0 =A0 =A0TASKQUEUE_PENDING_MAX =A0 255U
> + =A0 =A0 =A0 u_char =A0ta_pending; =A0 =A0 =A0 =A0 =A0 =A0 /* (q) count =
times queued */
> +#define =A0 =A0 =A0 =A0TASKQUEUE_PRIORITY_MAX =A065535U
> + =A0 =A0 =A0 u_short ta_priority; =A0 =A0 =A0 =A0 =A0 =A0/* (c) priority=
 of task in queue */
> =A0 =A0 =A0 =A0task_fn_t *ta_func; =A0 =A0 =A0 =A0 =A0 =A0 /* (c) task ha=
ndler */
> =A0 =A0 =A0 =A0void =A0 =A0*ta_context; =A0 =A0 =A0 =A0 =A0 =A0/* (c) arg=
ument for handler */
> =A0};
> =3D=3D=3D sys/sys/taskqueue.h
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- sys/sys/taskqueue.h (revision 214433)
> +++ sys/sys/taskqueue.h (local)
> @@ -54,6 +54,7 @@
> =A0int =A0 =A0taskqueue_start_threads(struct taskqueue **tqp, int count, =
int pri,
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0const char=
 *name, ...) __printflike(4, 5);
> =A0int =A0 =A0taskqueue_enqueue(struct taskqueue *queue, struct task *tas=
k);
> +int =A0 =A0taskqueue_enqueue_odd(struct taskqueue *queue, struct task *t=
0, struct task *t1);
> =A0void =A0 taskqueue_drain(struct taskqueue *queue, struct task *task);
> =A0void =A0 taskqueue_free(struct taskqueue *queue);
> =A0void =A0 taskqueue_run(struct taskqueue *queue);
> @@ -71,6 +72,7 @@
> =A0* Initialise a task structure.
> =A0*/
> =A0#define TASK_INIT(task, priority, func, context) do { =A0\
> + =A0 =A0 =A0 (task)->ta_link.tqe_prev =3D NULL; =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0\
> =A0 =A0 =A0 =A0(task)->ta_pending =3D 0; =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 \
> =A0 =A0 =A0 =A0(task)->ta_priority =3D (priority); =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 \
> =A0 =A0 =A0 =A0(task)->ta_func =3D (func); =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 \
> =3D=3D=3D sys/kern/subr_taskqueue.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> --- sys/kern/subr_taskqueue.c =A0 (revision 214433)
> +++ sys/kern/subr_taskqueue.c =A0 (local)
> @@ -52,7 +52,7 @@
> =A0};
>
> =A0struct taskqueue {
> - =A0 =A0 =A0 STAILQ_HEAD(, task) =A0 =A0 tq_queue;
> + =A0 =A0 =A0 TAILQ_HEAD(task_head, task) =A0 =A0 tq_queue;
> =A0 =A0 =A0 =A0const char =A0 =A0 =A0 =A0 =A0 =A0 =A0*tq_name;
> =A0 =A0 =A0 =A0taskqueue_enqueue_fn =A0 =A0tq_enqueue;
> =A0 =A0 =A0 =A0void =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*tq_context;
> @@ -62,12 +62,15 @@
> =A0 =A0 =A0 =A0int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tq_tcount;
> =A0 =A0 =A0 =A0int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tq_spin;
> =A0 =A0 =A0 =A0int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tq_flags;
> + =A0 =A0 =A0 u_char =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tq_sequence;
> =A0};
>
> =A0#define =A0 =A0 =A0 =A0TQ_FLAGS_ACTIVE =A0 =A0 =A0 =A0 (1 << 0)
> =A0#define =A0 =A0 =A0 =A0TQ_FLAGS_BLOCKED =A0 =A0 =A0 =A0(1 << 1)
> =A0#define =A0 =A0 =A0 =A0TQ_FLAGS_PENDING =A0 =A0 =A0 =A0(1 << 2)
>
> +static void taskqueue_enqueue_locked(struct taskqueue *, struct task *);
> +
> =A0static __inline void
> =A0TQ_LOCK(struct taskqueue *tq)
> =A0{
> @@ -106,7 +109,7 @@
> =A0 =A0 =A0 =A0if (!queue)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return NULL;
>
> - =A0 =A0 =A0 STAILQ_INIT(&queue->tq_queue);
> + =A0 =A0 =A0 TAILQ_INIT(&queue->tq_queue);
> =A0 =A0 =A0 =A0TAILQ_INIT(&queue->tq_active);
> =A0 =A0 =A0 =A0queue->tq_name =3D name;
> =A0 =A0 =A0 =A0queue->tq_enqueue =3D enqueue;
> @@ -155,48 +158,132 @@
> =A0int
> =A0taskqueue_enqueue(struct taskqueue *queue, struct task *task)
> =A0{
> - =A0 =A0 =A0 struct task *ins;
> - =A0 =A0 =A0 struct task *prev;
> -
> =A0 =A0 =A0 =A0TQ_LOCK(queue);
>
> =A0 =A0 =A0 =A0/*
> =A0 =A0 =A0 =A0 * Count multiple enqueues.
> =A0 =A0 =A0 =A0 */
> =A0 =A0 =A0 =A0if (task->ta_pending) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 task->ta_pending++;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (task->ta_pending !=3D TASKQUEUE_PENDING=
_MAX)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 task->ta_pending++;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0TQ_UNLOCK(queue);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 return 0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return (0);
> =A0 =A0 =A0 =A0}
>
> + =A0 =A0 =A0 KASSERT(task->ta_link.tqe_prev =3D=3D NULL, ("Task already =
queued?"));
> +
> + =A0 =A0 =A0 /* Insert task in queue */
> +
> + =A0 =A0 =A0 taskqueue_enqueue_locked(queue, task);
> +
> + =A0 =A0 =A0 TQ_UNLOCK(queue);
> +
> + =A0 =A0 =A0 return (0);
> +}
> +
> +/* Enqueue task ordered and dualed */
> +
> +int
> +taskqueue_enqueue_odd(struct taskqueue *queue, struct task *t0, struct t=
ask *t1)
> +{
> + =A0 =A0 =A0 struct task *tx;
> + =A0 =A0 =A0 uint8_t t;
> + =A0 =A0 =A0 uint8_t d;
> +
> + =A0 =A0 =A0 TQ_LOCK(queue);
> +
> =A0 =A0 =A0 =A0/*
> + =A0 =A0 =A0 =A0* Compute a number based on which of the two tasks passe=
d as
> + =A0 =A0 =A0 =A0* arguments to this function are queued.
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 t =3D 0;
> + =A0 =A0 =A0 if (t0->ta_link.tqe_prev !=3D NULL)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 t |=3D 1;
> + =A0 =A0 =A0 if (t1->ta_link.tqe_prev !=3D NULL)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 t |=3D 2;
> +
> + =A0 =A0 =A0 if (t =3D=3D 0) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* No entries are queued. Queue task "t0"=
 last and use
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* the existing sequence number.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 tx =3D t0;
> + =A0 =A0 =A0 } else if (t =3D=3D 1) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Check if we need to increment the sequ=
ence number.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (t0->ta_sequence =3D=3D queue->tq_sequen=
ce)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 queue->tq_sequence++;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 tx =3D t1;
> + =A0 =A0 =A0 } else if (t =3D=3D 2) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Check if we need to increment the sequ=
ence number.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (t1->ta_sequence =3D=3D queue->tq_sequen=
ce)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 queue->tq_sequence++;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 tx =3D t0;
> + =A0 =A0 =A0 } else {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Both tasks are queued. Re-queue the ta=
sk closest to
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* the end which is computed by looking a=
t the
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* sequence number.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 d =3D (t1->ta_sequence - t0->ta_sequence);
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Check sign after subtraction */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (d & 0x80)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tx =3D t0;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 else
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tx =3D t1;
> +
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 TAILQ_REMOVE(&queue->tq_queue, tx, ta_link)=
;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Insert task in queue */
> +
> + =A0 =A0 =A0 taskqueue_enqueue_locked(queue, tx);
> +
> + =A0 =A0 =A0 TQ_UNLOCK(queue);
> +
> + =A0 =A0 =A0 if (tx =3D=3D t1)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return (1);
> +
> + =A0 =A0 =A0 return (0);
> +}
> +
> +static void
> +taskqueue_enqueue_locked(struct taskqueue *queue, struct task *task)
> +{
> + =A0 =A0 =A0 struct task *ins;
> + =A0 =A0 =A0 struct task *prev;
> +
> + =A0 =A0 =A0 /*
> =A0 =A0 =A0 =A0 * Optimise the case when all tasks have the same priority=
.
> =A0 =A0 =A0 =A0 */
> - =A0 =A0 =A0 prev =3D STAILQ_LAST(&queue->tq_queue, task, ta_link);
> + =A0 =A0 =A0 prev =3D TAILQ_LAST(&queue->tq_queue, task_head);
> =A0 =A0 =A0 =A0if (!prev || prev->ta_priority >=3D task->ta_priority) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 STAILQ_INSERT_TAIL(&queue->tq_queue, task, =
ta_link);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 TAILQ_INSERT_TAIL(&queue->tq_queue, task, t=
a_link);
> =A0 =A0 =A0 =A0} else {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0prev =3D NULL;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 for (ins =3D STAILQ_FIRST(&queue->tq_queue)=
; ins;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0prev =3D ins, ins =3D STAILQ_NEX=
T(ins, ta_link))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 for (ins =3D TAILQ_FIRST(&queue->tq_queue);=
 ins;
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0prev =3D ins, ins =3D TAILQ_NEXT=
(ins, ta_link))
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (ins->ta_priority < tas=
k->ta_priority)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (prev)
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 STAILQ_INSERT_AFTER(&queue-=
>tq_queue, prev, task, ta_link);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 TAILQ_INSERT_AFTER(&queue->=
tq_queue, prev, task, ta_link);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0else
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 STAILQ_INSERT_HEAD(&queue->=
tq_queue, task, ta_link);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 TAILQ_INSERT_HEAD(&queue->t=
q_queue, task, ta_link);
> =A0 =A0 =A0 =A0}
>
> + =A0 =A0 =A0 task->ta_sequence =3D queue->tq_sequence;
> =A0 =A0 =A0 =A0task->ta_pending =3D 1;
> =A0 =A0 =A0 =A0if ((queue->tq_flags & TQ_FLAGS_BLOCKED) =3D=3D 0)
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0queue->tq_enqueue(queue->tq_context);
> =A0 =A0 =A0 =A0else
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0queue->tq_flags |=3D TQ_FLAGS_PENDING;
> -
> - =A0 =A0 =A0 TQ_UNLOCK(queue);
> -
> - =A0 =A0 =A0 return 0;
> =A0}
>
> =A0void
> @@ -232,13 +319,14 @@
> =A0 =A0 =A0 =A0tb.tb_running =3D NULL;
> =A0 =A0 =A0 =A0TAILQ_INSERT_TAIL(&queue->tq_active, &tb, tb_link);
>
> - =A0 =A0 =A0 while (STAILQ_FIRST(&queue->tq_queue)) {
> + =A0 =A0 =A0 while ((task =3D TAILQ_FIRST(&queue->tq_queue)) !=3D NULL) =
{
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/*
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Carefully remove the first task from t=
he queue and
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* zero its pending count.
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* Carefully remove the first task from t=
he queue,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* clear the previous next pointer and ze=
ro its
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* pending count.
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 */
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 task =3D STAILQ_FIRST(&queue->tq_queue);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 STAILQ_REMOVE_HEAD(&queue->tq_queue, ta_lin=
k);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 TAILQ_REMOVE(&queue->tq_queue, task, ta_lin=
k);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 task->ta_link.tqe_prev =3D NULL;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0pending =3D task->ta_pending;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0task->ta_pending =3D 0;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0tb.tb_running =3D task;
>
> _______________________________________________
> freebsd-arch@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-arch
> To unsubscribe, send any mail to "freebsd-arch-unsubscribe@freebsd.org"
>



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