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
9static inline void
10memory_read_barrier_inline(void)
11{
12	asm volatile("lock; addl $0, (%%esp)" : : : "memory");
13}
14
15
16static inline void
17memory_write_barrier_inline(void)
18{
19	asm volatile("lock; addl $0, (%%esp)" : : : "memory");
20}
21
22
23static inline void
24memory_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
38static inline void
39atomic_set_inline(int32* value, int32 newValue)
40{
41	memory_write_barrier();
42	*(volatile int32*)value = newValue;
43}
44
45
46static inline int32
47atomic_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
57static inline int32
58atomic_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
68static inline int32
69atomic_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
79static inline int32
80atomic_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