1 /**
2 * Copyright (C) Mellanox Technologies Ltd. 2001-2017.  ALL RIGHTS RESERVED.
3 * Copyright (C) UT-Battelle, LLC. 2015. ALL RIGHTS RESERVED.
4 *
5 * See file LICENSE for terms.
6 */
7 
8 #ifndef UCS_COMPILER_DEF_H
9 #define UCS_COMPILER_DEF_H
10 
11 /* Note: Place "@file <file name>.h" after BEGIN_C_DECS
12  * to avoid bugs in a documentation */
13 #ifdef __cplusplus
14 # define BEGIN_C_DECLS  extern "C" {
15 # define END_C_DECLS    }
16 #else
17 # define BEGIN_C_DECLS
18 # define END_C_DECLS
19 #endif
20 
21 /*
22  * Assertions which are checked in compile-time
23  *
24  * Usage: UCS_STATIC_ASSERT(condition)
25  */
26 #define UCS_STATIC_ASSERT(_cond) \
27      switch(0) {case 0:case (_cond):;}
28 
29 /* Aliasing structure */
30 #define UCS_S_MAY_ALIAS __attribute__((may_alias))
31 
32 /* A function without side effects */
33 #define UCS_F_PURE   __attribute__((pure))
34 
35 /* A function which does not return */
36 #define UCS_F_NORETURN __attribute__((noreturn))
37 
38 /* Packed structure */
39 #define UCS_S_PACKED             __attribute__((packed))
40 
41 /* Avoid inlining the function */
42 #define UCS_F_NOINLINE __attribute__ ((noinline))
43 
44 /* Shared library constructor and destructor */
45 #define UCS_F_CTOR __attribute__((constructor))
46 #define UCS_F_DTOR __attribute__((destructor))
47 
48 /* Silence "defined but not used" error for static function */
49 #define UCS_F_MAYBE_UNUSED __attribute__((used))
50 
51 /* Non-null return */
52 #define UCS_F_NON_NULL __attribute__((nonnull))
53 
54 /* Always inline the function */
55 #ifdef __GNUC__
56 #define UCS_F_ALWAYS_INLINE      inline __attribute__ ((always_inline))
57 #else
58 #define UCS_F_ALWAYS_INLINE      inline
59 #endif
60 
61 /* Silence "uninitialized variable" for stupid compilers (gcc 4.1)
62  * which can't optimize properly.
63  */
64 #if (((__GNUC__ == 4) && (__GNUC_MINOR__ == 1)) || !defined(__OPTIMIZE__))
65 #  define UCS_V_INITIALIZED(_v)  (_v = (typeof(_v))0)
66 #else
67 #  define UCS_V_INITIALIZED(_v)  ((void)0)
68 #endif
69 
70 /* The i-th bit */
71 #define UCS_BIT(i)               (1ul << (i))
72 
73 /* Mask of bits 0..i-1 */
74 #define UCS_MASK(i)              (UCS_BIT(i) - 1)
75 
76 /*
77  * Enable compiler checks for printf-like formatting.
78  *
79  * @param fmtargN number of formatting argument
80  * @param vargN   number of variadic argument
81  */
82 #define UCS_F_PRINTF(fmtargN, vargN) __attribute__((format(printf, fmtargN, vargN)))
83 
84 /* Unused variable */
85 #define UCS_V_UNUSED __attribute__((unused))
86 
87 /* Aligned variable */
88 #define UCS_V_ALIGNED(_align) __attribute__((aligned(_align)))
89 
90 /* Used for labels */
91 #define UCS_EMPTY_STATEMENT {}
92 
93 /* Helper macro for address arithmetic in bytes */
94 #define UCS_PTR_BYTE_OFFSET(_ptr, _offset) \
95     ((void *)((intptr_t)(_ptr) + (intptr_t)(_offset)))
96 
97 /* Helper macro to calculate an address with offset equal to size of _type */
98 #define UCS_PTR_TYPE_OFFSET(_ptr, _type) \
99     ((void *)((typeof(_type) *)(_ptr) + 1))
100 
101 /* Helper macro to calculate ptr difference (_end - _start) */
102 #define UCS_PTR_BYTE_DIFF(_start, _end) \
103     ((ptrdiff_t)((uintptr_t)(_end) - (uintptr_t)(_start)))
104 
105 
106 /**
107  * Size of statically-declared array
108  */
109 #define ucs_static_array_size(_array) \
110     ({ \
111         UCS_STATIC_ASSERT((void*)&(_array) == (void*)&((_array)[0])); \
112         ( sizeof(_array) / sizeof((_array)[0]) ); \
113     })
114 
115 /**
116  * @return count of elements in const-size array
117  */
118 #define ucs_array_size(_array) \
119     (sizeof(_array) / sizeof((_array)[0]))
120 
121 /**
122  * @return Offset of _member in _type. _type is a structure type.
123  */
124 #define ucs_offsetof(_type, _member) \
125     ((unsigned long)&( ((_type*)0)->_member ))
126 
127 /**
128  * Get a pointer to a struct containing a member.
129  *
130  * @param __ptr   Pointer to the member.
131  * @param type    Container type.
132  * @param member  Element member inside the container.
133 
134  * @return Address of the container structure.
135  */
136 #define ucs_container_of(_ptr, _type, _member) \
137     ( (_type*)( (char*)(void*)(_ptr) - ucs_offsetof(_type, _member) )  )
138 
139 
140 /**
141  * @return Address of a derived structure. It must have a "super" member at offset 0.
142  * NOTE: we use the built-in offsetof here because we can't use ucs_offsetof() in
143  *       a constant expression.
144  */
145 #define ucs_derived_of(_ptr, _type) \
146     ({\
147         UCS_STATIC_ASSERT(offsetof(_type, super) == 0) \
148         ucs_container_of(_ptr, _type, super); \
149     })
150 
151 /**
152  * @param _type   Structure type.
153  * @param _field  Field of structure.
154  *
155  * @return Size of _field in _type.
156  */
157 #define ucs_field_sizeof(_type, _field) \
158     sizeof(((_type*)0)->_field)
159 
160 /**
161  * @param _type   Structure type.
162  * @param _field  Field of structure.
163  *
164  * @return Type of _field in _type.
165  */
166 #define ucs_field_type(_type, _field) \
167     typeof(((_type*)0)->_field)
168 
169 /**
170  * Prevent compiler from reordering instructions
171  */
172 #define ucs_compiler_fence()       asm volatile(""::: "memory")
173 
174 /**
175  * Prefetch cache line
176  */
177 #define ucs_prefetch(p)            __builtin_prefetch(p)
178 
179 /* Branch prediction */
180 #define ucs_likely(x)              __builtin_expect(x, 1)
181 #define ucs_unlikely(x)            __builtin_expect(x, 0)
182 
183 /* Check if an expression is a compile-time constant */
184 #define ucs_is_constant(expr)      __builtin_constant_p(expr)
185 
186 /*
187  * Define code which runs at global constructor phase
188  */
189 #define UCS_STATIC_INIT \
190     static void UCS_F_CTOR UCS_PP_APPEND_UNIQUE_ID(ucs_initializer_ctor)()
191 
192 /*
193  * Define code which runs at global destructor phase
194  */
195 #define UCS_STATIC_CLEANUP \
196     static void UCS_F_DTOR UCS_PP_APPEND_UNIQUE_ID(ucs_initializer_dtor)()
197 
198 #endif /* UCS_COMPILER_DEF_H */
199