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)
 
 /*

Reply via email to