Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 Nov 2011 14:37:02 +1100 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Warner Losh <imp@bsdimp.com>
Cc:        svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org, Hans Petter Selasky <hselasky@freebsd.org>
Subject:   Re: svn commit: r227749 - head/sys/kern
Message-ID:  <20111121134538.R1108@besplex.bde.org>
In-Reply-To: <229B993A-8F52-42B3-AE87-7DB4451AA9D0@bsdimp.com>
References:  <201111200836.pAK8aIEq082864@svn.freebsd.org> <229B993A-8F52-42B3-AE87-7DB4451AA9D0@bsdimp.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, 20 Nov 2011, Warner Losh wrote:

> Is this right?  Passing 0 to timo causes a panic?  That can't be good.

Because it reverses the natural order of conversations.

> On Nov 20, 2011, at 1:36 AM, Hans Petter Selasky wrote:

>> Log:
>>  Given that the typical usage of pause() is pause("zzz", hz / N), where N can
>>  be greater than hz in some cases, simply ignore a timeout value of zero.
>>
>>  Suggested by:	Bruce Evans
>>  MFC after:	1 week
>>
>> Modified:
>>  head/sys/kern/kern_synch.c
>>
>> Modified: head/sys/kern/kern_synch.c
>> ==============================================================================
>> --- head/sys/kern/kern_synch.c	Sun Nov 20 08:29:23 2011	(r227748)
>> +++ head/sys/kern/kern_synch.c	Sun Nov 20 08:36:18 2011	(r227749)
>> @@ -333,7 +333,7 @@ msleep_spin(void *ident, struct mtx *mtx
>> int
>> pause(const char *wmesg, int timo)
>> {
>> -	KASSERT(timo > 0, ("pause: timo must be > 0"));
>> +	KASSERT(timo >= 0, ("pause: timo must be >= 0"));
>>
>> 	/* silently convert invalid timeouts */
>> 	if (timo < 1)

I tried to get Hans to remove the KASSERT() and its panic in one of my
many reviews of changes to usb_pause() and pause(), but got confused in
my review of this commit.  I said that this commit restores the old
KASSERT() which gives panics for a timeout of 0, but it actually
completes changing the KASSERT() so that it doesn't give panics in this
case.  I got confused because the comments and the code are inconsistent
in different ways than before (and KASSERT() has its usual negative
logic complications):
- a previous comment says, verbosely, that "the timeout must be greater
   than zero"
- the previous KASSERT() requires, consisely, that "timo must be > 0".
   This was consistent with the comment.  The new KASSERT() is inconsistent
   with the comment.
- the "silently convert invalid timeouts" code, which was added on my
   request in the previous commit, was unreachable in all cases that it
   handles when INVARIANTS is configured.  Now it is reachable for timeouts
   of 0.  It remains unreachable for timeouts of < 0.  The verbose previous
   comment is not as verbose as this mail, so it doesn't describe all the
   cases.

timo isn't a function, so 0 can't be passed to it.  Passing a timeout of
0 to various functions has various behaviours:
- passing a timeout of 0 to msleep() is supported and means no timeout
   (= a timeout of infinity).  (Negative timeouts don't seem to be
   properly handled by msleep().  They are neither rejected not silently
   fixed up, but are passed on.)
- passing a timeout of 0 (or < 0) to callout_reset() makes no sense,
   but is not considered harmful enough the panic on.  It was silently
   fixed up to be a timeout of 1.
- passing a timeout of 0 (or < 0) to pause() makes no sense, but was
   considered to be harmful enough to panic on for a timeout of 0, while
   negative timeouts were just passed on.
     (pause()'s main comment says that it is like tsleep(), but it is
     really like DELAY().  Thus its timeout isn't really a (maximum)
     timeout, but is a (minimum) DELAY().  Another minor problem with
     the API or documentation is that it isn't clear if the caller is
     responsible for handling the implementation detail that pause(msg,
     1) only delays for a fractional tick iff it is implemented using
     tsleep(); the caller must ask for a "timeout" of of 2 if it wants
     a delay of strictly >= 1 tick.  Returning early is OK for a
     maximum timeout but not for a minimum delay.  Non-hardware callers
     probably don't care about getting a minimum, but usb callers do.
     usb_pause() has always adds 1 tick to handle this and rounding
     errors.)
   After Hans' first change, negative timeouts were considered harmful
   enough to panic on too.  I thought that this was silly, since pause()
   is unimportant compared with callout_reset() -- who cares if it is
   passed an invalid timeout? -- and asked him to change to the silent
   fixup used by callout_reset().  This is now done for timeouts of 0,
   but not for timeouts of < 0 in the INVARIANTS case (since the KASSERT()
   is still there for them).  Checking for timeouts of < 0 in pause() is
   getting close to checking for parity errors in the CPU in pause().
   msleep() is much more important, but never did either.

pause() grew some additional complications that I don't like.  Hans
noticed that DELAY(n) overflows for large n on arm.  So pause() now
avoids passing large n to DELAY().  Probably no other callers of
DELAY() do this, and no callers of pause() need large n for DELAY().

Why is top posting considered harmful?

Bruce



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