From owner-freebsd-usb@FreeBSD.ORG Mon Nov 1 20:39:00 2010 Return-Path: Delivered-To: freebsd-usb@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 1E97A1065670; Mon, 1 Nov 2010 20:39:00 +0000 (UTC) (envelope-from mdf356@gmail.com) Received: from mail-iw0-f182.google.com (mail-iw0-f182.google.com [209.85.214.182]) by mx1.freebsd.org (Postfix) with ESMTP id C9BA48FC1C; Mon, 1 Nov 2010 20:38:59 +0000 (UTC) Received: by iwn39 with SMTP id 39so7508248iwn.13 for ; Mon, 01 Nov 2010 13:38:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:received:in-reply-to :references:date:message-id:subject:from:to:cc:content-type :content-transfer-encoding; bh=RWRcEYFem6yf3fFJORN9++0ZAcVpKD8bEdU3c+Br+K0=; b=nYzGF19PZHbdY+6HSGUtgeRe15B//XOSLLcRdlApiCEsfJDl804+TwBLyLFdoS3565 bIr7IkDd6DL6e6Y23BDHqLfx6hclDaqfm8mAQKsod3osYKL2lsfipRU+antc2F23hu5U JvVUWLMMAjFiHE6vZtY1BCaXoq5t1ZlFuJx0Y= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; b=FgzmYJefrCOF1QzDICxSxu1Ir7bgCDwQO1m0ULj6dYR3JNFbNqr+3mcKzt/01yg6Ch xi6P56kzYuLvAR5VkxZXSdd69O4odBl5dQnRpwfrr88GJcxZs1CjtYZdz/eN39tOlom5 8W+2qmZrQ8mgws3IO4FHcDHwMuhVEU756za4k= MIME-Version: 1.0 Received: by 10.231.36.11 with SMTP id r11mr3331721ibd.58.1288642049448; Mon, 01 Nov 2010 13:07:29 -0700 (PDT) Received: by 10.231.159.198 with HTTP; Mon, 1 Nov 2010 13:07:29 -0700 (PDT) In-Reply-To: <201011012054.59551.hselasky@c2i.net> References: <201011012054.59551.hselasky@c2i.net> Date: Mon, 1 Nov 2010 13:07:29 -0700 Message-ID: From: Matthew Fleming To: Hans Petter Selasky Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Cc: freebsd-current@freebsd.org, Weongyo Jeong , freebsd-usb@freebsd.org, freebsd-arch@freebsd.org Subject: Re: [RFC] Outline of USB process integration in the kernel taskqueue system X-BeenThere: freebsd-usb@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: FreeBSD support for USB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 01 Nov 2010 20:39:00 -0000 On Mon, Nov 1, 2010 at 12:54 PM, Hans Petter Selasky 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" >