xref: /illumos-gate/usr/src/uts/common/sys/containerof.h (revision 6062513a89a98a278aea621a2e591ba8df1a8b8e)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2017 Toomas Soome <tsoome@me.com>
14  */
15 
16 #ifndef _SYS_CONTAINEROF_H
17 #define	_SYS_CONTAINEROF_H
18 
19 /*
20  * __containerof macro for private use in illumos.
21  *
22  * __containerof(ptr, type, member) will return pointer to the data
23  * structure of given type, calculated based on the offset of 'member'
24  * in the structure 'type'.
25  *
26  * For this macro to work, we should be certain of the pointer type.
27  */
28 
29 #include <sys/stddef.h>
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 #if !defined(__containerof)
36 
37 /*
38  * The extension to support statements and declarations in expressions,
39  * https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html, is available
40  * in gcc >= 3.1.
41  * We perform the assignment below to try and provide additional type safety.
42  */
43 #if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
44 #define	__containerof(m, s, name) (					\
45 {									\
46 	const volatile __typeof(((s *)0)->name) *__m = (m);		\
47 	(void *)((uintptr_t)__m - (uintptr_t)offsetof(s, name));	\
48 })
49 #else
50 #define	__containerof(m, s, name)			\
51 	(void *)((uintptr_t)(m) - (uintptr_t)offsetof(s, name))
52 #endif
53 #endif
54 
55 #ifdef __cplusplus
56 }
57 #endif
58 
59 #endif /* _SYS_CONTAINEROF_H */
60