If have no these memory barriers, sometime it will cause bug in multiple threads program.
Unified · Split
| @@ -15,6 +15,56 @@ · 14 unmodified lines | ||
| 15 | 15 | #define __ATOMIC_SEQ_CST 5 |
| 16 | 16 | typedef __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 | + | |
| 25 | +void ATOMIC(signal_fence) (int memorder) | |
| 26 | +{ | |
| 27 | +} | |
| 28 | + | |
| 29 | +void 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 | + | |
| 44 | +bool 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__ | |
| 63 | +void __atomic_signal_fence(int memorder) __attribute__((alias("__tcc_atomic_signal_fence"))); | |
| 64 | +void __atomic_thread_fence(int memorder) __attribute__((alias("__tcc_atomic_thread_fence"))); | |
| 65 | +bool __atomic_is_lock_free(unsigned long size, const volatile void *ptr) __attribute__((alias("__tcc_atomic_is_lock_free"))); | |
| 66 | +#endif | |
| 67 | + | |
| 18 | 68 | #if defined __i386__ || defined __x86_64__ |
| 19 | 69 | #define ATOMIC_COMPARE_EXCHANGE(TYPE, MODE, SUFFIX) \ |
| 20 | 70 | bool __atomic_compare_exchange_##MODE \ |
| @@ -42,6 +92,7 @@ typedef __SIZE_TYPE__ size_t; · 21 unmodified lines | ||
| 42 | 92 | #define ATOMIC_LOAD(TYPE, MODE) \ |
| 43 | 93 | TYPE __atomic_load_##MODE(const volatile void *atom, int memorder) \ |
| 44 | 94 | { \ |
| 95 | + __atomic_thread_fence(__ATOMIC_ACQUIRE); \ | |
| 45 | 96 | return *(volatile TYPE *)atom; \ |
| 46 | 97 | } |
| 47 | 98 | |
| @@ -49,6 +100,7 @@ typedef __SIZE_TYPE__ size_t; · 1 unmodified line | ||
| 49 | 100 | void __atomic_store_##MODE(volatile void *atom, TYPE value, int memorder) \ |
| 50 | 101 | { \ |
| 51 | 102 | *(volatile TYPE *)atom = value; \ |
| 103 | + __atomic_thread_fence(__ATOMIC_RELEASE); \ | |
| 52 | 104 | } |
| 53 | 105 | |
| 54 | 106 | #define ATOMIC_GEN_OP(TYPE, MODE, NAME, OP, RET) \ |
| @@ -114,53 +166,3 @@ ATOMIC_GEN(uint32_t, 4, "l") · 59 unmodified lines | ||
| 114 | 166 | #if defined __x86_64__ || defined __aarch64__ || defined __riscv |
| 115 | 167 | ATOMIC_GEN(uint64_t, 8, "q") |
| 116 | 168 | #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 | − | |
| 125 | −void ATOMIC(signal_fence) (int memorder) | |
| 126 | −{ | |
| 127 | −} | |
| 128 | − | |
| 129 | −void 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 | − | |
| 144 | −bool 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__ | |
| 163 | −void __atomic_signal_fence(int memorder) __attribute__((alias("__tcc_atomic_signal_fence"))); | |
| 164 | −void __atomic_thread_fence(int memorder) __attribute__((alias("__tcc_atomic_thread_fence"))); | |
| 165 | −bool __atomic_is_lock_free(unsigned long size, const volatile void *ptr) __attribute__((alias("__tcc_atomic_is_lock_free"))); | |
| 166 | −#endif | |