Date: Wed, 1 Jun 2011 19:13:44 +1000 (EST) From: Bruce Evans <brde@optusnet.com.au> To: mdf@FreeBSD.org Cc: freebsd-hackers <freebsd-hackers@FreeBSD.org>, Bruce Evans <brde@optusnet.com.au> Subject: Re: sizeof(function pointer) Message-ID: <20110601183251.I1061@besplex.bde.org> In-Reply-To: <BANLkTimctcBWRrYVLyc-WLgePyCXqaPTGA@mail.gmail.com> References: <BANLkTimctcBWRrYVLyc-WLgePyCXqaPTGA@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 31 May 2011 mdf@FreeBSD.org wrote: > I am looking into potentially MFC'ing r212367 and related, that adds > drains to sbufs. The reason for MFC is that several pieces of new > code in CURRENT are using the drain functionality and it would make > MFCing those changes much easier. > > The problem is that r212367 added a pointer to a drain function in the > sbuf (it replaced a pointer to void). The C standard doesn't > guarantee that a void * and a function pointer have the same size, > though its true on amd64, i386 and I believe PPC. What I'm wondering > is, though not guaranteed by the standard, is it *practically* true > that sizeof(void *) == sizeof(int(*)(void)), such that an MFC won't > break binary compatibility for any supported architecture? (The Only on supported arches. > standard does guarantee, though not in words, that all function > pointers have the same size, since it guarantees that pointers to > functions can be cast to other pointers to functions and back without > changing the value). No, it doesn't guarantee that they have the same size. The casts may change inything in the representation including the size. In 1995 I added intfptr_t, uintfptr_t and fptrdiff_t to FreeBSD to handle this problem in the profil(2) APIs. You can check the MD definitions of these to verify that their size is always the same as the sizeof(void *). There are some style bugs and namespace issues with these. The definitions in /sys/*/include/_types.h are clean, but are mostly not used in their primary consumer /sys/*/include/profile.h. intfptr_t and uintfptr_t are bogusly declared for the kernel in a bogus declaration section in /sys/types.h. They are intentionally kept out of general headers, but even the kernel doesn't really need them there, unless they are used for more than profiling and then you might need them outside the kernel. > Another possibility is to malloc a blob that is sizeof(int(*)(void)) > and store that in a renamed s_unused; this is a bit messier but > guaranteed to work. I'd just rather the code be an MCF instead of a > partial re-write. It is only guaranteed to work if the value is converted to the actual function pointer type before use. (At least for use as a function pointer.) Someone pointed out that POSIX now requires function pointers to have the same representation as void *. This is a bug in POSIX IMO. It isn't in the 2001 version. I think POSIX had to do something for broken parts of dlcfn APIs. Hopefully this isn't required generally. Requiring all function pointers to be convertible to void * and back without breaking them is bad enough, but requiring the same representation is much more restrictive. It breaks any system that has type info in the pointers. The C standard is careful not to require this breakage even for data pointers. Someones pointed out that ia64 function pointers are actually handles. Systems that want to put type info in pointers would have to use handles instead of actual pointers to give the same representation, even if this is not the natural ABI. Whether handle values are useful when the data that they point to is unavailable is unclear. The profiling ABIs mainly need the function pointers (converted to integers) as ids, and handle values are hopefully enough for that. If not, the conversion needs to mangle the values sufficiently for uniqueness. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20110601183251.I1061>