|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
From fb835651aff79a1e7fc5795086c9b26e59a8e6ca Mon Sep 17 00:00:00 2001
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
From: David Herrmann <dh.herrmann@gmail.com>
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
Date: Fri, 22 Aug 2014 14:41:37 +0200
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
Subject: [PATCH] shared: make container_of() use unique variable names
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
If you stack container_of() macros, you will get warnings due to shadowing
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
variables of the parent context. To avoid this, use unique names for
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
variables.
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
Two new helpers are added:
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
UNIQ: This evaluates to a truly unique value never returned by any
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
evaluation of this macro. It's a shortcut for __COUNTER__.
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
UNIQ_T: Takes two arguments and concatenates them. It is a shortcut for
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
CONCATENATE, but meant to defined typed local variables.
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
As you usually want to use variables that you just defined, you need to
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
reference the same unique value at least two times. However, UNIQ returns
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
a new value on each evaluation, therefore, you have to pass the unique
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
values into the macro like this:
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
#define my_macro(a, b) __max_macro(UNIQ, UNIQ, (a), (b))
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
#define __my_macro(uniqa, uniqb, a, b) ({
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
typeof(a) UNIQ_T(A, uniqa) = (a);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
typeof(b) UNIQ_T(B, uniqb) = (b);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
MY_UNSAFE_MACRO(UNIQ_T(A, uniqa), UNIQ_T(B, uniqb));
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
})
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
This way, MY_UNSAFE_MACRO() can safely evaluate it's arguments multiple
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
times as they are local variables. But you can also stack invocations to
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
the macro my_macro() without clashing names.
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
This is the same as if you did:
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
#define my_macro(a, b) __max_macro(__COUNTER__, __COUNTER__, (a), (b))
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
#define __my_macro(prefixa, prefixb, a, b) ({
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
typeof(a) CONCATENATE(A, prefixa) = (a);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
typeof(b) CONCATENATE(B, prefixb) = (b);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
MY_UNSAFE_MACRO(CONCATENATE(A, prefixa), CONCATENATE(B, prefixb));
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
})
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
...but in my opinion, the first macro is easier to write and read.
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
This patch starts by converting container_of() to use this new helper.
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
Other macros may follow (like MIN, MAX, CLAMP, ...).
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
---
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
src/shared/macro.h | 13 ++++++++-----
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
src/test/test-util.c | 19 +++++++++++++++++++
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
2 files changed, 27 insertions(+), 5 deletions(-)
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
diff --git a/src/shared/macro.h b/src/shared/macro.h
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
index 2807bc74e8..e6734804bd 100644
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
--- a/src/shared/macro.h
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+++ b/src/shared/macro.h
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
@@ -79,6 +79,9 @@
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
#define XCONCATENATE(x, y) x ## y
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
#define CONCATENATE(x, y) XCONCATENATE(x, y)
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+#define UNIQ_T(x, uniq) CONCATENATE(__unique_prefix_, CONCATENATE(x, uniq))
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+#define UNIQ __COUNTER__
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
/* Rounds up */
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
#define ALIGN4(l) (((l) + 3) & ~3)
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
@@ -122,13 +125,13 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) {
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
* @ptr: the pointer to the member.
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
* @type: the type of the container struct this is embedded in.
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
* @member: the name of the member within the struct.
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
- *
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
*/
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
-#define container_of(ptr, type, member) \
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+#define container_of(ptr, type, member) __container_of(UNIQ, (ptr), type, member)
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+#define __container_of(uniq, ptr, type, member) \
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
__extension__ ({ \
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
- const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
- (type *)( (char *)__mptr - offsetof(type,member) ); \
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
- })
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ const typeof( ((type*)0)->member ) *UNIQ_T(A, uniq) = (ptr); \
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ (type*)( (char *)UNIQ_T(A, uniq) - offsetof(type,member) ); \
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ })
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
#undef MAX
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
#define MAX(a,b) \
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
diff --git a/src/test/test-util.c b/src/test/test-util.c
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
index 4d9b28f9c8..795f3a1b3d 100644
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
--- a/src/test/test-util.c
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+++ b/src/test/test-util.c
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
@@ -96,6 +96,24 @@ static void test_max(void) {
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
assert_cc(MAXSIZE(char, long) == sizeof(long));
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
}
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+static void test_container_of(void) {
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ struct mytype {
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ uint8_t pad1[3];
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ uint64_t v1;
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ uint8_t pad2[2];
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ uint32_t v2;
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ } _packed_ myval = { };
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ assert_cc(sizeof(myval) == 17);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ assert_se(container_of(&myval.v1, struct mytype, v1) == &myval);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ assert_se(container_of(&myval.v2, struct mytype, v2) == &myval);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ assert_se(container_of(&container_of(&myval.v2,
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ struct mytype,
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ v2)->v1,
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ struct mytype,
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ v1) == &myval);
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+}
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
static void test_first_word(void) {
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
assert_se(first_word("Hello", ""));
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
assert_se(first_word("Hello", "Hello"));
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
@@ -1218,6 +1236,7 @@ int main(int argc, char *argv[]) {
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
test_streq_ptr();
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
test_align_power2();
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
test_max();
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
+ test_container_of();
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
test_first_word();
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
test_close_many();
|
|
Zbigniew Jędrzejewski-Szmek |
62fe94 |
test_parse_boolean();
|