1 /*
2 * Copyright 2014, Paweł Dziepak, pdziepak@quarnos.org.
3 * Distributed under the terms of the MIT License.
4 */
5 #ifndef _KERNEL_ARCH_X86_32_ATOMIC_H
6 #define _KERNEL_ARCH_X86_32_ATOMIC_H
7
8
9 static inline void
memory_read_barrier_inline(void)10 memory_read_barrier_inline(void)
11 {
12 asm volatile("lock; addl $0, (%%esp)" : : : "memory");
13 }
14
15
16 static inline void
memory_write_barrier_inline(void)17 memory_write_barrier_inline(void)
18 {
19 asm volatile("lock; addl $0, (%%esp)" : : : "memory");
20 }
21
22
23 static inline void
memory_full_barrier_inline(void)24 memory_full_barrier_inline(void)
25 {
26 asm volatile("lock; addl $0, (%%esp)" : : : "memory");
27 }
28
29
30 #define memory_read_barrier memory_read_barrier_inline
31 #define memory_write_barrier memory_write_barrier_inline
32 #define memory_full_barrier memory_full_barrier_inline
33
34
35 #if __GNUC__ < 4
36
37
38 static inline void
atomic_set_inline(int32 * value,int32 newValue)39 atomic_set_inline(int32* value, int32 newValue)
40 {
41 memory_write_barrier();
42 *(volatile int32*)value = newValue;
43 }
44
45
46 static inline int32
atomic_get_and_set_inline(int32 * value,int32 newValue)47 atomic_get_and_set_inline(int32* value, int32 newValue)
48 {
49 asm volatile("xchgl %0, (%1)"
50 : "+r" (newValue)
51 : "r" (value)
52 : "memory");
53 return newValue;
54 }
55
56
57 static inline int32
atomic_test_and_set_inline(int32 * value,int32 newValue,int32 testAgainst)58 atomic_test_and_set_inline(int32* value, int32 newValue, int32 testAgainst)
59 {
60 asm volatile("lock; cmpxchgl %2, (%3)"
61 : "=a" (newValue)
62 : "0" (testAgainst), "r" (newValue), "r" (value)
63 : "memory");
64 return newValue;
65 }
66
67
68 static inline int32
atomic_add_inline(int32 * value,int32 newValue)69 atomic_add_inline(int32* value, int32 newValue)
70 {
71 asm volatile("lock; xaddl %0, (%1)"
72 : "+r" (newValue)
73 : "r" (value)
74 : "memory");
75 return newValue;
76 }
77
78
79 static inline int32
atomic_get_inline(int32 * value)80 atomic_get_inline(int32* value)
81 {
82 int32 newValue = *(volatile int32*)value;
83 memory_read_barrier();
84 return newValue;
85 }
86
87
88 #define atomic_set atomic_set_inline
89 #define atomic_get_and_set atomic_get_and_set_inline
90 #define atomic_test_and_set atomic_test_and_set_inline
91 #define atomic_add atomic_add_inline
92 #define atomic_get atomic_get_inline
93
94
95 #endif // dark ages
96
97
98 #endif // _KERNEL_ARCH_X86_32_ATOMIC_H
99
100