Skip to content

Commit c5acdf1

Browse files
committed
csky: atomic: Add conditional atomic operations' optimization
Add conditional atomic operations' optimization: - arch_atomic_fetch_add_unless - arch_atomic_inc_unless_negative - arch_atomic_dec_unless_positive - arch_atomic_dec_if_positive Comments by Boqun: FWIW, you probably need to make sure that a barrier instruction inside an lr/sc loop is a good thing. IIUC, the execution time of a barrier instruction is determined by the status of store buffers and invalidate queues (and probably other stuffs), so it may increase the execution time of the lr/sc loop, and make it unlikely to succeed. But this really depends on how the arch executes these instructions. Signed-off-by: Guo Ren <[email protected]> Signed-off-by: Guo Ren <[email protected]> Cc: Boqun Feng <[email protected]>
1 parent 6b160e0 commit c5acdf1

File tree

1 file changed

+95
-0
lines changed

1 file changed

+95
-0
lines changed

arch/csky/include/asm/atomic.h

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,101 @@ ATOMIC_OPS(xor)
100100

101101
#undef ATOMIC_FETCH_OP
102102

103+
static __always_inline int
104+
arch_atomic_fetch_add_unless(atomic_t *v, int a, int u)
105+
{
106+
int prev, tmp;
107+
108+
__asm__ __volatile__ (
109+
RELEASE_FENCE
110+
"1: ldex.w %0, (%3) \n"
111+
" cmpne %0, %4 \n"
112+
" bf 2f \n"
113+
" mov %1, %0 \n"
114+
" add %1, %2 \n"
115+
" stex.w %1, (%3) \n"
116+
" bez %1, 1b \n"
117+
FULL_FENCE
118+
"2:\n"
119+
: "=&r" (prev), "=&r" (tmp)
120+
: "r" (a), "r" (&v->counter), "r" (u)
121+
: "memory");
122+
123+
return prev;
124+
}
125+
#define arch_atomic_fetch_add_unless arch_atomic_fetch_add_unless
126+
127+
static __always_inline bool
128+
arch_atomic_inc_unless_negative(atomic_t *v)
129+
{
130+
int rc, tmp;
131+
132+
__asm__ __volatile__ (
133+
RELEASE_FENCE
134+
"1: ldex.w %0, (%2) \n"
135+
" movi %1, 0 \n"
136+
" blz %0, 2f \n"
137+
" movi %1, 1 \n"
138+
" addi %0, 1 \n"
139+
" stex.w %0, (%2) \n"
140+
" bez %0, 1b \n"
141+
FULL_FENCE
142+
"2:\n"
143+
: "=&r" (tmp), "=&r" (rc)
144+
: "r" (&v->counter)
145+
: "memory");
146+
147+
return tmp ? true : false;
148+
149+
}
150+
#define arch_atomic_inc_unless_negative arch_atomic_inc_unless_negative
151+
152+
static __always_inline bool
153+
arch_atomic_dec_unless_positive(atomic_t *v)
154+
{
155+
int rc, tmp;
156+
157+
__asm__ __volatile__ (
158+
RELEASE_FENCE
159+
"1: ldex.w %0, (%2) \n"
160+
" movi %1, 0 \n"
161+
" bhz %0, 2f \n"
162+
" movi %1, 1 \n"
163+
" subi %0, 1 \n"
164+
" stex.w %0, (%2) \n"
165+
" bez %0, 1b \n"
166+
FULL_FENCE
167+
"2:\n"
168+
: "=&r" (tmp), "=&r" (rc)
169+
: "r" (&v->counter)
170+
: "memory");
171+
172+
return tmp ? true : false;
173+
}
174+
#define arch_atomic_dec_unless_positive arch_atomic_dec_unless_positive
175+
176+
static __always_inline int
177+
arch_atomic_dec_if_positive(atomic_t *v)
178+
{
179+
int dec, tmp;
180+
181+
__asm__ __volatile__ (
182+
RELEASE_FENCE
183+
"1: ldex.w %0, (%2) \n"
184+
" subi %1, %0, 1 \n"
185+
" blz %1, 2f \n"
186+
" stex.w %1, (%2) \n"
187+
" bez %1, 1b \n"
188+
FULL_FENCE
189+
"2:\n"
190+
: "=&r" (dec), "=&r" (tmp)
191+
: "r" (&v->counter)
192+
: "memory");
193+
194+
return dec - 1;
195+
}
196+
#define arch_atomic_dec_if_positive arch_atomic_dec_if_positive
197+
103198
#define ATOMIC_OP() \
104199
static __always_inline \
105200
int arch_atomic_xchg_relaxed(atomic_t *v, int n) \

0 commit comments

Comments
 (0)