1#pragma once
 2
 3/*
 4 * Miscellaneous helper macros
 5 */
 6
 7#include <limits.h>
 8#include <stdatomic.h>
 9
10#ifdef __cplusplus
11extern "C" {
12#endif
13
14#define PW_STRUCT(name)  \
15    struct name;  \
16    typedef struct name name;  \
17    struct name
18
19#define PW_UNION(name)  \
20    union name;  \
21    typedef union name name;  \
22    union name
23
24#define PW_LENGTH(array)  (sizeof(array) / sizeof((array)[0]))
25/*
26 * Get array length
27 */
28
29// __LINE_STR__ hack borrowed from here:
30// https://stackoverflow.com/questions/2670816/how-can-i-use-the-compile-time-constant-line-in-a-string#2670919
31#define __PW_STRINGIZE(n) __PW_STRINGIZE2(n)
32#define __PW_STRINGIZE2(n) #n
33#define __LINE_STR__ __PW_STRINGIZE(__LINE__)
34
35static inline unsigned _pw_atomic_load(atomic_uint* p)
36{
37    return atomic_load_explicit(p, memory_order_relaxed);
38}
39
40static inline void _pw_atomic_store(atomic_uint* p, unsigned v)
41{
42    atomic_store_explicit(p, v, memory_order_relaxed);
43}
44
45#define _pw_atomic_add(p, v)  \
46    __extension__  \
47    ({  \
48        unsigned prev = atomic_fetch_add_explicit((p), (v), memory_order_relaxed);  \
49        if ((prev > UINT_MAX - (v))) {  \
50            pw_panic("atomic_uint overflow %s:%u p=%p v=%u prev=%u\n", __FILE__, __LINE__, (void*) (p), prev, (v));  \
51        }  \
52        prev;  \
53    })
54
55#define _pw_atomic_sub(p, v)  \
56    __extension__  \
57    ({  \
58        unsigned prev = atomic_fetch_sub_explicit((p), (v), memory_order_relaxed);  \
59        if (prev < (v)) {  \
60            pw_panic("atomic_uint underflow %s:%u p=%p v=%u prev=%u\n", __FILE__, __LINE__, (void*) (p), prev, (v));  \
61        }  \
62        prev;  \
63    })
64
65#ifdef __cplusplus
66}
67#endif