Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1226064
| From | Michal Nazarewicz <mina86@mina86.com> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | [PATCH] kernel.h: make abs() work with 64-bit types |
| Date | 2015-09-16 15:00 +0200 |
| Message-ID | <q9ktA-4U2-15@gated-at.bofh.it> (permalink) |
| References | <q8MUV-6nq-5@gated-at.bofh.it> <q8MUW-6nq-13@gated-at.bofh.it> <q8QYy-3JQ-5@gated-at.bofh.it> <q98iL-4c5-27@gated-at.bofh.it> |
| Organization | http://mina86.com/ |
For 64-bit arguments, abs macro casts it to an int which leads to lost
precision and may cause incorrect results. To deal with 64-bit types
abs64 macro has been introduced but still there are places where abs
macro is used incorrectly.
To deal with the problem, expand abs macro such that it operates on s64
type when dealing with 64-bit types while still returning long when
dealing with smaller types.
Signed-off-by: Michal Nazarewicz <mina86@mina86.com>
---
include/linux/kernel.h | 45 ++++++++++++++++++++++++---------------------
1 file changed, 24 insertions(+), 21 deletions(-)
On Tue, Sep 15 2015, Linus Torvalds wrote:
> So I think the "auto-expand to 's64' using __builtin_choose_expr()" is
> the preferable model, and get rid of abs64() entirely. It has very few
> uses.
Compile tested (with ‘make allmodconfig && make bzImage modules’ on
x86_64) only.
The 32-bit case could be further ‘simplified’ with:
typeof(__builtin_choose_expr(sizeof(x) == sizeof(long), \
1L, 1)) __x = (x); \
(long)(__x < 0 ? -__x : __x);
but I don’t suppose the few saved lines (and hacker-cred ;) ) are worth
added confusion or risk of angry developer attacking me with a blunt
instrument after they had to debug the code for previous fortnight.
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 5582410..f985d16 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -200,28 +200,31 @@ extern int _cond_resched(void);
#define might_sleep_if(cond) do { if (cond) might_sleep(); } while (0)
-/*
- * abs() handles unsigned and signed longs, ints, shorts and chars. For all
- * input types abs() returns a signed long.
- * abs() should not be used for 64-bit types (s64, u64, long long) - use abs64()
- * for those.
+/**
+ * abs - return absolute value of an argument
+ * @x: the value. If it is unsigned type, it is converted to signed type first
+ * (s64, long or int depending on its size).
+ *
+ * Return: an absolute value of x. If x is 64-bit, macro's return type is s64,
+ * otherwise it is signed long.
*/
-#define abs(x) ({ \
- long ret; \
- if (sizeof(x) == sizeof(long)) { \
- long __x = (x); \
- ret = (__x < 0) ? -__x : __x; \
- } else { \
- int __x = (x); \
- ret = (__x < 0) ? -__x : __x; \
- } \
- ret; \
- })
-
-#define abs64(x) ({ \
- s64 __x = (x); \
- (__x < 0) ? -__x : __x; \
- })
+#define abs(x) __builtin_choose_expr(sizeof(x) == sizeof(s64), ({ \
+ s64 __x = (x); \
+ (__x < 0) ? -__x : __x; \
+ }), ({ \
+ long ret; \
+ if (sizeof(x) == sizeof(long)) { \
+ long __x = (x); \
+ ret = (__x < 0) ? -__x : __x; \
+ } else { \
+ int __x = (x); \
+ ret = (__x < 0) ? -__x : __x; \
+ } \
+ ret; \
+ }))
+
+/* Deprecated, use abs instead. */
+#define abs64(x) abs((s64)(x))
/**
* reciprocal_scale - "scale" a value into range [0, ep_ro)
--
2.6.0.rc0.131.gf624c3d
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
[RFC][PATCH 5/5] abs(): Provide build error on passing 64bit value to abs() John Stultz <john.stultz@linaro.org> - 2015-09-15 03:10 +0200
Re: [RFC][PATCH 5/5] abs(): Provide build error on passing 64bit value to abs() Ingo Molnar <mingo@kernel.org> - 2015-09-15 07:30 +0200
Re: [RFC][PATCH 5/5] abs(): Provide build error on passing 64bit value to abs() Linus Torvalds <torvalds@linux-foundation.org> - 2015-09-16 02:00 +0200
[PATCH] kernel.h: make abs() work with 64-bit types Michal Nazarewicz <mina86@mina86.com> - 2015-09-16 15:00 +0200
Re: [PATCH] kernel.h: make abs() work with 64-bit types John Stultz <john.stultz@linaro.org> - 2015-09-18 05:20 +0200
csiph-web