rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

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 */