xref: /DragonOS/kernel/src/common/atomic.h (revision fae6e9ade46a52976ad5d099643d51cc20876448)
1 /**
2  * @file atomic.h
3  * @author fslongjin (longjin@RinGoTek.cn)
4  * @brief 原子变量
5  * @version 0.1
6  * @date 2022-04-12
7  *
8  * @copyright Copyright (c) 2022
9  *
10  */
11 #pragma once
12 #if ARCH(I386) || ARCH(X86_64)
13 
14 #include <arch/x86_64/include/asm/cmpxchg.h>
15 
16 #define atomic_read(atomic) ((atomic)->value)               // 读取原子变量
17 #define atomic_set(atomic, val) (((atomic)->value) = (val)) // 设置原子变量的初始值
18 
19 typedef struct
20 {
21     volatile long value;
22 } atomic_t;
23 
24 /**
25  * @brief 原子变量增加值
26  *
27  * @param ato 原子变量对象
28  * @param val 要增加的值
29  */
30 inline void atomic_add(atomic_t *ato, long val)
31 {
32     asm volatile("lock addq %1, %0 \n\t"
33                  : "=m"(ato->value)
34                  : "m"(val)
35                  : "memory");
36 }
37 
38 /**
39  * @brief 原子变量减少值
40  *
41  * @param ato 原子变量对象
42  * @param val 要减少的值
43  */
44 inline void atomic_sub(atomic_t *ato, long val)
45 {
46     asm volatile("lock subq %1, %0  \n\t"
47                  : "=m"(ato->value)
48                  : "m"(val)
49                  : "memory");
50 }
51 
52 /**
53  * @brief 原子变量自增
54  *
55  * @param ato 原子变量对象
56  */
57 void atomic_inc(atomic_t *ato)
58 {
59     asm volatile("lock incq %0   \n\t"
60                  : "=m"(ato->value)
61                  : "m"(ato->value)
62                  : "memory");
63 }
64 
65 /**
66  * @brief 原子变量自减
67  *
68  * @param ato 原子变量对象
69  */
70 void atomic_dec(atomic_t *ato)
71 {
72     asm volatile("lock decq %0 \n\t"
73                  : "=m"(ato->value)
74                  : "m"(ato->value)
75                  : "memory");
76 }
77 
78 /**
79  * @brief 设置原子变量的mask
80  *
81  * @param ato 原子变量对象
82  */
83 inline void atomic_set_mask(atomic_t *ato, long mask)
84 {
85     __asm__ __volatile__("lock	orq	%1,	%0	\n\t"
86                          : "=m"(ato->value)
87                          : "r"(mask)
88                          : "memory");
89 }
90 
91 /**
92  * @brief 清除原子变量的mask
93  *
94  * @param ato 原子变量对象
95  */
96 inline void atomic_clear_mask(atomic_t *ato, long mask)
97 {
98     __asm__ __volatile__("lock	andq	%1,	%0	\n\t"
99                          : "=m"(ato->value)
100                          : "r"(mask)
101                          : "memory");
102 }
103 
104 // cmpxchgq 比较并交换
105 inline long atomic_cmpxchg(atomic_t *ato, long oldval, long newval)
106 {
107     bool success = arch_try_cmpxchg(&ato->value, &oldval, newval);
108     return success ? oldval : newval;
109 }
110 #endif