Add parlib/common.h
[akaros.git] / user / parlib / include / x86 / atomic.h
1 #ifndef PARLIB_ARCH_ATOMIC_H
2 #define PARLIB_ARCH_ATOMIC_H
3
4 #include <parlib/common.h>
5 #include <ros/atomic.h>
6
7 __BEGIN_DECLS
8
9 static inline void atomic_init(atomic_t *number, long val);
10 static inline long atomic_read(atomic_t *number);
11 static inline void atomic_set(atomic_t *number, long val);
12 static inline void atomic_inc(atomic_t *number);
13 static inline void atomic_dec(atomic_t *number);
14 static inline long atomic_fetch_and_add(atomic_t *number, long val);
15 static inline long atomic_swap(atomic_t *addr, long val);
16 static inline void *atomic_swap_ptr(void **addr, void *val);
17 static inline uint32_t atomic_swap_u32(uint32_t *addr, uint32_t val);
18 static inline bool atomic_cas(atomic_t *addr, long exp_val, long new_val);
19 static inline bool atomic_cas_ptr(void **addr, void *exp_val, void *new_val);
20 static inline bool atomic_cas_u32(uint32_t *addr, uint32_t exp_val,
21                                   uint32_t new_val);
22 static inline void atomic_andb(volatile uint8_t *number, uint8_t mask);
23 static inline void atomic_orb(volatile uint8_t *number, uint8_t mask);
24
25 /* Inlined functions declared above */
26 static inline void atomic_init(atomic_t *number, long val)
27 {
28         asm volatile("mov %1,%0" : "=m"(*number) : "r"(val));
29 }
30
31 static inline long atomic_read(atomic_t *number)
32 {
33         long val;
34         asm volatile("mov %1,%0" : "=r"(val) : "m"(*number));
35         return val;
36 }
37
38 static inline void atomic_set(atomic_t *number, long val)
39 {
40         asm volatile("mov %1,%0" : "=m"(*number) : "r"(val));
41 }
42
43 static inline void atomic_inc(atomic_t *number)
44 {
45         __sync_fetch_and_add(number, 1);
46 }
47
48 static inline void atomic_dec(atomic_t *number)
49 {
50         __sync_fetch_and_sub(number, 1);
51 }
52
53 static inline long atomic_fetch_and_add(atomic_t *number, long val)
54 {
55         return (long)__sync_fetch_and_add(number, val);
56 }
57
58 static inline long atomic_swap(atomic_t *addr, long val)
59 {
60         /* This poorly named function does an xchg */
61         return (long)__sync_lock_test_and_set(addr, val);
62 }
63
64 static inline void *atomic_swap_ptr(void **addr, void *val)
65 {
66         return (void*)__sync_lock_test_and_set(addr, val);
67 }
68
69 static inline uint32_t atomic_swap_u32(uint32_t *addr, uint32_t val)
70 {
71         return (uint32_t)__sync_lock_test_and_set(addr, val);
72 }
73
74 static inline bool atomic_cas(atomic_t *addr, long exp_val, long new_val)
75 {
76         return __sync_bool_compare_and_swap(addr, exp_val, new_val);
77 }
78
79 static inline bool atomic_cas_ptr(void **addr, void *exp_val, void *new_val)
80 {
81         return __sync_bool_compare_and_swap(addr, exp_val, new_val);
82 }
83
84 static inline bool atomic_cas_u32(uint32_t *addr, uint32_t exp_val,
85                                   uint32_t new_val)
86 {
87         return __sync_bool_compare_and_swap(addr, exp_val, new_val);
88 }
89
90 static inline void atomic_andb(volatile uint8_t *number, uint8_t mask)
91 {
92         __sync_fetch_and_and(number, mask);
93 }
94
95 static inline void atomic_orb(volatile uint8_t *number, uint8_t mask)
96 {
97         __sync_fetch_and_or(number, mask);
98 }
99
100 __END_DECLS
101
102 #endif /* PARLIB_ARCH_ATOMIC_H */