Added BCQs to the preempt structs in procdata
[akaros.git] / user / include / i686 / atomic.h
1 #ifndef PARLIB_ATOMIC_H
2 #define PARLIB_ATOMIC_H
3
4 #include <ros/common.h>
5
6 typedef void * RACY atomic_t;
7
8 static inline void atomic_init(atomic_t *number, int32_t val);
9 static inline int32_t atomic_read(atomic_t *number);
10 static inline void atomic_set(atomic_t *number, int32_t val);
11 static inline void atomic_inc(atomic_t *number);
12 static inline void atomic_dec(atomic_t *number);
13 static inline uint32_t atomic_swap(uint32_t *addr, uint32_t val);
14 static inline bool atomic_comp_swap(uint32_t *addr, uint32_t exp_val,
15                                     uint32_t new_val);
16 static inline void atomic_andb(volatile uint8_t RACY* number, uint8_t mask);
17 static inline void atomic_orb(volatile uint8_t RACY* number, uint8_t mask);
18
19 /* Inlined functions declared above */
20 static inline void atomic_init(atomic_t *number, int32_t val)
21 {
22         asm volatile("movl %1,%0" : "=m"(*number) : "r"(val));
23 }
24
25 static inline int32_t atomic_read(atomic_t *number)
26 {
27         int32_t val;
28         asm volatile("movl %1,%0" : "=r"(val) : "m"(*number));
29         return val;
30 }
31
32 static inline void atomic_set(atomic_t *number, int32_t val)
33 {
34         asm volatile("movl %1,%0" : "=m"(*number) : "r"(val));
35 }
36
37 // need to do this with pointers and deref.  %0 needs to be the memory address
38 static inline void atomic_inc(atomic_t *number)
39 {
40         asm volatile("lock incl %0" : "=m"(*number) : : "cc");
41 }
42
43 static inline void atomic_dec(atomic_t *number)
44 {
45         // for instance, this doesn't work:
46         //asm volatile("lock decl (%0)" : "=r"(number) : : "cc");
47         asm volatile("lock decl %0" : "=m"(*number) : : "cc");
48 }
49
50 static inline uint32_t atomic_swap(uint32_t *addr, uint32_t val)
51 {
52         // this would work, but its code is bigger, and it's not like the others
53         //asm volatile("xchgl %0,(%2)" : "=r"(val) : "0"(val), "r"(addr) : "memory");
54         asm volatile("xchgl %0,%1" : "=r"(val), "=m"(*addr) : "0"(val), "m"(*addr));
55         return val;
56 }
57
58 /* reusing exp_val for the bool return */
59 static inline bool atomic_comp_swap(uint32_t *addr, uint32_t exp_val,
60                                     uint32_t new_val)
61 {
62         asm volatile("lock cmpxchgl %4,%1; sete %%al"
63                      : "=a"(exp_val), "=m"(*addr)
64                      : "m"(*addr), "a"(exp_val), "r"(new_val)
65                      : "cc");
66         return exp_val;
67 }
68
69 static inline void atomic_andb(volatile uint8_t RACY*number, uint8_t mask)
70 {
71         asm volatile("lock andb %1,%0" : "=m"(*number) : "r"(mask) : "cc");
72 }
73
74 static inline void atomic_orb(volatile uint8_t RACY*number, uint8_t mask)
75 {
76         asm volatile("lock orb %1,%0" : "=m"(*number) : "r"(mask) : "cc");
77 }
78
79 #endif /* !PARLIB_ATOMIC_H */