kern_yield vs ukbd_yield

Hans Petter Selasky hselasky at c2i.net
Sat Dec 17 17:09:17 UTC 2011


On Saturday 17 December 2011 15:57:24 Andriy Gapon wrote:
> on 16/12/2011 01:16 Hans Petter Selasky said the following:
> > I think I was not aware about the Giant locking maybe having something to
> > do about this. I was just thinking about this recently, that syscons and
> > all keyboard stuff, currently is Giant locked. Scary?
> 
> Nope :-)
> I think that no syscons + keyboards code depends on the special properties
> of the Giant, most likely with the prominent exception of the ukbd.
> Also, the Giant is almost never acquired explicitly (again with the
> prominent exception of the ukbd), which actually leads to a consequence
> that no lock is acquired in the context where the kernel polls for input. 
> Which is a good thing if we keep in mind that the kernel may poll for
> input in the context like panic or ddb where any lock may be already held
> by a thread that is not able to run.
> 
> > I can always become better writing commit messages! What is your plan
> > forward then with regard to the Giant lock problem?
> > 
> > If one thread is like:
> > 
> > while (1)
> > {
> > lock(Giant);
> > c = get nonblocking key from console();
> > unlock(Giant);
> > }
> > 
> > And the other is like:
> > 
> > if (callback complete) {
> > lock(Giant);
> > run callback();
> > unlock(Giant);
> > }
> > 
> > Who gets to run?
> 

Hi,

> First, there is no need to acquire the Giant in the first snippet.
> Second, "get nonblocking key from console" should not depend on the
> callback in a parallel thread.  The polling routine should go all the way
> to hardware if needed.

It can do that. This feature is usually only used in panic mode.

> 
> I see where all the complications in ukbd code come from.  I think that
> they started as attempts to work around the current stupid behavior of
> syscons during polling:
> do {
> 	kbd_poll_enter();
> 	try_to_get_one_char();
> 	kbd_poll_exit();
> } while (!got_a_char);
> For ukbd this means ugly races between the polling thread and the usb
> threads at the mountroot stage.  And so you had to invent "polling
> autodetection" and add extra locking.  But that lead to troubles in the
> contexts where no lock was previously held.  And so on.  So now ukbd
> resembles a big collection of hacks and crotches.

Right! You got it!

> 
> For example consider the following scenario which does not occur very
> frequently in reality, but is quite possible.  Thread T1 on CPU P1 holds
> the Giant, at the same time thread T2 on CPU P2 enters ddb.  That means
> that T1 is "frozen" and won't be able to release Giant.  ddb would try to
> interact with an operator and there would be a call-chain like this:
> ukbd_check_char
> scgetc
> sc_cngetc
> cncheckc
> cngetc
> db_readline
> ...
> 
> And now the code in ukbd to which I referred above:
> /* check if char is waiting */
> static int
> ukbd_check_char(keyboard_t *kbd)
> {
>         struct ukbd_softc *sc = kbd->kb_data;
> 
>         if (!KBD_IS_ACTIVE(kbd))
>                 return (0);
> 
>         if (sc->sc_flags & UKBD_FLAG_POLLING) {
>                 if (!mtx_owned(&Giant)) {
>                         /* XXX cludge */
>                         int retval;
>                         mtx_lock(&Giant);
>                         retval = ukbd_check_char(kbd);
>                         mtx_unlock(&Giant);
>                         return (retval);
> 
> So we are in a polling mode and Giant is not owned by us (T2) because it is
> owned by T1 and so mtx_lock would be called and then we would probably get
> into a recursion via mi_switch and kdb_reenter.

That's true!

If the problem is only in UKBD driver, I don't think this is a big problem to 
solve. The reason for the auto-magic locking, is that I've sometimes seen 
callers in non-polling mode call into UKBD without Giant locked. And this 
causes a panic when starting USB transfers, because the code expects Giant to 
be locked.

Requirement: I would say that to use UKBD polling mode, the scheduler must be 
stopped. Else you should not use polling mode at all. I think that mountroot 
is getting characters the wrong way in this regard.

--HPS


More information about the freebsd-hackers mailing list