summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2014-12-29 17:51:36 +0100
committerDavid Herrmann <dh.herrmann@gmail.com>2014-12-30 01:39:01 +0100
commit180a60bc879ab0554297bc08a7a0b9274b119b55 (patch)
tree842c1afa088c3c26ce98856bcefde420dc6257c2 /src/shared
parent5ef378c1c5ba1a29a461e77685765da81163c853 (diff)
macro: add DIV_ROUND_UP()
This macro calculates A / B but rounds up instead of down. We explicitly do *NOT* use: (A + B - 1) / A as it suffers from an integer overflow, even though the passed values are properly tested against overflow. Our test-cases show this behavior. Instead, we use: A / B + !!(A % B) Note that on "Real CPUs" this does *NOT* result in two divisions. Instead, instructions like idivl@x86 provide both, the quotient and the remainder. Therefore, both algorithms should perform equally well (I didn't verify this, though).
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/macro.h11
1 files changed, 11 insertions, 0 deletions
diff --git a/src/shared/macro.h b/src/shared/macro.h
index 548294e47b..6a57428244 100644
--- a/src/shared/macro.h
+++ b/src/shared/macro.h
@@ -197,6 +197,17 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
UNIQ_T(X,xq); \
})
+/* [(x + y - 1) / y] suffers from an integer overflow, even though the
+ * computation should be possible in the given type. Therefore, we use
+ * [x / y + !!(x % y)]. Note that on "Real CPUs" a division returns both the
+ * quotient and the remainder, so both should be equally fast. */
+#define DIV_ROUND_UP(_x, _y) \
+ __extension__ ({ \
+ const typeof(_x) __x = (_x); \
+ const typeof(_y) __y = (_y); \
+ (__x / __y + !!(__x % __y)); \
+ })
+
#define assert_se(expr) \
do { \
if (_unlikely_(!(expr))) \