History

atomic_load/atomic_store : to ensure return the latest value, should we add a memory barrier here?

If have no these memory barriers, sometime it will cause bug in multiple threads program.

kbkpbot committed 2 years ago

Commit 105d70f1 parent da0d4391 file · +52 −50Browse files

Unified · Split

lib/stdatomic.c+52−50
@@ -15,6 +15,56 @@ · 14 unmodified lines
15#define __ATOMIC_SEQ_CST 515#define __ATOMIC_SEQ_CST 5
16typedef __SIZE_TYPE__ size_t;16typedef __SIZE_TYPE__ size_t;
17 17
18/* uses alias to allow building with gcc/clang */
19#ifdef __TINYC__
20#define ATOMIC(x) __atomic_##x
21#else
22#define ATOMIC(x) __tcc_atomic_##x
23#endif
24
25void ATOMIC(signal_fence) (int memorder)
26{
27}
28
29void ATOMIC(thread_fence) (int memorder)
30{
31#if defined __i386__
32 __asm__ volatile("lock orl $0, (%esp)");
33#elif defined __x86_64__
34 __asm__ volatile("lock orq $0, (%rsp)");
35#elif defined __arm__
36 __asm__ volatile(".int 0xee070fba"); // mcr p15, 0, r0, c7, c10, 5
37#elif defined __aarch64__
38 __asm__ volatile(".int 0xd5033bbf"); // dmb ish
39#elif defined __riscv
40 __asm__ volatile(".int 0x0ff0000f"); // fence iorw,iorw
41#endif
42}
43
44bool ATOMIC(is_lock_free) (unsigned long size, const volatile void *ptr)
45{
46 bool ret;
47
48 switch (size) {
49 case 1: ret = true; break;
50 case 2: ret = true; break;
51 case 4: ret = true; break;
52#if defined __x86_64__ || defined __aarch64__ || defined __riscv
53 case 8: ret = true; break;
54#else
55 case 8: ret = false; break;
56#endif
57 default: ret = false; break;
58 }
59 return ret;
60}
61
62#ifndef __TINYC__
63void __atomic_signal_fence(int memorder) __attribute__((alias("__tcc_atomic_signal_fence")));
64void __atomic_thread_fence(int memorder) __attribute__((alias("__tcc_atomic_thread_fence")));
65bool __atomic_is_lock_free(unsigned long size, const volatile void *ptr) __attribute__((alias("__tcc_atomic_is_lock_free")));
66#endif
67
18#if defined __i386__ || defined __x86_64__68#if defined __i386__ || defined __x86_64__
19#define ATOMIC_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \69#define ATOMIC_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \
20 bool __atomic_compare_exchange_##MODE \70 bool __atomic_compare_exchange_##MODE \
@@ -42,6 +92,7 @@ typedef __SIZE_TYPE__ size_t; · 21 unmodified lines
42#define ATOMIC_LOAD(TYPE, MODE) \92#define ATOMIC_LOAD(TYPE, MODE) \
43 TYPE __atomic_load_##MODE(const volatile void *atom, int memorder) \93 TYPE __atomic_load_##MODE(const volatile void *atom, int memorder) \
44 { \94 { \
95 __atomic_thread_fence(__ATOMIC_ACQUIRE); \
45 return *(volatile TYPE *)atom; \96 return *(volatile TYPE *)atom; \
46 }97 }
47 98
@@ -49,6 +100,7 @@ typedef __SIZE_TYPE__ size_t; · 1 unmodified line
49 void __atomic_store_##MODE(volatile void *atom, TYPE value, int memorder) \100 void __atomic_store_##MODE(volatile void *atom, TYPE value, int memorder) \
50 { \101 { \
51 *(volatile TYPE *)atom = value; \102 *(volatile TYPE *)atom = value; \
103 __atomic_thread_fence(__ATOMIC_RELEASE); \
52 }104 }
53 105
54#define ATOMIC_GEN_OP(TYPE, MODE, NAME, OP, RET) \106#define ATOMIC_GEN_OP(TYPE, MODE, NAME, OP, RET) \
@@ -114,53 +166,3 @@ ATOMIC_GEN(uint32_t, 4, "l") · 59 unmodified lines
114#if defined __x86_64__ || defined __aarch64__ || defined __riscv166#if defined __x86_64__ || defined __aarch64__ || defined __riscv
115ATOMIC_GEN(uint64_t, 8, "q")167ATOMIC_GEN(uint64_t, 8, "q")
116#endif168#endif
117
118/* uses alias to allow building with gcc/clang */
119#ifdef __TINYC__
120#define ATOMIC(x) __atomic_##x
121#else
122#define ATOMIC(x) __tcc_atomic_##x
123#endif
124
125void ATOMIC(signal_fence) (int memorder)
126{
127}
128
129void ATOMIC(thread_fence) (int memorder)
130{
131#if defined __i386__
132 __asm__ volatile("lock orl $0, (%esp)");
133#elif defined __x86_64__
134 __asm__ volatile("lock orq $0, (%rsp)");
135#elif defined __arm__
136 __asm__ volatile(".int 0xee070fba"); // mcr p15, 0, r0, c7, c10, 5
137#elif defined __aarch64__
138 __asm__ volatile(".int 0xd5033bbf"); // dmb ish
139#elif defined __riscv
140 __asm__ volatile(".int 0x0ff0000f"); // fence iorw,iorw
141#endif
142}
143
144bool ATOMIC(is_lock_free) (unsigned long size, const volatile void *ptr)
145{
146 bool ret;
147
148 switch (size) {
149 case 1: ret = true; break;
150 case 2: ret = true; break;
151 case 4: ret = true; break;
152#if defined __x86_64__ || defined __aarch64__ || defined __riscv
153 case 8: ret = true; break;
154#else
155 case 8: ret = false; break;
156#endif
157 default: ret = false; break;
158 }
159 return ret;
160}
161
162#ifndef __TINYC__
163void __atomic_signal_fence(int memorder) __attribute__((alias("__tcc_atomic_signal_fence")));
164void __atomic_thread_fence(int memorder) __attribute__((alias("__tcc_atomic_thread_fence")));
165bool __atomic_is_lock_free(unsigned long size, const volatile void *ptr) __attribute__((alias("__tcc_atomic_is_lock_free")));
166#endif

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t