Revision | a13b4d8aabe9b525fa280f4a240e89d991d7f106 (tree) |
---|---|
Time | 2022-07-20 18:47:17 |
Author | Vladimir Murzin <vladimir.murzin@arm....> |
Commiter | Waldemar Brodkorb |
linuxthreads/arm: fix ldrex/strex loop when built with O0
O0 build result in the following codegen
00000000 <ldrex>:
0000001e <strex>:
00000040 <testandset>:
ARM ARM suggests that LoadExcl/StoreExcl loops are guaranteed to make
forward progress only if, for any LoadExcl/StoreExcl loop within a
single thread of execution, the software meets all of the following
conditions:
1 Between the Load-Exclusive and the Store-Exclusive, there are no
...
Obviously condition is not met for O0 builds.
O2 build (which is highly likely the most common setting) able to do
the right thing resulting in
00000000 <ldrex>:
00000008 <strex>:
00000010 <testandset>:
Rather than depending on level of optimisation implement whole
ldrex/strex loop in inline assembly.
Signed-off-by: Vladimir Murzin <vladimir.murzin@arm.com>
@@ -29,35 +29,19 @@ | ||
29 | 29 | #endif |
30 | 30 | |
31 | 31 | #if defined(__thumb2__) |
32 | -PT_EI long int ldrex(int *spinlock) | |
33 | -{ | |
34 | - long int ret; | |
35 | - __asm__ __volatile__( | |
36 | - "ldrex %0, [%1]\n" | |
37 | - : "=r"(ret) | |
38 | - : "r"(spinlock) : "memory"); | |
39 | - return ret; | |
40 | -} | |
41 | - | |
42 | -PT_EI long int strex(int val, int *spinlock) | |
43 | -{ | |
44 | - long int ret; | |
45 | - __asm__ __volatile__( | |
46 | - "strex %0, %1, [%2]\n" | |
47 | - : "=r"(ret) | |
48 | - : "r" (val), "r"(spinlock) : "memory"); | |
49 | - return ret; | |
50 | -} | |
51 | - | |
52 | 32 | /* Spinlock implementation; required. */ |
53 | 33 | PT_EI long int |
54 | 34 | testandset (int *spinlock) |
55 | 35 | { |
56 | - register unsigned int ret; | |
57 | - | |
58 | - do { | |
59 | - ret = ldrex(spinlock); | |
60 | - } while (strex(1, spinlock)); | |
36 | + unsigned int ret, tmp, val = 1; | |
37 | + | |
38 | + __asm__ __volatile__ ( | |
39 | +"0: ldrex %0, [%2] \n" | |
40 | +" strex %1, %3, [%2] \n" | |
41 | +" cmp %1, #0 \n" | |
42 | +" bne 0b" | |
43 | + : "=&r" (ret), "=&r" (tmp) | |
44 | + : "r" (spinlock), "r" (val) : "memory", "cc"); | |
61 | 45 | |
62 | 46 | return ret; |
63 | 47 | } |