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