Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Nov 2015 04:50:52 +1100 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Conrad Meyer <cem@freebsd.org>
Cc:        Hans Petter Selasky <hps@selasky.org>, Ian Lepore <ian@freebsd.org>,  src-committers@freebsd.org, svn-src-all@freebsd.org,  svn-src-head@freebsd.org
Subject:   Re: svn commit: r290613 - head/sys/compat/linuxkpi/common/include/linux
Message-ID:  <20151111033555.P2914@besplex.bde.org>
In-Reply-To: <CAG6CVpWeVVZmkyPOK2RbhC285LfGmyGbS=51qF6g9cNSSFxn%2BA@mail.gmail.com>
References:  <201511091650.tA9Gog7d061645@repo.freebsd.org> <20151110080516.M4088@besplex.bde.org> <5641A056.2040805@selasky.org> <1447168083.91061.2.camel@freebsd.org> <CAG6CVpWeVVZmkyPOK2RbhC285LfGmyGbS=51qF6g9cNSSFxn%2BA@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 10 Nov 2015, Conrad Meyer wrote:

> On Tue, Nov 10, 2015 at 7:08 AM, Ian Lepore <ian@freebsd.org> wrote:
>> On Tue, 2015-11-10 at 08:44 +0100, Hans Petter Selasky wrote:
>>>> -sysctl_root_handler_locked(struct sysctl_oid *oid, void *arg1,
>>>> intptr_t arg2,
>>>> +sysctl_root_handler_locked(struct sysctl_oid *oid, void *arg1,
>>>> intmax_t arg2,
>>>>      struct sysctl_req *req, struct rm_priotracker *tracker)
>>>
>>> Given that the second argument is sometimes used for pointers, maybe
>>> we
>>> should keep it intptr_t. Or add a compile time assert that
>>> sizeof(intmax) >=3D sizeof(intptr_t) which I think doesn't hold?
>>
>> If intmax_t is the "maximum width integer type" and intptr_t is
>> "integer type capable of holding a pointer", I think by definition
>> sizeof(intmax_t) must be >=3D sizeof(intptr_t).

intmax_t isn't the "maximum width integer type".  It is a "signed integer
type capable of representing any value of any signed integer type (includin=
g
extended ones).  This imples that INTMAX_MAX >=3D INTPTR_MAX but not that
sizeof(intmax_t) >=3D sizeof(intptr_t) or that
rankof(intmax_t) >=3D rankof(intptr_t).  intptr_t may have more padding bit=
s
than intmax_t.  In FreeBSD, rankof(intmax_t) >=3D rankof(intptr_t), but
rankof(intmax_t) doesn't have maximum rank.  It is smaller than the long
long abomination in rank on all 64-bit arches  All arches declare intmax_t
as int64_t, and this has to be long_long_abomination_t on 32-bit arches
(except I made it a magic gcc type in old versions of FreeBSD and C where
long long was a syntax error), but intmax_t is always plain long on 64
bit arches.  In terms of rank, intptr_t =3D=3D int64_t =3D=3D intmax_t <
long_long_abomination_t on 64-bit arches, and
intptr_t < int64_t =3D=3D intmax_t =3D=3D long_long_abomination_t on 32-bit=
 arches.

>> On the other hand, given
>> the perverse way standards-writers think, I'm not sure "big enough" is
>> all it takes to qualify as "capable of holding a pointer".  But I think
>> in reality it'll work out right anyway.

Only on vaxes, unless you write correct code.  E.g., consider the following
reasonable implementation:
- pointers have 64 bits, consisting of 32 high address bits and 32 low
   low type bits
- the type bits for void have value 1=20
- intmax_t is also 64 bits
- intptr_t is 32 bits (the type bits need not be represented because they
   are always 1)
- conversion from void * to intmax_t then can and should be to copy all
   the bits.  The void * pointer kernbase with bits 0xc000000000000001
   gives the same bit when converted to intmax_t.  The reversion conversion
   also copies the bits.
- conversion from void * to intmax_t must reduce to 32 bits.  It can and
   should do this in the obvious way by discarding the low type bits and
   shifting the top bits to the low bits.  The kernbase becomes
   0xc00000000 when converted to intptr_t.  The reverse conversion shifts
   the addres bits back and sets the type bits to their known value for
   void *.
Then wrong code breaks nicely.  (intptr_t)(intmax_t)kernbase gives 1
and there is obviously no way to convert this back to kernbase.  To
use intmax_t for kernbase, you have write (intmax_t)(intptr_t)kernbase.
This has value 0xc0000000.  Then to get back to void *, first cast
back to intptr_t.

Qualified pointers to void are required to work too.  In the above
implementation, they should have different type bits and some only
difference is that casting back must restore different type bits.
Conversions of other pointers are not required to work, but would
work accidentally.  All the type info needed to recover the original
type bits is in the cast back (provided it is really back to the same
type).

> +1 to what Ian said.
>
> In any C99 implementation where intptr_t is defined, I believe
> intmax_t must be at least as big.  See =C2=A7 7.18.1.5, "Greatest-width
> integer types," and =C2=A7 7.18.1.4, "Integer types capable of holding
> object pointers."
>=20
>> The following type designates a signed integer type with the property th=
at any valid pointer to void can be converted to this type, then converted =
back to pointer to void, and the result will compare equal to the original =
pointer: intptr_t

Note that it only requires working when the conversion is to this type.
Any conversion from a pointer to int may involve some reduction or
reordering of the bits.  The conversion might depend on the type of
both the integer and the pointer in more complicated ways than the
above.  The requirement that the conversions are not required to work
for all "large enough" types makes things simpler for everyone.

>> The following type designates a signed integer type capable of represent=
ing any value of any signed integer type: intmax_t
>
> Given that intptr_t exists in our implementation and is a signed
> integer type, I see no reason why intmax_t could possibly not
> represent any such value.  Same argument for the unsigned variants.

It can only represent integers directly.  intptr_t is only required to
represent pointers with some unique encoding.  Other integer types are
only required to represent (via conversion) pointers with some encoding.
The encoding is not required to be unique.  0 for everything is a valid
encoding and might be used to detect bugs or just accidentally for
optimization.

Bruce
From owner-svn-src-all@freebsd.org  Tue Nov 10 18:23:14 2015
Return-Path: <owner-svn-src-all@freebsd.org>
Delivered-To: svn-src-all@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 7A954A2B4C0;
 Tue, 10 Nov 2015 18:23:14 +0000 (UTC)
 (envelope-from brde@optusnet.com.au)
Received: from mail109.syd.optusnet.com.au (mail109.syd.optusnet.com.au
 [211.29.132.80])
 by mx1.freebsd.org (Postfix) with ESMTP id 370561B4E;
 Tue, 10 Nov 2015 18:23:13 +0000 (UTC)
 (envelope-from brde@optusnet.com.au)
Received: from c211-30-166-197.carlnfd1.nsw.optusnet.com.au
 (c211-30-166-197.carlnfd1.nsw.optusnet.com.au [211.30.166.197])
 by mail109.syd.optusnet.com.au (Postfix) with ESMTPS id CEBC4D641AE;
 Wed, 11 Nov 2015 05:23:05 +1100 (AEDT)
Date: Wed, 11 Nov 2015 05:23:04 +1100 (EST)
From: Bruce Evans <brde@optusnet.com.au>
X-X-Sender: bde@besplex.bde.org
To: Justin Hibbits <jrh29@alumni.cwru.edu>
cc: cem@freebsd.org, Hans Petter Selasky <hps@selasky.org>, 
 Ian Lepore <ian@freebsd.org>, src-committers <src-committers@freebsd.org>, 
 "svn-src-all@freebsd.org" <svn-src-all@freebsd.org>, 
 "svn-src-head@freebsd.org" <svn-src-head@freebsd.org>
Subject: Re: svn commit: r290613 -
 head/sys/compat/linuxkpi/common/include/linux
In-Reply-To: <CAHSQbTCh3ExHQ1aCDoGwDaiUeEbr-vP5QimZOO4Nqw=Fio-Vkg@mail.gmail.com>
Message-ID: <20151111051325.S3235@besplex.bde.org>
References: <201511091650.tA9Gog7d061645@repo.freebsd.org>
 <20151110080516.M4088@besplex.bde.org> <5641A056.2040805@selasky.org>
 <1447168083.91061.2.camel@freebsd.org>
 <CAG6CVpWeVVZmkyPOK2RbhC285LfGmyGbS=51qF6g9cNSSFxn+A@mail.gmail.com>
 <CAHSQbTCh3ExHQ1aCDoGwDaiUeEbr-vP5QimZOO4Nqw=Fio-Vkg@mail.gmail.com>
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=cK4dyQqN c=1 sm=1 tr=0
 a=KA6XNC2GZCFrdESI5ZmdjQ==:117 a=PO7r1zJSAAAA:8 a=JzwRw_2MAAAA:8
 a=kj9zAlcOel0A:10 a=6I5d2MoRAAAA:8 a=8_tSZztaHGgigfQZgVQA:9
 a=CjuIK1q_8ugA:10
X-BeenThere: svn-src-all@freebsd.org
X-Mailman-Version: 2.1.20
Precedence: list
List-Id: "SVN commit messages for the entire src tree \(except for &quot;
 user&quot; and &quot; projects&quot; \)" <svn-src-all.freebsd.org>
List-Unsubscribe: <https://lists.freebsd.org/mailman/options/svn-src-all>,
 <mailto:svn-src-all-request@freebsd.org?subject=unsubscribe>
List-Archive: <http://lists.freebsd.org/pipermail/svn-src-all/>;
List-Post: <mailto:svn-src-all@freebsd.org>
List-Help: <mailto:svn-src-all-request@freebsd.org?subject=help>
List-Subscribe: <https://lists.freebsd.org/mailman/listinfo/svn-src-all>,
 <mailto:svn-src-all-request@freebsd.org?subject=subscribe>
X-List-Received-Date: Tue, 10 Nov 2015 18:23:14 -0000

On Tue, 10 Nov 2015, Justin Hibbits wrote:

> On Tue, Nov 10, 2015 at 9:42 AM, Conrad Meyer <cem@freebsd.org> wrote:
>> ...
>> Given that intptr_t exists in our implementation and is a signed
>> integer type, I see no reason why intmax_t could possibly not
>> represent any such value.  Same argument for the unsigned variants.
>
> I may be wrong on this, but I *think* uintptr_t/intptr_t are required
> to be *precisely* the same size as a pointer, which explains why you
> can't cast directly from uintmax_t on 32-bit architectures.

Good compilers use the size for a simple portability check.  They
should also complain if the types are different but have the same size,
as is done for int vs long format mismatches on i386.

Bruce



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