Skip to content

Commit f9cbaf5

Browse files
committed
libc/atomic: decoupling atomic and spinlock to avoid recursion
1. use irq save in AMP mode 2. use critical section in SMP mode Signed-off-by: chao an <anchao@lixiang.com>
1 parent 1bba720 commit f9cbaf5

File tree

1 file changed

+63
-37
lines changed

1 file changed

+63
-37
lines changed

libs/libc/machine/arch_atomic.c

Lines changed: 63 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,33 @@
2828

2929
#include <stdbool.h>
3030
#include <stdint.h>
31-
#include <nuttx/spinlock.h>
31+
#include <nuttx/irq.h>
32+
33+
/****************************************************************************
34+
* Private Data
35+
****************************************************************************/
36+
37+
#ifdef CONFIG_SMP
38+
static inline_function irqstate_t atomic_lock(void)
39+
{
40+
return enter_critical_section();
41+
}
42+
43+
static inline_function void atomic_unlock(irqstate_t flags)
44+
{
45+
leave_critical_section(flags);
46+
}
47+
#else
48+
static inline_function irqstate_t atomic_lock(void)
49+
{
50+
return up_irq_save();
51+
}
52+
53+
static inline_function void atomic_unlock(irqstate_t flags)
54+
{
55+
up_irq_restore(flags);
56+
}
57+
#endif
3258

3359
/****************************************************************************
3460
* Pre-processor Definitions
@@ -39,23 +65,23 @@
3965
void weak_function __atomic_store_##n (FAR volatile void *ptr, \
4066
type value, int memorder) \
4167
{ \
42-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
68+
irqstate_t irqstate = atomic_lock(); \
4369
\
4470
*(FAR type *)ptr = value; \
4571
\
46-
spin_unlock_irqrestore(NULL, irqstate); \
72+
atomic_unlock(irqstate); \
4773
}
4874

4975
#define LOAD(n, type) \
5076
\
5177
type weak_function __atomic_load_##n (FAR const volatile void *ptr, \
5278
int memorder) \
5379
{ \
54-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
80+
irqstate_t irqstate = atomic_lock(); \
5581
\
5682
type ret = *(FAR type *)ptr; \
5783
\
58-
spin_unlock_irqrestore(NULL, irqstate); \
84+
atomic_unlock(irqstate); \
5985
return ret; \
6086
}
6187

@@ -64,13 +90,13 @@
6490
type weak_function __atomic_exchange_##n (FAR volatile void *ptr, \
6591
type value, int memorder) \
6692
{ \
67-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
93+
irqstate_t irqstate = atomic_lock(); \
6894
FAR type *tmp = (FAR type *)ptr; \
6995
\
7096
type ret = *tmp; \
7197
*tmp = value; \
7298
\
73-
spin_unlock_irqrestore(NULL, irqstate); \
99+
atomic_unlock(irqstate); \
74100
return ret; \
75101
}
76102

@@ -82,7 +108,7 @@
82108
int success, int failure) \
83109
{ \
84110
bool ret = false; \
85-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
111+
irqstate_t irqstate = atomic_lock(); \
86112
FAR type *tmpmem = (FAR type *)mem; \
87113
FAR type *tmpexp = (FAR type *)expect; \
88114
\
@@ -96,7 +122,7 @@
96122
*tmpexp = *tmpmem; \
97123
} \
98124
\
99-
spin_unlock_irqrestore(NULL, irqstate); \
125+
atomic_unlock(irqstate); \
100126
return ret; \
101127
}
102128

@@ -105,13 +131,13 @@
105131
type weak_function __atomic_flags_test_and_set##n (FAR volatile void *ptr, \
106132
int memorder) \
107133
{ \
108-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
134+
irqstate_t irqstate = atomic_lock(); \
109135
FAR type *tmp = (FAR type *)ptr; \
110136
type ret = *tmp; \
111137
\
112138
*(FAR type *)ptr = 1; \
113139
\
114-
spin_unlock_irqrestore(NULL, irqstate); \
140+
atomic_unlock(irqstate); \
115141
return ret; \
116142
}
117143

@@ -120,13 +146,13 @@
120146
type weak_function __atomic_fetch_add_##n (FAR volatile void *ptr, \
121147
type value, int memorder) \
122148
{ \
123-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
149+
irqstate_t irqstate = atomic_lock(); \
124150
FAR type *tmp = (FAR type *)ptr; \
125151
type ret = *tmp; \
126152
\
127153
*tmp = *tmp + value; \
128154
\
129-
spin_unlock_irqrestore(NULL, irqstate); \
155+
atomic_unlock(irqstate); \
130156
return ret; \
131157
}
132158

@@ -135,13 +161,13 @@
135161
type weak_function __atomic_fetch_sub_##n (FAR volatile void *ptr, \
136162
type value, int memorder) \
137163
{ \
138-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
164+
irqstate_t irqstate = atomic_lock(); \
139165
FAR type *tmp = (FAR type *)ptr; \
140166
type ret = *tmp; \
141167
\
142168
*tmp = *tmp - value; \
143169
\
144-
spin_unlock_irqrestore(NULL, irqstate); \
170+
atomic_unlock(irqstate); \
145171
return ret; \
146172
}
147173

@@ -150,13 +176,13 @@
150176
type weak_function __atomic_fetch_and_##n (FAR volatile void *ptr, \
151177
type value, int memorder) \
152178
{ \
153-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
179+
irqstate_t irqstate = atomic_lock(); \
154180
FAR type *tmp = (FAR type *)ptr; \
155181
type ret = *tmp; \
156182
\
157183
*tmp = *tmp & value; \
158184
\
159-
spin_unlock_irqrestore(NULL, irqstate); \
185+
atomic_unlock(irqstate); \
160186
return ret; \
161187
}
162188

@@ -165,13 +191,13 @@
165191
type weak_function __atomic_fetch_or_##n (FAR volatile void *ptr, \
166192
type value, int memorder) \
167193
{ \
168-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
194+
irqstate_t irqstate = atomic_lock(); \
169195
FAR type *tmp = (FAR type *)ptr; \
170196
type ret = *tmp; \
171197
\
172198
*tmp = *tmp | value; \
173199
\
174-
spin_unlock_irqrestore(NULL, irqstate); \
200+
atomic_unlock(irqstate); \
175201
return ret; \
176202
}
177203

@@ -180,13 +206,13 @@
180206
type weak_function __atomic_fetch_xor_##n (FAR volatile void *ptr, \
181207
type value, int memorder) \
182208
{ \
183-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
209+
irqstate_t irqstate = atomic_lock(); \
184210
FAR type *tmp = (FAR type *)ptr; \
185211
type ret = *tmp; \
186212
\
187213
*tmp = *tmp ^ value; \
188214
\
189-
spin_unlock_irqrestore(NULL, irqstate); \
215+
atomic_unlock(irqstate); \
190216
return ret; \
191217
}
192218

@@ -195,12 +221,12 @@
195221
type weak_function __sync_add_and_fetch_##n (FAR volatile void *ptr, \
196222
type value) \
197223
{ \
198-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
224+
irqstate_t irqstate = atomic_lock(); \
199225
FAR type *tmp = (FAR type *)ptr; \
200226
\
201227
*tmp = *tmp + value; \
202228
\
203-
spin_unlock_irqrestore(NULL, irqstate); \
229+
atomic_unlock(irqstate); \
204230
return *tmp; \
205231
}
206232

@@ -209,12 +235,12 @@
209235
type weak_function __sync_sub_and_fetch_##n (FAR volatile void *ptr, \
210236
type value) \
211237
{ \
212-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
238+
irqstate_t irqstate = atomic_lock(); \
213239
FAR type *tmp = (FAR type *)ptr; \
214240
\
215241
*tmp = *tmp - value; \
216242
\
217-
spin_unlock_irqrestore(NULL, irqstate); \
243+
atomic_unlock(irqstate); \
218244
return *tmp; \
219245
}
220246

@@ -223,12 +249,12 @@
223249
type weak_function __sync_or_and_fetch_##n (FAR volatile void *ptr, \
224250
type value) \
225251
{ \
226-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
252+
irqstate_t irqstate = atomic_lock(); \
227253
FAR type *tmp = (FAR type *)ptr; \
228254
\
229255
*tmp = *tmp | value; \
230256
\
231-
spin_unlock_irqrestore(NULL, irqstate); \
257+
atomic_unlock(irqstate); \
232258
return *tmp; \
233259
}
234260

@@ -237,12 +263,12 @@
237263
type weak_function __sync_and_and_fetch_##n (FAR volatile void *ptr, \
238264
type value) \
239265
{ \
240-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
266+
irqstate_t irqstate = atomic_lock(); \
241267
FAR type *tmp = (FAR type *)ptr; \
242268
\
243269
*tmp = *tmp & value; \
244270
\
245-
spin_unlock_irqrestore(NULL, irqstate); \
271+
atomic_unlock(irqstate); \
246272
return *tmp; \
247273
}
248274

@@ -251,12 +277,12 @@
251277
type weak_function __sync_xor_and_fetch_##n (FAR volatile void *ptr, \
252278
type value) \
253279
{ \
254-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
280+
irqstate_t irqstate = atomic_lock(); \
255281
FAR type *tmp = (FAR type *)ptr; \
256282
\
257283
*tmp = *tmp ^ value; \
258284
\
259-
spin_unlock_irqrestore(NULL, irqstate); \
285+
atomic_unlock(irqstate); \
260286
return *tmp; \
261287
}
262288

@@ -265,12 +291,12 @@
265291
type weak_function __sync_nand_and_fetch_##n (FAR volatile void *ptr, \
266292
type value) \
267293
{ \
268-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
294+
irqstate_t irqstate = atomic_lock(); \
269295
FAR type *tmp = (FAR type *)ptr; \
270296
\
271297
*tmp = ~(*tmp & value); \
272298
\
273-
spin_unlock_irqrestore(NULL, irqstate); \
299+
atomic_unlock(irqstate); \
274300
return *tmp; \
275301
}
276302

@@ -281,7 +307,7 @@
281307
type newvalue) \
282308
{ \
283309
bool ret = false; \
284-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
310+
irqstate_t irqstate = atomic_lock(); \
285311
FAR type *tmp = (FAR type *)ptr; \
286312
\
287313
if (*tmp == oldvalue) \
@@ -290,7 +316,7 @@
290316
*tmp = newvalue; \
291317
} \
292318
\
293-
spin_unlock_irqrestore(NULL, irqstate); \
319+
atomic_unlock(irqstate); \
294320
return ret; \
295321
}
296322

@@ -300,7 +326,7 @@
300326
type oldvalue, \
301327
type newvalue) \
302328
{ \
303-
irqstate_t irqstate = spin_lock_irqsave(NULL); \
329+
irqstate_t irqstate = atomic_lock(); \
304330
FAR type *tmp = (FAR type *)ptr; \
305331
type ret = *tmp; \
306332
\
@@ -309,7 +335,7 @@
309335
*tmp = newvalue; \
310336
} \
311337
\
312-
spin_unlock_irqrestore(NULL, irqstate); \
338+
atomic_unlock(irqstate); \
313339
return ret; \
314340
}
315341

0 commit comments

Comments
 (0)