Date: Sun, 18 Mar 2007 07:44:25 +1100 (EST) From: Bruce Evans <bde@zeta.org.au> To: Jeff Roberson <jroberson@chesapeake.net> Cc: cvs-src@FreeBSD.org, Jeff Roberson <jeff@FreeBSD.org>, src-committers@FreeBSD.org, cvs-all@FreeBSD.org Subject: Re: cvs commit: src/sys/kern sched_ule.c Message-ID: <20070318065052.B39699@besplex.bde.org> In-Reply-To: <20070317110821.I560@10.0.0.1> References: <200703171813.l2HIDXWI008212@repoman.freebsd.org> <20070317110821.I560@10.0.0.1>
next in thread | previous in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20070318065052.B39699>