Post by MousePost by MouseThere is a macro, historically ROUNDUP defined in various .c files,
RT_ROUNDUP in <net/route.h> in 5.1 and presumably later, [...]
So, I'm curious: does anyone know what this macro turned into on a
system with sizeof(long) not a power of two but with anything like
the BSD routing socket, if such a system exists?
http://lkml.org/lkml/2007/4/1/50
(a) That appears to be dealing with PCI support, not routing socket
support. It's the routing socket macro I'm curious about. (The
ROUND_UP macro being replaced does appear to assume the grain size
being rounded up to is a pwoer of two, so it's related, but since it
doesn't show the definition of the ALIGN it's being replaced with, the
message is pretty much content-free for my purposes.)
If you search for both macro names, you'll discover that this Milind Choudhary made a sweep through the Linux kernel, including PCI support, network drivers, and so forth. If the "not invented here" syndrome or whatever other reason means that you don't want to consider a change made in Linux, you'll even discover that it's used in APR-- see APR_ALIGN in include/apr_general.h:
#define APR_ALIGN(size, boundary) (((size) + ((boundary) - 1)) & ~((boundary) - 1))
Post by Mouse(b) The ROUND_UP macro affected by that patch is not the one used by
the routing socket code; it returns zero when passed zero, whereas the
routing socket's ROUNDUP / RT_ROUNDUP returns sizeof(long) when passed
zero.
I have reason to believe the NetBSD macro resembles:
#define RT_ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1) | ((n) - 1))) : (n))
#define RT_ROUNDUP(a) RT_ROUNDUP2((a), sizeof(uint64_t))
Passing a=0 to RT_ROUNDUP2 is already aligned, but the ternary ?: causes it to return the "n" or alignment boundary, you get sizeof(uint64_t) back. Whether that's the same as sizeof(long) depends on whether you are running an (I)LP64 platform or not, because RT_ROUNDUP always passes n=8 to RT_ROUNDUP2:
% cat m.c
#define APR_ALIGN(size, boundary) (((size) + ((boundary) - 1)) & ~((boundary) - 1))
#define RT_ROUNDUP2(a, n) ((a) > 0 ? (1 + (((a) - 1) | ((n) - 1))) : (n))
#define RT_ROUNDUP(a) RT_ROUNDUP2((a), sizeof(uint64_t))
#include <stdio.h>
int main() {
printf("align 0, sizeof(int): %ld\n", APR_ALIGN(0, sizeof(int)));
printf("align 0, sizeof(long): %ld\n", APR_ALIGN(0, sizeof(long)));
printf("align 2, sizeof(int): %ld\n", APR_ALIGN(2, sizeof(int)));
printf("align 2, sizeof(long): %ld\n", APR_ALIGN(2, sizeof(long)));
printf("align 4, sizeof(int): %ld\n", APR_ALIGN(4, sizeof(int)));
printf("align 4, sizeof(long): %ld\n", APR_ALIGN(4, sizeof(long)));
printf("align 8, sizeof(int): %ld\n", APR_ALIGN(8, sizeof(int)));
printf("align 8, sizeof(long): %ld\n", APR_ALIGN(8, sizeof(long)));
printf("rt_roundup2 0, sizeof(int): %ld\n", RT_ROUNDUP2(0, sizeof(int)));
printf("rt_roundup2 0, sizeof(long): %ld\n", RT_ROUNDUP2(0, sizeof(long)));
printf("rt_roundup2 2, sizeof(int): %ld\n", RT_ROUNDUP2(2, sizeof(int)));
printf("rt_roundup2 2, sizeof(long): %ld\n", RT_ROUNDUP2(2, sizeof(long)));
printf("rt_roundup2 4, sizeof(int): %ld\n", RT_ROUNDUP2(4, sizeof(int)));
printf("rt_roundup2 4, sizeof(long): %ld\n", RT_ROUNDUP2(4, sizeof(long)));
printf("rt_roundup2 8, sizeof(int): %ld\n", RT_ROUNDUP2(8, sizeof(int)));
printf("rt_roundup2 8, sizeof(long): %ld\n", RT_ROUNDUP2(8, sizeof(long)));
}
% cc -o m m.c && ./m
align 0, sizeof(int): 0
align 0, sizeof(long): 0
align 2, sizeof(int): 4
align 2, sizeof(long): 8
align 4, sizeof(int): 4
align 4, sizeof(long): 8
align 8, sizeof(int): 8
align 8, sizeof(long): 8
rt_roundup2 0, sizeof(int): 4
rt_roundup2 0, sizeof(long): 8
rt_roundup2 2, sizeof(int): 4
rt_roundup2 2, sizeof(long): 8
rt_roundup2 4, sizeof(int): 4
rt_roundup2 4, sizeof(long): 8
rt_roundup2 8, sizeof(int): 8
rt_roundup2 8, sizeof(long): 8
% cc -m32 -o m m.c && ./m
align 0, sizeof(int): 0
align 0, sizeof(long): 0
align 2, sizeof(int): 4
align 2, sizeof(long): 4
align 4, sizeof(int): 4
align 4, sizeof(long): 4
align 8, sizeof(int): 8
align 8, sizeof(long): 8
rt_roundup2 0, sizeof(int): 4
rt_roundup2 0, sizeof(long): 4
rt_roundup2 2, sizeof(int): 4
rt_roundup2 2, sizeof(long): 4
rt_roundup2 4, sizeof(int): 4
rt_roundup2 4, sizeof(long): 4
rt_roundup2 8, sizeof(int): 8
rt_roundup2 8, sizeof(long): 8
Post by Mouse(c) Your citing this in response to my question implies that Linux runs
on something with sizeof(long) not a power of two. Now I'm also
curious what CPU (and/or machine) that is.
A DEC PDP-7 had an 18-bit word size, and the PDP-10 had a 36-bit word size; I'm not sure you'll find anything much newer than that.
However, my reason for citing the above is that many variants of ROUNDUP / ROUND_UP are buggy, and reasoning about an address or size that might be rounded up or not, depending on whether it is already aligned (or not), or zero, etc leads to problems. (You also get problems when code using it moves from ILP32 to LP64, which is why I'm familiar with this macro and variants.)
Post by Mouseand it appears to assume 2's compliment arithmetic....
Well, two's complement (not "compliment") versus alternatives is
relevant only when dealing with negative values.
True, and "routing socket rouding?" should be "routing socket rounding?"
Many folks are more apt to fault others than they are to fault themselves for the same error.
Regards,
--
-Chuck
--
Posted automagically by a mail2news gateway at muc.de e.V.
Please direct questions, flames, donations, etc. to news-***@muc.de