Module Name: src Committed By: riastradh Date: Mon Apr 20 15:19:00 UTC 2015
Modified Files: src/sys/sys: param.h Log Message: Fix C arithmetic quirks in roundup2 and avoid multiple evaluation. Add rounddown2. Discussed on tech-kern a while ago: https://mail-index.netbsd.org/tech-kern/2013/03/21/msg015131.html To generate a diff of this commit: cvs rdiff -u -r1.470 -r1.471 src/sys/sys/param.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/sys/param.h diff -u src/sys/sys/param.h:1.470 src/sys/sys/param.h:1.471 --- src/sys/sys/param.h:1.470 Mon Apr 13 21:32:04 2015 +++ src/sys/sys/param.h Mon Apr 20 15:18:59 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: param.h,v 1.470 2015/04/13 21:32:04 riastradh Exp $ */ +/* $NetBSD: param.h,v 1.471 2015/04/20 15:18:59 riastradh Exp $ */ /*- * Copyright (c) 1982, 1986, 1989, 1993 @@ -374,7 +374,25 @@ #endif #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) #define rounddown(x,y) (((x)/(y))*(y)) -#define roundup2(x, m) (((x) + (m) - 1) & ~((m) - 1)) + +/* + * Rounding to powers of two. The naive definitions of roundup2 and + * rounddown2, + * + * #define roundup2(x,m) (((x) + ((m) - 1)) & ~((m) - 1)) + * #define rounddown2(x,m) ((x) & ~((m) - 1)), + * + * exhibit a quirk of integer arithmetic in C because the complement + * happens in the type of m, not in the type of x. So if unsigned int + * is 32-bit, and m is an unsigned int while x is a uint64_t, then + * roundup2 and rounddown2 would have the unintended effect of clearing + * the upper 32 bits of the result(!). These definitions avoid the + * pitfalls of C arithmetic depending on the types of x and m, and + * additionally avoid multiply evaluating their arguments. + */ +#define roundup2(x,m) ((((x) - 1) | ((m) - 1)) + 1) +#define rounddown2(x,m) ((x) & ~((__typeof__(x))((m) - 1))) + #define powerof2(x) ((((x)-1)&(x))==0) /*