1// SPDX-License-Identifier: GPL-3.0-or-later
2
3#pragma once
4
5#ifdef __MOS_KERNEL__
6#include <abi-bits/errno.h>
7#endif
8#include <mos/compiler.h>
9#include <stddef.h>
10
11#ifdef __cplusplus
12#define MOS_STATIC_ASSERT static_assert
13#else
14#define MOS_STATIC_ASSERT _Static_assert
15#endif
16
17// clang-format off
18#if defined(__MOS_KERNEL__) && defined(__cplusplus)
19#define __BEGIN_DECLS extern "C" {
20#define __END_DECLS }
21#else
22#define __BEGIN_DECLS
23#define __END_DECLS
24#endif
25// clang-format on
26
27#define __aligned(x) __attribute__((__aligned__(x)))
28#define __malloc __attribute__((__malloc__))
29#define __packed __attribute__((__packed__))
30#define __printf(a, b) __attribute__((__format__(__printf__, a, b)))
31#define __pure __attribute__((__pure__))
32#define __section(S) __attribute__((__section__(S)))
33#define __maybe_unused __attribute__((__unused__))
34#define __used __attribute__((__used__))
35#define __nodiscard __attribute__((__warn_unused_result__))
36
37#define should_inline __maybe_unused static inline
38
39#define likely(x) __builtin_expect(!!(x), 1)
40#define unlikely(x) __builtin_expect(!!(x), 0)
41
42#define __types_compatible(a, b) __builtin_types_compatible_p(__typeof(a), __typeof(b))
43#define do_container_of(ptr, type, member) \
44 __extension__({ \
45 void *real_ptr = (void *) (ptr); \
46 _Static_assert(__types_compatible(*(ptr), ((type *) 0)->member) | __types_compatible(*(ptr), void), "type mismatch: (" #type ") vs (" #ptr "->" #member ")"); \
47 ((type *) (real_ptr - offsetof(type, member))); \
48 })
49
50#define container_of(ptr, type, member) \
51 _Generic(ptr, const __typeof(*(ptr)) *: ((const type *) do_container_of(ptr, type, member)), default: ((type *) do_container_of(ptr, type, member)))
52
53#define cast_to(value, valtype, desttype) _Generic((value), valtype: (desttype) (value), const valtype: (const desttype)(value))
54
55#define is_aligned(ptr, alignment) (((ptr_t) ptr & (alignment - 1)) == 0)
56
57#define GET_BIT(x, n) (((x) >> (n)) & 1)
58#define MASK_BITS(value, width) ((value) & ((1 << (width)) - 1))
59#define SET_BITS(bit, width, value) (MASK_BITS(value, width) << (bit))
60
61#define MOS_STRINGIFY2(x) #x
62#define MOS_STRINGIFY(x) MOS_STRINGIFY2(x)
63
64#define MOS_UNUSED(x) (void) (x)
65
66#define MOS_CONCAT_INNER(a, b) a##b
67#define MOS_CONCAT(a, b) MOS_CONCAT_INNER(a, b)
68
69#define MOS_WARNING_PUSH MOS_PRAGMA(diagnostic push)
70#define MOS_WARNING_POP MOS_PRAGMA(diagnostic pop)
71#define MOS_WARNING_DISABLE(text) MOS_PRAGMA(diagnostic ignored text)
72
73#define ALIGN_UP(addr, size) (((addr) + (size - 1)) & ~(size - 1))
74#define ALIGN_DOWN(addr, size) ((addr) & ~(size - 1))
75#define ALIGN_UP_TO_PAGE(addr) ALIGN_UP(addr, MOS_PAGE_SIZE)
76#define ALIGN_DOWN_TO_PAGE(addr) ALIGN_DOWN(addr, MOS_PAGE_SIZE)
77
78#define MOS_IN_RANGE(addr, start, end) ((addr) >= (start) && (addr) < (end))
79
80#define MOS_FOURCC(a, b, c, d) ((u32) (a) | ((u32) (b) << 8) | ((u32) (c) << 16) | ((u32) (d) << 24))
81#define MOS_ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
82
83#define MOS_MAX_VADDR ((ptr_t) ~0)
84
85#define READ_ONCE(x) (*(volatile typeof(x) *) &(x))
86
87// clang-format off
88#define KB * 1024
89#define MB * 1024 KB
90#define GB * (u64) 1024 MB
91#define TB * (u64) 1024 GB
92#define statement_expr(type, ...) __extension__({ type retval; __VA_ARGS__; retval; })
93// clang-format on
94
95#define __NO_OP(...)
96
97#define BIT(x) (1ull << (x))
98
99#ifdef __cplusplus
100#define MOSAPI extern "C"
101#else
102#define MOSAPI extern
103#endif
104
105// If the feature is enabled, the expression will be 1, otherwise -1.
106// If the given feature is not defined, the expression will be 0, which throws a division by zero error.
107#define MOS_CONFIG(feat) (1 / feat == 1)
108
109#define MOS_DEBUG_FEATURE(feat) MOS_CONFIG(MOS_CONCAT(MOS_DEBUG_, feat))
110
111/**
112 * @brief Returns true for the first call, false for all subsequent calls.
113 */
114#define once() \
115 __extension__({ \
116 static bool __seen = false; \
117 bool ret = false; \
118 if (__seen) \
119 ret = false; \
120 else \
121 __seen = true, ret = true; \
122 ret; \
123 })
124
125#define MOS_PUT_IN_SECTION(_section, _struct, _var, ...) static const _struct _var __used __section(_section) = __VA_ARGS__
126#define IS_ERR_VALUE(x) unlikely((unsigned long) (void *) (x) >= (unsigned long) -4095)
127
128__nodiscard should_inline void *ERR_PTR(long error)
129{
130 return (void *) error;
131}
132
133__nodiscard should_inline long PTR_ERR(const void *ptr)
134{
135 return (long) ptr;
136}
137
138__nodiscard should_inline void *ERR(const void *ptr)
139{
140 return (void *) ptr;
141}
142
143__nodiscard should_inline bool IS_ERR(const void *ptr)
144{
145 return IS_ERR_VALUE((unsigned long) ptr);
146}
147
148__attribute__((__deprecated__("reconsider if a NULL check is really required"))) __nodiscard should_inline bool IS_ERR_OR_NULL(const void *ptr)
149{
150 return unlikely(!ptr) || IS_ERR_VALUE((unsigned long) ptr);
151}
152
153#define MOS_STUB_IMPL(...) \
154 MOS_WARNING_PUSH \
155 MOS_WARNING_DISABLE("-Wunused-parameter") \
156 __VA_ARGS__ \
157 { \
158 MOS_UNREACHABLE_X("unimplemented: file %s, line %d", __FILE__, __LINE__); \
159 } \
160 MOS_WARNING_POP
161
162#ifdef __cplusplus
163// enum operators are not supported in C++ implicitly
164// clang-format off
165#define MOS_ENUM_OPERATORS(_enum) \
166 constexpr inline _enum operator|(_enum a, _enum b) { return static_cast<_enum>(static_cast<int>(a) | static_cast<int>(b)); } \
167 constexpr inline _enum operator&(_enum a, _enum b) { return static_cast<_enum>(static_cast<int>(a) & static_cast<int>(b)); } \
168 constexpr inline _enum operator~(_enum a) { return static_cast<_enum>(~static_cast<int>(a)); } \
169 constexpr inline _enum &operator|=(_enum &a, _enum b) { return a = a | b; } \
170 constexpr inline _enum &operator&=(_enum &a, _enum b) { return a = a & b; }
171// clang-format on
172#else
173#define MOS_ENUM_OPERATORS(_enum)
174#endif
175