11/*
2- * struct - Offset of & Container of macros
2+ * _offset_of & _container_of macros
3+ * =================================
34 *
4- * Refer
5+ * Access a container using its member.
6+ *
7+ * Refer:
58 *
69 * https://stackoverflow.com/a/39805594
710 * https://radek.io/posts/magical-container_of-macro/
811 * https://www.kernel.org/doc/Documentation/driver-model/design-patterns.txt
912 */
1013
11- #include <stdio.h>
12- #include <stdlib.h>
14+ #include "tests.h"
1315
1416/* ===========================================================================
1517 * Macro implementations
1618 * ===========================================================================
1719 */
1820// also defined in stddef.h
1921// clang-format off
20- #define offsetof (st , m ) ((size_t) &((st *)0)->m)
22+ #define _offset_of (st , m ) ((size_t) &((st *)0)->m)
2123// clang-format on
2224
23- #define container_of (ptr , type , member ) \
25+ #define _container_of (ptr , type , member ) \
2426 ({ \
2527 const typeof(((type *)0)->member) *__mptr = (ptr); \
26- (type *)((char *)__mptr - offsetof (type, member)); \
28+ (type *)((char *)__mptr - _offset_of (type, member)); \
2729 })
2830
2931/* ===========================================================================
@@ -41,14 +43,13 @@ struct task_struct {
4143 int flags ;
4244};
4345
44- static inline void list_add_tail (struct list_head * new ,
45- struct list_head * head )
46+ void _list_append (struct list_head * head , struct list_head * node )
4647{
4748 struct list_head * last = head -> prev ;
48- new -> next = head ;
49- new -> prev = last ;
50- last -> next = new ;
51- head -> prev = new ;
49+ node -> next = head ;
50+ node -> prev = last ;
51+ last -> next = node ;
52+ head -> prev = node ;
5253}
5354
5455#define list_for_each (pos , head ) \
@@ -69,92 +70,28 @@ void get_task_states(int *a)
6970 task3 .state = 3 ;
7071
7172 // Add tasks to list
72- list_add_tail ( & task1 . tasks , & task_list );
73- list_add_tail ( & task2 . tasks , & task_list );
74- list_add_tail ( & task3 . tasks , & task_list );
73+ _list_append ( & task_list , & task1 . tasks );
74+ _list_append ( & task_list , & task2 . tasks );
75+ _list_append ( & task_list , & task3 . tasks );
7576
7677 // Iterate over tasks
7778 int i = 0 ;
7879 struct list_head * curr = NULL ;
7980 list_for_each (curr , & task_list )
8081 {
8182 struct task_struct * task =
82- container_of (curr , struct task_struct , tasks );
83+ _container_of (curr , struct task_struct , tasks );
8384 a [i ++ ] = task -> state ;
8485 }
8586}
8687
87- /* ===========================================================================
88- * Test helpers
89- * ===========================================================================
90- */
91- #define array_size (a ) (sizeof(a) / sizeof(a[0]))
92-
93- #define fii (n ) for (int i = 0; i < (n); i++)
94-
95- static int check_eq_n (int * l , int * r , int n )
96- {
97- fii (n ) {
98- if (l [i ] != r [i ]) return 0 ;
99- }
100- return 1 ;
101- }
102-
103- static void _a2s (int * a , int n , char * b )
104- {
105- int l = 0 , f = 1 ;
106- b [l ++ ] = '{' ;
107- fii (n ) {
108- l += sprintf (& b [l ], "%s%d" , (f ? "" : ", " ), a [i ]);
109- f = 0 ;
110- }
111- b [l ++ ] = '}' ;
112- b [l ] = '\0' ;
113- }
114-
115- #define CHECK_EQ_N (l , r , n ) \
116- { \
117- char ab[100], eb[100]; \
118- _a2s(l, n, ab); \
119- _a2s(r, n, eb); \
120- if (!check_eq_n(l, r, n)) { \
121- fprintf(stderr, \
122- " test-%d failed! " \
123- "expected %s, actual %s.\n", \
124- tc, ab, eb); \
125- exit(1); \
126- } else { \
127- if (getenv("SHOW_TEST_OUTPUT")) \
128- fprintf( \
129- stdout, \
130- " test-%d: input: %s, output: %s.\n", \
131- tc, ab, eb); \
132- } \
133- }
134-
135- #define RUN_ALL_TESTS () \
136- size_t tc = 0, ts = 0; \
137- for (; ts < array_size(_tests); ts++) { \
138- if (getenv("SHOW_TEST_OUTPUT")) \
139- fprintf(stdout, "Testing implementation %d %s\n", \
140- ts + 1, _tests[ts].desc); \
141- tc += _tests[ts].func(); \
142- } \
143- fprintf(stdout, "Executed %d implementations with %d tests.", ts, tc);
144-
145- typedef int (* TestFuncPtr )();
146-
147- struct TestsStruct {
148- const char * desc ;
149- TestFuncPtr func ;
150- };
151-
152- #define TEST_LIST static struct TestsStruct _tests[]
153-
15488/* ===========================================================================
15589 * Test code
15690 * ===========================================================================
15791 */
92+ #define _of_desc_prefix "_offset_of & _container_of macros"
93+ #define _of_desc_suffix "Access a container using its member"
94+ #define _of_desc _of_desc_prefix " - " _of_desc_suffix
15895
15996int test_iterate_list ()
16097{
@@ -168,11 +105,7 @@ int test_iterate_list()
168105}
169106
170107TEST_LIST = {
171- {"container_of: Access a container using its member" , test_iterate_list },
108+ {_of_desc , test_iterate_list },
172109};
173110
174- int main (int , char * * )
175- {
176- RUN_ALL_TESTS ();
177- return 0 ;
178- }
111+ INIT_TEST_MAIN ();
0 commit comments