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