Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 20 Feb 2016 15:13:45 +1100 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Justin Hibbits <jhibbits@freebsd.org>
Cc:        src-committers@freebsd.org, svn-src-all@freebsd.org,  svn-src-head@freebsd.org
Subject:   Re: svn commit: r295833 - head/sys/sys
Message-ID:  <20160220142119.U1712@besplex.bde.org>
In-Reply-To: <201602200134.u1K1YDOD016555@repo.freebsd.org>
References:  <201602200134.u1K1YDOD016555@repo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Sat, 20 Feb 2016, Justin Hibbits wrote:

> Log:
>  Fix the definition of RM_MAX_END.
>
>  Even though casting from signed to unsigned is well-defined in C, it's better to
>  first cast to the larger unsigned type, then negate.

Casting ~0 is well-defined, but ~0 isn't.

The operation is complementation, not negation.

> Modified: head/sys/sys/rman.h
> ==============================================================================
> --- head/sys/sys/rman.h	Sat Feb 20 01:32:58 2016	(r295832)
> +++ head/sys/sys/rman.h	Sat Feb 20 01:34:13 2016	(r295833)
> @@ -61,7 +61,7 @@ enum	rman_type { RMAN_UNINIT = 0, RMAN_G
>  */
> #define RM_TEXTLEN	32
>
> -#define	RM_MAX_END	((rman_res_t)~0)
> +#define	RM_MAX_END	(~(rman_res_t)0)

If the operation were negation, then its result -0 would actually be well-
defined.  It would be 0 again, even in the 1's complement and signed
magnitude cases where -0 can be represented.  -0 cast to unsigned must
give 0 again, and not be all-bits-1 even if it started as all-bits 1
representing -0 in 2's complement.

~0 was under-specified in C90 as being the bitwise complement.  The value
of that is not specified unless the promotion of the orginal type is
unsigned (~(unsigned char)0 is also not specified except on exotic
machines (no longer permitted by POSIX) with unsigned char the same size
as unsigned int).

~0 is even more under-specified in C99 because C99 is more careful
with representations and has trap representations.  (This is not fixed
in C11.) Complementing a non- trap-representation might give a trap
representation if done bitwise, even starting from a nondescript value
like 0.  But if there are no trap or padding bits, the only reasonable
interpretation of the spec is that ~0 gives all-bits-1 with whatever
value that has.  In the 2's complement case, the value is -1 and casting
this to unsigned works right.  In the 1's complement case, the value
is -0 and casting this to unsigned gives unsigned plain 0.  In the
signed-magnitude case, I think it gives -0x7fffffff with 32-bit ints
and casting this to unsigned gives 0x80000001.  C90 allows other
representations, so the result can be anything.

The clearest way to write the expression is probably ((rman_res_t)-1)
like the buggy ~0 version did in the 2's complement case.

Everyone knows what -1 is.  Conversion of -1 to unsigned is better
known than what ~0 is.  It takes an explicit specification for both.

Conversion of -1 involves "[in extra precision] repeatedly adding or
subtracting one more than the maximim value that can be represented
in the new type until [the result is representable]".  Thus
((rman_res_t)-1) is maxof(rman_res_t) + 1 - 1 == maxof(rman_res_t).

(~(rman_res_t)0) involves the specification of the '~' operator
saying that complementing the bits actually works for the unsigned
case.  The precise wording is "If the promoted type [of E] is an
unsigned type, then the expression ~E is equivalent to the maximum
value representable in that type minus E".  Thus (~(rman_res_t)0)
is maxof(rman_res_t) - 0 = maxof(rman_res_t).  I think the precise
wording is redundant, but this is not clear.  Something is needed
to ensure that complementing bits doesn't give a trap representation
for the unsigned case.  Complementing only value bits wouldn't give
a trap representation, but complementing padding bits could (should)
give a trap representation.  The spec is too fuzzy to say which bits
are complemented, except in the unsigned case padding bits must not
be complemented if this would give a trap representation.

Bruce



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