On Sat, 17 Mar 2007, Jeff Roberson wrote:

Any language lawyers care to comment on this?

Don't all C programmers know this? :)

On Sat, 17 Mar 2007, Jeff Roberson wrote:

jeff        2007-03-17 18:13:33 UTC

 FreeBSD src repository

 Modified files:
   sys/kern             sched_ule.c
 Log:
  - Cast the intermediate value in priority computtion back down to
unsigned char. Weirdly, casting the 1 constant to u_char still produces
    a signed integer result that is then used in the % computation.  This
    avoids that mess all together and causes a 0 pri to turn into 255 % 64
    as we expect.

- tdq_ridx has the dubious type u_char.  This may be good for saving space,
  but using unsigned types tends to give sign extension problems, and using
  types smaller than ints tends to waste time.
- pri = tdq->tdq_ridx also has type u_char.  Good -- otherwise you have to
  be concerned about conversions.
- the expression (pri - 1) has the int thanks to C90's broken value-preserving
  unsign extensions.  In any binary expression, both types get promoted to
  a common type that is at least as wide as int for integer expressions.
  (Surely C programmers know this?)  Broken value-preserving extension gives
  a common type of int.  Value pri = 0 is preserved.  Then subtraction gives
  the unwanted value of -1.  Sign-preserving extension would give a common
  type of u_int; value pri = 0 would be preserved, and subtraction of 1 would
  give a value of UINT_MAX.
- there should still have been no problem in the (previous) semi-final
  expression `(pri - 1) % RQ_NQS' since RQ_NQS is power of 2.  -1
  should equal UINT_MAX mod any power of 2 (> 2).  It actually gives
  -1 due to older C brokenness.  Before C99, the value of integer
  division and remainder on a negative numerator (assume a positive
  denominator for simplicity) was implementation defined.  Division
  may be rounded either towards zero or towards minus infinity.  The
  correct rounding is towards minus infinity so that the remainder is
  always between 0 and the numerator (>= 0, < numerator).  Most
  implementations follow the hardware and most hardware of course gets
  this wrong (*).  Thus -1 % 64 normally gives -1.  C99 "fixed" this by
  requiring incorrect rounding in all cases.  This -1 % 64 always gives
  -1.

(*) Rounding towards -infinity may be simplest for the hardware.  However,
it is more complicated for software implementations of remainder by a
power of 2.  gcc has to generate extra code to give the unwanted result
for `(pri - 1) % RQ_NQS'.  It can't just AND (pri -1) with 0x3F, but has
to do a sign test and adjust the result if (pri - 1 < 0).

Bruce
_______________________________________________
cvs-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/cvs-all
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to