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