My Kernel v0.1.0
atomic.h
1#ifndef KERNEL_ATOMIC_H
2#define KERNEL_ATOMIC_H
3
4#ifdef __STDC_NO_ATOMICS__
5#error No standard atomic header available, are you compiling using C11 at least ?
6#endif
7
8#include <kernel/types.h>
9
10#include <utils/compiler.h>
11
12#include <stdatomic.h>
13
14#define __atomic_t native_t
15
22typedef struct {
23 _Atomic __atomic_t val;
24} atomic_t;
25
26static_assert(sizeof(atomic_t) == sizeof(__atomic_t));
27static_assert(offsetof(atomic_t, val) == 0);
28
30#define atomic_cast(val) \
31 ({ \
32 _Static_assert(same_size(atomic_t, *val), "Invalid atomic cast"); \
33 (atomic_t *)(val); \
34 })
35
37#define const_atomic_cast(val) \
38 ({ \
39 _Static_assert(same_size(atomic_t, *val), "Invalid const atomic " \
40 "cast"); \
41 (const atomic_t *)(val); \
42 })
43
45#define READ_ONCE(_x) \
46 ({ \
47 _Static_assert(is_native_word(_x), "Variable is not of native size"); \
48 *(const volatile typeof(_x) *)&(_x); \
49 })
50
52#define WRITE_ONCE(_x, _val) \
53 ({ \
54 _Static_assert(is_native_word(_x), "Variable is not of native size"); \
55 *(volatile typeof(_x) *)&(_x) = (_val); \
56 })
57
58#define stdatomic_read atomic_load
59#define stdatomic_write atomic_store
60#define stdatomic_add atomic_fetch_add
61#define stdatomic_sub atomic_fetch_sub
62
63/*
64 * Defined inside stdatomic.h, but we need to redefine it ourselves to be able
65 * to reuse the atomic_exchange() name. This definition is taken straight from
66 * the original stdatomic.h implementation of atomic_exchange.
67 */
68#undef atomic_exchange
69#define stdatomic_exchange(atomic, val) \
70 atomic_exchange_explicit(atomic, val, memory_order_seq_cst);
71
73static ALWAYS_INLINE __atomic_t atomic_read(const atomic_t *atomic)
74{
75 return stdatomic_read(&atomic->val);
76}
77
79static ALWAYS_INLINE void atomic_write(atomic_t *atomic, __atomic_t val)
80{
81 stdatomic_write(&atomic->val, val);
82}
83
85static ALWAYS_INLINE __atomic_t atomic_exchange(atomic_t *atomic,
86 __atomic_t val)
87{
88 return stdatomic_exchange(&atomic->val, val);
89}
90
95static ALWAYS_INLINE __atomic_t atomic_add(atomic_t *atomic, __atomic_t val)
96{
97 return stdatomic_add(&atomic->val, val);
98}
99
104static ALWAYS_INLINE __atomic_t atomic_sub(atomic_t *atomic, __atomic_t val)
105{
106 return stdatomic_sub(&atomic->val, val);
107}
108
113static ALWAYS_INLINE __atomic_t atomic_inc(atomic_t *atomic)
114{
115 return atomic_add(atomic, 1);
116}
117
122static ALWAYS_INLINE __atomic_t atomic_dec(atomic_t *atomic)
123{
124 return atomic_sub(atomic, 1);
125}
126
127#endif /* KERNEL_ATOMIC_H */
An atomic value.
Definition: atomic.h:22