Merge branch 'master' into proc-work
[akaros.git] / kern / arch / i386 / atomic.h
1 #ifndef ROS_INCLUDE_ATOMIC_H
2 #define ROS_INCLUDE_ATOMIC_H
3
4 #include <arch/types.h>
5
6 #define mb() {rmb(); wmb();}
7 #define rmb() ({ asm volatile("lfence"); })
8 #define wmb() 
9
10 typedef void* atomic_t;
11
12 static inline void atomic_init(atomic_t *number, int32_t val);
13 static inline int32_t atomic_read(atomic_t *number);
14 static inline void atomic_set(atomic_t *number, int32_t val);
15 static inline void atomic_inc(atomic_t *number);
16 static inline void atomic_dec(atomic_t *number);
17 static inline void atomic_andb(volatile uint8_t* number, uint8_t mask);
18 static inline void spin_lock(volatile uint32_t* lock);
19 static inline void spin_unlock(volatile uint32_t* lock);
20
21 /* Inlined functions declared above */
22 static inline void atomic_init(atomic_t *number, int32_t val)
23 {
24         asm volatile("movl %1,%0" : "=m"(*number) : "r"(val));
25 }
26
27 static inline int32_t atomic_read(atomic_t *number)
28 {
29         int32_t val;
30         asm volatile("movl %1,%0" : "=r"(val) : "m"(*number));
31         return val;
32 }
33
34 static inline void atomic_set(atomic_t *number, int32_t val)
35 {
36         asm volatile("movl %1,%0" : "=m"(*number) : "r"(val));
37 }
38
39 // need to do this with pointers and deref.  %0 needs to be the memory address
40 static inline void atomic_inc(atomic_t *number)
41 {
42         asm volatile("lock incl %0" : "=m"(*number) : : "cc");
43 }
44
45 static inline void atomic_dec(atomic_t *number)
46 {
47         asm volatile("lock decl %0" : "=m"(*number) : : "cc");
48 }
49
50 static inline void atomic_andb(volatile uint8_t *number, uint8_t mask)
51 {
52         asm volatile("lock andb %1,%0" : "=m"(*number) : "r"(mask) : "cc");
53 }
54
55
56 static inline void spin_lock(volatile uint32_t* lock)
57 {
58         asm volatile(
59                         "1:                       "
60                         "       cmpb $0, %0;          "
61                         "       je 2f;                "
62                         "       pause;                "
63                         "       jmp 1b;               "
64                         "2:                       " 
65                         "       movb $1, %%al;        "
66                         "       xchgb %%al, %0;       "
67                         "       cmpb $0, %%al;        "
68                         "       jne 1b;               "
69                 : : "m"(*lock) : "eax", "cc");
70 }
71
72 static inline void spin_unlock(volatile uint32_t* lock)
73 {
74         *lock = 0;
75 }
76
77 #endif /* !ROS_INCLUDE_ATOMIC_H */