tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Definitions of types also as macros

On Fri, Nov 09, 2018 at 01:41:35PM +0100, Kamil Rytarowski wrote:
 > >>  > I wanna do this, looks good?
 > >>
 > >> It should probably use double wings:
 > >>
 > >>  > -#ifndef	int8_t
 > >>  > +#ifndef	_BSD_INT8_T_
 > >>
 > >>    +#ifndef	__BSD_INT8_T__
 > > 
 > > In terms of namespace consumption, the single leading underscore
 > > followed by an uppercase letter as used here is sufficient.
 > We alredy use this syntax, eg. in <sys/timespec.h>:
 > #ifdef  _BSD_TIME_T_
 > typedef _BSD_TIME_T_    time_t;
 > #undef  _BSD_TIME_T_
 > #endif
 > (however here the ifdef is switched for some reason)

Those are older, and work differently. So looking the same isn't
necessarily a feature.

all of it ought to be retconned.

The basic problem is: according to standards, certain typedefs need to
be exposed by any of several headers but not others; and some typedefs
need to be accessible to headers that are not allowed to expose them.
(Crazy as that sounds.) However, any combination or order of #includes
must generate only one typedef as repeated typedefs anger the

To make life more exciting, some of these types are also
machine-dependent and most of them need to be shared between userland
and kernel.

The "correct" way to handle this (as in, the worked-out and tested way
based on twenty years of hindsight and having seen and tried various
other less successful ways) is:

(1) Create an exported kernel header, that is not part of any
user-facing API and that will never be, and put all the affected MI
types in it as typedefs with underscore prefixes (like __time_t).
This header file should define nothing outside of the implementation
namespace so it can be included freely anywhere.

(2) Create an exported MD kernel header, ditto, and put all the MD
types in it similarly, one for every port and/or one for every
machine. This header file can also be included freely anywhere.

(3) In all headers subject to namespace restrictions, which includes
most stuff shared between user and kernel, write the header itself
using only the underscore-prefix types. This makes these headers
compilable using only the private exported headers (1) and (2).

(4) For every group of types with a different set of exposure criteria
(there are not so many of these actually) create a header file, that
is not part of any user-facing API and will never be, that has a
conventional cpp guard against multiple inclusion, and put the
typedefs for the non-underscore prefixes of the types in the group in
this header. Include this header in each userland header that is
supposed to expose this group of types, and also in sys/types.h, which
is allowed/supposed to expose everything.

This covers all the standards requirements, minimizes the amount of
cutpaste, and avoids having unexpected #defines floating around
breaking builds. The only drawback is that it requires a place to put
header files that are not part of user-facing APIs, and in particular
such a place that can be shared user/kernel. We don't currently have
such a place in NetBSD.

It also is best used together with a kernel headers setup where shared
user/kernel headers are clearly separated from kernel internal
headers, to minimize the number of places where extra leading
underscores are needed and to keep it clear where those are. We also
don't have this in NetBSD.

This in turn should be fixed, and I have been threatening for years to
fix it once we get rename support in version control ... and maybe
we're finally getting near the point where tha'ts possible.

David A. Holland

Home | Main Index | Thread Index | Old Index