1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
|
/*
* Copyright (c) 2006-2021, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2021-04-27 peterfan Add copyright header.
*/
#include <rthw.h>
#include <stdint.h>
#include <stdbool.h>
#include <rtthread.h>
/*
* override gcc builtin atomic function for std::atomic<int64_t>, std::atomic<uint64_t>
* @see https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html
*/
uint64_t __atomic_load_8(volatile void *ptr, int memorder)
{
volatile uint64_t *val_ptr = (volatile uint64_t *)ptr;
rt_base_t level;
uint64_t tmp;
level = rt_hw_interrupt_disable();
tmp = *val_ptr;
rt_hw_interrupt_enable(level);
return tmp;
}
void __atomic_store_8(volatile void *ptr, uint64_t val, int memorder)
{
volatile uint64_t *val_ptr = (volatile uint64_t *)ptr;
rt_base_t level;
level = rt_hw_interrupt_disable();
*val_ptr = val;
rt_hw_interrupt_enable(level);
}
uint64_t __atomic_exchange_8(volatile void *ptr, uint64_t val, int memorder)
{
volatile uint64_t *val_ptr = (volatile uint64_t *)ptr;
rt_base_t level;
uint64_t tmp;
level = rt_hw_interrupt_disable();
tmp = *val_ptr;
*val_ptr = val;
rt_hw_interrupt_enable(level);
return tmp;
}
bool __atomic_compare_exchange_8(volatile void *ptr, volatile void *expected, uint64_t desired, bool weak, int success_memorder, int failure_memorder)
{
volatile uint64_t *val_ptr = (volatile uint64_t *)ptr;
volatile uint64_t *expected_ptr = (volatile uint64_t *)expected;
rt_base_t level;
bool exchanged;
level = rt_hw_interrupt_disable();
if (*val_ptr == *expected_ptr)
{
*val_ptr = desired;
exchanged = true;
}
else
{
*expected_ptr = *val_ptr;
exchanged = false;
}
rt_hw_interrupt_enable(level);
return exchanged;
}
/**
* @param size is the length of the value to load.
*
* @param mem is the source memory to load the value from.
*
* @param _return is the pointer to the space where the loaded value will be stored.
*/
void __atomic_load(size_t size, void *mem, void *_return, int model)
{
rt_base_t level;
level = rt_hw_interrupt_disable();
rt_memcpy(_return, mem, size);
rt_hw_interrupt_enable(level);
}
/**
* @param size is the length of the value to store.
*
* @param mem is the destination memory space to store the value.
*
* @param val is the pointer to the value to store.
*/
void __atomic_store(size_t size, void *mem, void *val, int model)
{
rt_base_t level;
level = rt_hw_interrupt_disable();
rt_memcpy(mem, val, size);
rt_hw_interrupt_enable(level);
}
/**
* @param size is the length of value to exchange.
*
* @param mem is the destination space to exchange.
*
* @param val is the pointer of value to exchange.
*
* @param _return gives back the the value before exchanging.
*/
void __atomic_exchange(size_t size, void *mem, void *val, void *_return, int model)
{
rt_base_t level;
level = rt_hw_interrupt_disable();
rt_memcpy(_return, mem, size);
rt_memcpy(mem, val, size);
rt_hw_interrupt_enable(level);
}
/**
* @param size is the length of value to operate.
*
* @param obj is the destination value space to operate.
*
* @param expected is the value to be compared with obj.
*
* @param desired is the value pointer to be written into obj, under the condition that *expected equals *obj.
*
* @return true if succeed in writing *desired into *obj; false if not.
*/
bool __atomic_compare_exchange(size_t size, void *obj, void *expected, void *desired, int success, int failure)
{
rt_base_t level;
volatile bool exchanged = false;
level = rt_hw_interrupt_disable();
if (rt_memcmp(obj, expected, size) == 0)
{
rt_memcpy(obj, desired, size);
exchanged = true;
}
else
{
rt_memcpy(expected, obj, size);
exchanged = false;
}
rt_hw_interrupt_enable(level);
return exchanged;
}
#define __atomic_fetch_op_8(OPNAME, OP) \
uint64_t __atomic_fetch_##OPNAME##_8(volatile void *ptr, uint64_t val, int memorder) {\
volatile uint64_t* val_ptr = (volatile uint64_t*)ptr;\
rt_base_t level;\
uint64_t tmp;\
level = rt_hw_interrupt_disable();\
tmp = *val_ptr;\
*val_ptr OP##= val;\
rt_hw_interrupt_enable(level);\
return tmp;\
}
__atomic_fetch_op_8(add, +)
__atomic_fetch_op_8(sub, -)
__atomic_fetch_op_8( and, &)
__atomic_fetch_op_8( or, |)
__atomic_fetch_op_8(xor, ^)
|