rsys.h (12188B)
1 /* Copyright (C) 2013-2023, 2025 Vincent Forest (vaplv@free.fr) 2 * 3 * The RSys library is free software: you can redistribute it and/or modify 4 * it under the terms of the GNU General Public License as published 5 * by the Free Software Foundation, either version 3 of the License, or 6 * (at your option) any later version. 7 * 8 * The RSys library is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with the RSys library. If not, see <http://www.gnu.org/licenses/>. */ 15 16 #ifndef RSYS_H 17 #define RSYS_H 18 19 /* In C99 standard, C++ defines some macros (eg UINT32_MAX) only when 20 * __STDC_LIMIT_MACROS or __STDC_CONSTANT_MACROS are defined before <stdint.h> 21 * is included. The C11 standard removes this constraint. The following work 22 * around always define those macros in C++ so that a C library implementation 23 * which follows the C99 standard can be used in C++. */ 24 #ifdef __cplusplus 25 #ifndef __STDC_LIMIT_MACROS 26 #define __STDC_LIMIT_MACROS 27 #define STDC_LIMIT_MACROS_DEFINED_BY_RSYS__ 28 #endif 29 #ifndef __STDC_CONSTANT_MACROS 30 #define __STDC_CONSTANT_MACROS 31 #define STDC_CONSTANT_MACROS_DEFINED_BY_RSYS__ 32 #endif 33 #endif 34 35 #include <stdint.h> 36 37 #ifdef STDC_LIMIT_MACROS_DEFINED_BY_RSYS__ 38 #undef __STDC_LIMIT_MACROS 39 #undef STDC_LIMIT_MACROS_DEFINED_BY_RSYS__ 40 #endif 41 #ifdef STDC_CONSTANT_MACROS_DEFINED_BY_RSYS__ 42 #undef __STDC_CONSTANT_MACROS 43 #undef STDC_CONSTANT_MACROS_DEFINED_BY_RSYS__ 44 #endif 45 46 #include <stddef.h> 47 #include <stdlib.h> 48 #include <stdio.h> 49 50 /******************************************************************************* 51 * Platform 52 ******************************************************************************/ 53 #if defined(__unix__) || defined(__unix) || defined(unix) 54 #define OS_UNIX 55 #else 56 #error "Unsupported OS" 57 #endif 58 59 /******************************************************************************* 60 * Compiler 61 ******************************************************************************/ 62 #if defined(__GNUC__) 63 #define COMPILER_GCC 64 #else 65 #error "Unsupported compiler" 66 #endif 67 68 /******************************************************************************* 69 * Architecture 70 ******************************************************************************/ 71 #if defined(__x86_64__) || defined(_M_X64) 72 #define ARCH_64BITS 73 #else 74 #define ARCH_32BITS 75 #endif 76 77 /******************************************************************************* 78 * Symbol visibility 79 ******************************************************************************/ 80 #if defined(COMPILER_GCC) 81 #define EXPORT_SYM __attribute__((visibility("default"))) 82 #define IMPORT_SYM 83 #define LOCAL_SYM __attribute__((visibility("hidden"))) 84 #else 85 #error "Undefined symbol visibility macros" 86 #endif 87 88 #if defined(OS_UNIX) 89 #define SHARED_LIBRARY_PREFIX "lib" 90 #define SHARED_LIBRARY_SUFFIX ".so" 91 #endif 92 93 #if !defined(SHARED_LIBRARY_PREFIX) || !defined(SHARED_LIBRARY_SUFFIX) 94 #error "Undefined library suffix/prefix" 95 #endif 96 97 #define SHARED_LIBRARY_NAME(Lib) SHARED_LIBRARY_PREFIX Lib SHARED_LIBRARY_SUFFIX 98 99 #if defined(RSYS_SHARED_BUILD) 100 #define RSYS_API extern EXPORT_SYM 101 #else 102 #define RSYS_API extern IMPORT_SYM 103 #endif 104 105 /******************************************************************************* 106 * Code inlining 107 ******************************************************************************/ 108 #if defined(COMPILER_GCC) 109 #define FINLINE __inline__ __attribute__((always_inline)) 110 #define INLINE __inline__ 111 #define NOINLINE __attribute__((noinline)) 112 #else 113 #error "Undefined inlining macros" 114 #endif 115 116 /******************************************************************************* 117 * Data alignment 118 ******************************************************************************/ 119 #if defined(COMPILER_GCC) 120 #define ALIGN(Size) __attribute__((aligned(Size))) 121 #define ALIGNOF(Type) __alignof__(Type) 122 #else 123 #error "Undefined alignment macros" 124 #endif 125 126 #define ALIGN_SIZE(Size, Algnt) (((Size) + ((Algnt) - 1)) & ~((Algnt) - 1)) 127 #define IS_ALIGNED(Addr, Algnt) (((uintptr_t)(Addr) & ((Algnt)-1)) == 0) 128 129 /******************************************************************************* 130 * Atomic 131 ******************************************************************************/ 132 #if defined(COMPILER_GCC) 133 #define ATOMIC int64_t 134 #define ATOMIC_INCR(A) __sync_add_and_fetch((A), 1) 135 #define ATOMIC_DECR(A) __sync_sub_and_fetch((A), 1) 136 #define ATOMIC_ADD(A, V) __sync_add_and_fetch((A), V) 137 #define ATOMIC_SUB(A, V) __sync_sub_and_fetch((A), V) 138 #define ATOMIC_CAS(Atom, NewVal, Comparand) /* Return the initial value */ \ 139 __sync_val_compare_and_swap((Atom), (Comparand), (NewVal)) 140 #else 141 #error "Undefined atomic operations" 142 #endif 143 144 #define ATOMIC_SET(A, V) ATOMIC_CAS((A), V, (*A)) /*Return the initial value*/ 145 #define ATOMIC_GET(A) ATOMIC_ADD(A, 0) 146 147 /******************************************************************************* 148 * Function deprecation 149 ******************************************************************************/ 150 #if defined COMPILER_GCC 151 #define DEPRECATED __attribute__((deprecated)) 152 #else 153 #define DEPRECATED 154 #endif 155 156 /******************************************************************************* 157 * Code checking 158 ******************************************************************************/ 159 #ifdef NDEBUG 160 #define ASSERT(C) (void)0 161 #else 162 #include <assert.h> 163 #define ASSERT(C) assert(C) 164 #endif 165 166 #ifdef COMPILER_GCC 167 #define STATIC_ASSERT(Cond, Msg) \ 168 static char CONCAT(CONCAT(CONCAT(STATIC_ASSERT_, COUNTER), _), Msg) \ 169 [1 - 2*(!(Cond))] __attribute__((unused)) 170 #endif 171 172 #define VFATAL(Fmt, Args) \ 173 { \ 174 fprintf(stderr, Fmt COMMA_##Args LIST_##Args); \ 175 ASSERT(0); \ 176 abort(); \ 177 } (void)0 178 179 #define FATAL(Msg) VFATAL(Msg, ARG0()) 180 181 #define CHK(Cond) \ 182 { \ 183 if(!(Cond)) \ 184 FATAL("error:" STR(__FILE__) ":" STR(__LINE__)"\n"); \ 185 } (void)0 186 187 /******************************************************************************* 188 * Branch prediction information 189 ******************************************************************************/ 190 #ifdef COMPILER_GCC 191 #define LIKELY(X) __builtin_expect((X), 1) 192 #define UNLIKELY(X) __builtin_expect((X), 0) 193 #else 194 #define LIKELY 195 #define UNLIKELY 196 #endif 197 198 /******************************************************************************* 199 * Iteration 200 ******************************************************************************/ 201 /* Iterate over [Start, End) */ 202 #define FOR_EACH(Id, Start, End) \ 203 for((Id) = (Start); (Id) < (End); ++(Id)) 204 205 /* Reverse iterrate over [Start, End) */ 206 #define FOR_EACH_REVERSE(Id, Start, End) \ 207 for((Id) = (Start); (Id) > (End); --(Id)) 208 209 /******************************************************************************* 210 * Instruction sets 211 ******************************************************************************/ 212 #if defined(COMPILER_GCC) 213 #ifdef __SSE__ 214 #define SIMD_SSE 215 #endif 216 #ifdef __SSE2__ 217 #define SIMD_SSE2 218 #endif 219 #ifdef __SSE3__ 220 #define SIMD_SSE3 221 #endif 222 #ifdef __SSSE3__ 223 #define SIMD_SSSE3 224 #endif 225 #ifdef __SSE4_1__ 226 #define SIMD_SSE4_1 227 #endif 228 #ifdef __SSE4_2__ 229 #define SIMD_SSE4_2 230 #endif 231 #ifdef __AVX__ 232 #define SIMD_AVX 233 #endif 234 #ifdef __FMA__ 235 #define FMADD 236 #endif 237 #endif 238 239 /******************************************************************************* 240 * Variadic macros 241 ******************************************************************************/ 242 #define ARG0() 243 #define ARG1(A) 244 #define ARG2(A, B) 245 #define ARG3(A, B, C) 246 #define ARG4(A, B, C, D) 247 #define ARG5(A, B, C, D, E) 248 #define ARG6(A, B, C, D, E, F) 249 #define ARG7(A, B, C, D, E, F, G) 250 #define ARG8(A, B, C, D, E, F, G, H) 251 #define ARG9(A, B, C, D, E, F, G, H, I) 252 253 #define LIST_ARG0() 254 #define LIST_ARG1(A) A 255 #define LIST_ARG2(A, B) A, B 256 #define LIST_ARG3(A, B, C) A, B, C 257 #define LIST_ARG4(A, B, C, D) A, B, C, D 258 #define LIST_ARG5(A, B, C, D, E) A, B, C, D, E 259 #define LIST_ARG6(A, B, C, D, E, F) A, B, C, D, E, F 260 #define LIST_ARG7(A, B, C, D, E, F, G) A, B, C, D, E, F, G 261 #define LIST_ARG8(A, B, C, D, E, F, G, H) A, B, C, D, E, F, G, H 262 #define LIST_ARG9(A, B, C, D, E, F, G, H, I) A, B, C, D, E, F, G, H, I 263 264 #define COMMA_ARG0() 265 #define COMMA_ARG1(A) , 266 #define COMMA_ARG2(A, B) , 267 #define COMMA_ARG3(A, B, C) , 268 #define COMMA_ARG4(A, B, C, D) , 269 #define COMMA_ARG5(A, B, C, D, E) , 270 #define COMMA_ARG6(A, B, C, D, E, F) , 271 #define COMMA_ARG7(A, B, C, D, E, F, G) , 272 #define COMMA_ARG8(A, B, C, D, E, F, G, H) , 273 #define COMMA_ARG9(A, B, C, D, E, F, G, H, I) , 274 275 /******************************************************************************* 276 * Result constants 277 ******************************************************************************/ 278 typedef int res_T; 279 #define RES_OK 0 280 #define RES_BAD_ARG 1 281 #define RES_MEM_ERR 2 282 #define RES_IO_ERR 3 283 #define RES_UNKNOWN_ERR 4 284 #define RES_BAD_OP 5 285 #define RES_EOF 6 /* End Of File */ 286 287 /******************************************************************************* 288 * Miscellaneous 289 ******************************************************************************/ 290 #ifdef COMPILER_GCC 291 /* On GCC compiler we follow the C-89 standard that does not support the 292 * va_copy macro. We thus use the built-in __va_copy GCC extension */ 293 #define VA_COPY(VArgs, Args) __va_copy((VArgs), (Args)) 294 #endif 295 296 #define BIT(Num) (1 << (Num)) 297 #define BIT_I16(Num) (int16_t)((int16_t)1 << (Num)) 298 #define BIT_I32(Num) (int32_t)((int32_t)1 << (Num)) 299 #define BIT_I64(Num) (int64_t)((int64_t)1 << (Num)) 300 #define BIT_U16(Num) (uint16_t)((uint16_t)1 << (Num)) 301 #define BIT_U32(Num) (uint32_t)((uint32_t)1 << (Num)) 302 #define BIT_U64(Num) (uint64_t)((uint64_t)1 << (Num)) 303 304 #define CONCAT__(A, B) A ## B 305 #define CONCAT(A, B) CONCAT__(A, B) 306 #define SPLIT2(A) (A)[0], (A)[1] 307 #define SPLIT3(A) (A)[0], (A)[1], (A)[2] 308 #define SPLIT4(A) (A)[0], (A)[1], (A)[2], (A)[3] 309 310 #define CONTAINER_OF(Ptr, Type, Member) \ 311 ((Type*)((uintptr_t)Ptr - offsetof(Type, Member))) 312 313 #if defined COMPILER_GCC 314 #define RESTRICT __restrict__ 315 #else 316 #define RESTRICT 317 #endif 318 319 #define COUNTER __COUNTER__ 320 321 #define SWAP(Type, A, B) \ 322 { \ 323 Type tmp__ = (A); \ 324 (A) = (B); \ 325 (B) = tmp__; \ 326 } (void)0 327 328 #define STR__(X) #X 329 #define STR(X) STR__(X) 330 331 #define OFFSET_PTR(Ptr, Offset) (void*)((uintptr_t)(Ptr) + (Offset)) 332 333 #ifdef COMPILER_GCC 334 #define FUNC_NAME (__extension__ __FUNCTION__) 335 #else 336 #define FUNC_NAME __FUNCTION__ 337 #endif 338 339 #define MEM_AREA_OVERLAP(A, SzA, B, SzB) \ 340 ((uintptr_t)(A) < (uintptr_t)(B) \ 341 ? (uintptr_t)(B) < ((uintptr_t)(A) + (SzA)) \ 342 : (uintptr_t)(A) < ((uintptr_t)(B) + (SzB))) 343 344 #ifdef __cplusplus 345 #define BEGIN_DECLS extern "C" { 346 #define END_DECLS } 347 #else 348 #define BEGIN_DECLS 349 #define END_DECLS 350 #endif 351 352 #ifdef COMPILER_GCC 353 #if __GNUC__ >= 7 354 #define FALLTHROUGH __attribute__ ((fallthrough)) 355 #else 356 #define FALLTHROUGH (void)0 357 #endif 358 #else 359 #define FALLTHROUGH (void)0 360 #endif 361 362 #endif /* RSYS_H */