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