Subject: Restricts cpu yield instructions a little.
Forwarded: https://github.com/microsoft/mimalloc/pull/350
From: Ryan Pavlik <ryan.pavlik@collabora.com>
Last-Update: 2021-02-11
Applied-Upstream: 3.0.0, https://github.com/solvespace/solvespace/commit/cdeb6c90fb753a2b0f6d033affedbcceab046758


adding clobber for ARM and preventing older 32 bits chips not supporting this instruction.

Backport of https://github.com/microsoft/mimalloc/commit/33a10b48605f8bb419487a03125815ad6ee00a70

Enhanced via https://github.com/mr-c/misc/wiki/pause-techniques-on-many-architectures

---
 extlib/mimalloc/include/mimalloc-atomic.h | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

--- solvespace.orig/extlib/mimalloc/include/mimalloc-atomic.h
+++ solvespace/extlib/mimalloc/include/mimalloc-atomic.h
@@ -266,17 +266,37 @@
   static inline void mi_atomic_yield(void) {
     std::this_thread::yield();
   }
-#elif (defined(__GNUC__) || defined(__clang__)) && \
-      (defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__))
-#if defined(__x86_64__) || defined(__i386__)
+#elif defined(__SSE2__)  // AMD and Intel
+  #include <emmintrin.h>
+  static inline void mi_atomic_yield(void) {
+    _mm_pause();
+  }
+#elif defined(__x86_64__) || defined(__i386__)
   static inline void mi_atomic_yield(void) {
     asm volatile ("pause" ::: "memory");
   }
-#elif defined(__arm__) || defined(__aarch64__)
+#elif defined(__aarch64__)
+  static inline void mi_atomic_yield(void) {
+    asm volatile("wfe");
+  }
+#elif defined(__arm__) && __ARM_ARCH__ >= 7
+  static inline void mi_atomic_yield(void) {
+    __asm__ volatile("yield" ::: "memory");
+  }
+#elif defined(__armel__) || defined(__ARMEL__)
+  static inline void mi_atomic_yield(void) {
+    asm volatile ("nop" ::: "memory");  // default operation - does nothing => Might lead to passive spinning.
+  }
+#elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) // PowerPC
+  static inline void mi_atomic_yield(void) {
+     __asm__ __volatile__ ("or 27,27,27" ::: "memory");
+  }
+#elif defined(__sun)
+  // Fallback for other archs
+  #include <synch.h>
   static inline void mi_atomic_yield(void) {
-    asm volatile("yield");
+    smt_pause();
   }
-#endif
 #elif defined(__wasi__)
   #include <sched.h>
   static inline void mi_atomic_yield(void) {
