From owner-svn-src-head@freebsd.org Sat Feb 20 04:42:15 2016 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 112CEAAD4F0; Sat, 20 Feb 2016 04:42:15 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from mail107.syd.optusnet.com.au (mail107.syd.optusnet.com.au [211.29.132.53]) by mx1.freebsd.org (Postfix) with ESMTP id 963B41368; Sat, 20 Feb 2016 04:42:14 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from c110-21-41-193.carlnfd1.nsw.optusnet.com.au (c110-21-41-193.carlnfd1.nsw.optusnet.com.au [110.21.41.193]) by mail107.syd.optusnet.com.au (Postfix) with ESMTPS id 2BDFED42917; Sat, 20 Feb 2016 15:13:45 +1100 (AEDT) Date: Sat, 20 Feb 2016 15:13:45 +1100 (EST) From: Bruce Evans X-X-Sender: bde@besplex.bde.org To: Justin Hibbits cc: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r295833 - head/sys/sys In-Reply-To: <201602200134.u1K1YDOD016555@repo.freebsd.org> Message-ID: <20160220142119.U1712@besplex.bde.org> References: <201602200134.u1K1YDOD016555@repo.freebsd.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed X-Optus-CM-Score: 0 X-Optus-CM-Analysis: v=2.1 cv=EfU1O6SC c=1 sm=1 tr=0 a=73JWPhLeruqQCjN69UNZtQ==:117 a=L9H7d07YOLsA:10 a=9cW_t1CCXrUA:10 a=s5jvgZ67dGcA:10 a=kj9zAlcOel0A:10 a=JL7xwK0kLOeRsF3iG-gA:9 a=CjuIK1q_8ugA:10 X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 20 Feb 2016 04:42:15 -0000 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