Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 26 Mar 2015 02:24:22 +1100 (EST)
From:      Bruce Evans <brde@optusnet.com.au>
To:        Hans Petter Selasky <hps@selasky.org>
Cc:        Emeric POUPON <emeric.poupon@stormshield.eu>, freebsd-net <freebsd-net@freebsd.org>, Adrian Chadd <adrian@freebsd.org>
Subject:   Re: Fragment questions
Message-ID:  <20150326005055.C3948@besplex.bde.org>
In-Reply-To: <5512BB1A.9070900@selasky.org>
References:  <522774578.25519037.1426765109046.JavaMail.zimbra@stormshield.eu> <550AC709.1050404@selasky.org> <2047974073.25663527.1426858267777.JavaMail.zimbra@stormshield.eu> <550C5FC6.6020401@selasky.org> <CAJ-Vmo=LkFc4sqbBSVeLE=7adV1nCuRDUO4ECUv8r6EYp=Oezw@mail.gmail.com> <550C6D65.6070409@selasky.org> <CAJ-Vmo=a6nzfRFH1cu0VefGk1opJf4WAt6u7ugT0uRMbjWvA-A@mail.gmail.com> <1776547746.25937476.1427189208729.JavaMail.zimbra@stormshield.eu> <5512BB1A.9070900@selasky.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 25 Mar 2015, Hans Petter Selasky wrote:

> On 03/24/15 10:26, Emeric POUPON wrote:
>> 
>> Please find attached a proposal using atomic_fetchadd.
> ...
> I think however we should define the code like a function, because the 
> htons() might be a macro, referring the input argument multiple times ...

htons() might be a macro, but then it must act like a function.  See
POSIX 2.1.1 "Use and Implementation of Functions" clauses 2-3.  In
particular, it must not evaluate its args more than once (clause 3).
These clauses copy the not so good wording of the C standard.  E.g.,
clause 3 also requires parenthesization of the args, but much more
than 2.1.1 specifies is required to replace a function by a macro.
Args must also be converted the same as a prototype would.  Casts to
do the conversions are not good enough, since casts should suppress
warnings for dubious conversions (e.g., htons(x) where x is a pointer)
while the more automatic conversions done by prototypes should warn.
2.1.1 cannot say that the macro implementation behaves identically,
since it the behaviour is slightly different.  It doesn't mention types
at all.  The closest it comes to requiring similar behaviour is just
"Any function declared in a header may also be implemented as a macro
defined in the header".  But this is impossible to implement a function
as a macro precisely, and 2.1.1 isn't very clear about which parts
must be precise (it mentions some parts that are imprecise).

POSIX's section about htons() (and most functions) is unclear about
this.  It says that "On some implementations, these functions [htons
family] are _defined_ as macros.  That is almost useless, since any
function may _also_ be _implemented_ as a macro.  It is unclear if
the possibility of being defined as a macro means that the function
version might not exist.  Actually, this is clear in the functions'
header.  For most functions, e.g., exit(), the wording is that
"The following functions shall be _declared_ as functions and may
also be defined as macros".  [Here it is unclear if _declared_ means
more than the declaration of a prototype.]  For the htons() family,
the wording for netinet/in.h is "The following shall either be
declared as functions, defined as macros, or both".

FreeBSD's htons() is careful about this.  The x86 version uses inline
functions to avoid multiple evaluation at the type level.  This also
accidentally gives the right level of warnings.

FreeBSD's man page gives no hints about this except the lower case name
of the APIs conventionally means that they are not unsafe macros.  It
describes the htons() family as "These routines".  Routines are unusual
in C and in man pages.  (In /usr/share/man/man3, there are about 80000
lines matching "function" and only 10000 matching "routine", with mist
of the latter in contribish places (lots in spam N-tuplicates from
libc/rpc.)

Bruce



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