Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 12 Dec 2011 11:13:49 -0800
From:      mdf@FreeBSD.org
To:        John Baldwin <jhb@freebsd.org>
Cc:        usb@freebsd.org, freebsd-hackers@freebsd.org, hackers@freebsd.org, Andriy Gapon <avg@freebsd.org>, Hans Petter Selasky <hselasky@c2i.net>
Subject:   Re: kern_yield vs ukbd_yield
Message-ID:  <CAMBSHm-AsLFXYWtdDavsEruZUp_R2sVSzm3_Bo3CowWZLJwGWA@mail.gmail.com>
In-Reply-To: <201112121405.38322.jhb@freebsd.org>
References:  <4EE51CB5.1060505@FreeBSD.org> <CAMBSHm_ChT5X1bhE3oLNiRJPf4LZ5OmmxthjTXxbE2kJNxOyTw@mail.gmail.com> <201112121658.22864.hselasky@c2i.net> <201112121405.38322.jhb@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, Dec 12, 2011 at 11:05 AM, John Baldwin <jhb@freebsd.org> wrote:
> On Monday, December 12, 2011 10:58:22 am Hans Petter Selasky wrote:
>> On Monday 12 December 2011 16:55:38 mdf@freebsd.org wrote:
>> > On Mon, Dec 12, 2011 at 12:03 AM, Andriy Gapon <avg@freebsd.org> wrote=
:
>> > > on 11/12/2011 23:48 mdf@FreeBSD.org said the following:
>> > >> On Sun, Dec 11, 2011 at 1:12 PM, Andriy Gapon <avg@freebsd.org> wro=
te:
>> > >>> Does the following change do what I think that it does?
>> > >>> Thank you!
>> > >>>
>> > >>> Author: Andriy Gapon <avg@icyb.net.ua>
>> > >>> Date: =A0 Thu Sep 1 16:50:13 2011 +0300
>> > >>>
>> > >>> =A0 =A0ukbd: drop local duplicate of kern_yield and use that inste=
ad
>> > >>>
>> > >>> diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c
>> > >>> index 086c178..8078cbb 100644
>> > >>> --- a/sys/dev/usb/input/ukbd.c
>> > >>> +++ b/sys/dev/usb/input/ukbd.c
>> > >>> @@ -399,33 +399,6 @@ ukbd_put_key(struct ukbd_softc *sc, uint32_t =
key)
>> > >>> =A0}
>> > >>>
>> > >>> =A0static void
>> > >>> -ukbd_yield(void)
>> > >>> -{
>> > >>> - =A0 =A0 =A0 struct thread *td =3D curthread;
>> > >>> - =A0 =A0 =A0 uint32_t old_prio;
>> > >>> -
>> > >>> - =A0 =A0 =A0 DROP_GIANT();
>> > >>> -
>> > >>> - =A0 =A0 =A0 thread_lock(td);
>> > >>> -
>> > >>> - =A0 =A0 =A0 /* get current priority */
>> > >>> - =A0 =A0 =A0 old_prio =3D td->td_base_pri;
>> > >>> -
>> > >>> - =A0 =A0 =A0 /* set new priority */
>> > >>> - =A0 =A0 =A0 sched_prio(td, td->td_user_pri);
>> > >>> -
>> > >>> - =A0 =A0 =A0 /* cause a task switch */
>> > >>> - =A0 =A0 =A0 mi_switch(SW_INVOL | SWT_RELINQUISH, NULL);
>> > >>> -
>> > >>> - =A0 =A0 =A0 /* restore priority */
>> > >>> - =A0 =A0 =A0 sched_prio(td, old_prio);
>> > >>> -
>> > >>> - =A0 =A0 =A0 thread_unlock(td);
>> > >>> -
>> > >>> - =A0 =A0 =A0 PICKUP_GIANT();
>> > >>> -}
>> > >>> -
>> > >>> -static void
>> > >>> =A0ukbd_do_poll(struct ukbd_softc *sc, uint8_t wait)
>> > >>> =A0{
>> > >>>
>> > >>> @@ -439,7 +412,7 @@ ukbd_do_poll(struct ukbd_softc *sc, uint8_t wa=
it)
>> > >>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0while (sc->sc_inputs =3D=3D 0) {
>> > >>>
>> > >>> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* give USB threads=
 a chance to run */
>> > >>> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ukbd_yield();
>> > >>> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 kern_yield(-1);
>> > >>
>> > >> Not quite.
>> > >>
>> > >> 1) -1 should be spelled PRI_UNCHANGED, except ukbd_yield() uses
>> > >> td_user_pri, but then puts it back again, so I think UNCHANGED is w=
hat
>> > >> is meant.
>> > >> 2) kern_yield() calls it a SW_VOL rather than SW_INVOL, which seems
>> > >> the desired behaviour here anyways, since this is an explicit (i.e.
>> > >> voluntary) yield.
>> > >
>> > > Thank you for the explanation. =A0So would you say that the patch is=
 OK?
>> >
>> > As far as I know, yes. =A0There may be a difference in behaviour,
>> > though, while yielding, if the priority of the thread remains high (as
>> > this change would make it) -- I'm not completely sure how the
>> > scheduler chooses threads, because I'm pretty sure I've seen it take
>> > threads with lower (higher numbered) priorities even when there's
>> > runnable threads with a higher (lower numbered) priority available.
>
> The scheduler generally should not do this with the following exceptions:
>
> =A01) for timesharing threads, priorities are in bands, so effectively th=
e
> =A0 =A0pri / 4 is what is used for comparison and if two threads have the=
 same
> =A0 =A0pri / 4 the scheduler will round-robin among htem.
>
> =A02) ULE might be a bit different because of the way it assigns threads =
to
> =A0 =A0CPUs, so if a CPU has two high priority threads and another CPU on=
ly
> =A0 =A0has a low priority thread, the second CPU will not run the second =
high
> =A0 =A0priority thread. =A04BSD handles this case more correctly.
>
>> > It has always seemed weird to me that the priorities in the kernel are
>> > strictly higher than user-space -- but only after a prio change like
>> > that done implicitly by many of the calls to sleep(9). =A0So it may be
>> > that the better patch is to use PRI_USER, not PRI_UNCHANGED, which
>> > would revert any potentially changed thread prio (e.g. due to a
>> > sleep(9)) back to its user-space level, so that it contended as
>> > expected with other threads.
>
> Realtime priorities (for rtprio user threads) are higher than the kernel
> "sleep" priorities. =A0Also, keep in mind that a thread does not get an
> automatic priority boost when it enters the kernel. =A0It only gets a boo=
st
> either temporarily from priority propagation, or a slightly longer (but
> still temporary) boost from a sleep(9) call.

I still don't understand why threads are boosting their priority while
sleeping; if it's so they are woken preferentially, that makes some
sense, but then they shouldn't be keeping the boosted priority after
the thread is woken.  If a thread really needs higher priority to do
its work, that should be an explicit call to sched_prio(9), rather
than implicitly only when/if it first sleeps.

Thanks,
matthew


>> > hselasky@ or someone else familiar with the various usb threads would
>> > have to answer that.
>>
>> The problem is only during init() where the init thread has highest prio=
rity
>> and that doesn't allow other threads to run even if the scheduler is
> running!
>
> Hmm, that should be fixed by lowering the relevant thread's priority.
> Do you mean thread0 (the one doing all the SYSINIT's or thread we create =
for
> init (pid 1) before it executes init?
>
> --
> John Baldwin



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