From 16e699a76155b8babb51e14d03b1c65eb6c589bb Mon Sep 17 00:00:00 2001
From: David Carlier <[EMAIL REDACTED]>
Date: Mon, 1 Aug 2022 07:59:04 +0100
Subject: [PATCH] Proposing exposing as public api the various arch dependent
pause instructions so could be used in app infinite loops. A handful of games
do already so we unify it in one place.
---
include/SDL_atomic.h | 20 ++++++++++++++++++++
src/atomic/SDL_spinlock.c | 21 +--------------------
2 files changed, 21 insertions(+), 20 deletions(-)
diff --git a/include/SDL_atomic.h b/include/SDL_atomic.h
index b29ceeac2af..2eace20869a 100644
--- a/include/SDL_atomic.h
+++ b/include/SDL_atomic.h
@@ -237,6 +237,26 @@ typedef void (*SDL_KernelMemoryBarrierFunc)();
#endif
#endif
+/* "REP NOP" is PAUSE, coded for tools that don't know it by that name. */
+#if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
+ #define SDL_CPUPauseInstruction() __asm__ __volatile__("pause\n") /* Some assemblers can't do REP NOP, so go with PAUSE. */
+#elif (defined(__arm__) && __ARM_ARCH__ >= 7) || defined(__aarch64__)
+ #define SDL_CPUPauseInstruction() __asm__ __volatile__("yield" ::: "memory")
+#elif (defined(__powerpc__) || defined(__powerpc64__))
+ #define SDL_CPUPauseInstruction() __asm__ __volatile__("or 27,27,27");
+#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+ #define SDL_CPUPauseInstruction() _mm_pause() /* this is actually "rep nop" and not a SIMD instruction. No inline asm in MSVC x86-64! */
+#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
+ #define SDL_CPUPauseInstruction() __yield()
+#elif defined(__WATCOMC__) && defined(__386__)
+ /* watcom assembler rejects PAUSE if CPU < i686, and it refuses REP NOP as an invalid combination. Hardcode the bytes. */
+ extern __inline void SDL_CPUPauseInstruction(void);
+ #pragma aux SDL_CPUPauseInstruction = "db 0f3h,90h"
+#else
+ #define SDL_CPUPauseInstruction()
+#endif
+
+
/**
* \brief A type representing an atomic integer value. It is a struct
* so people don't accidentally use numeric operations on it.
diff --git a/src/atomic/SDL_spinlock.c b/src/atomic/SDL_spinlock.c
index cbe5445f10c..965c021e19a 100644
--- a/src/atomic/SDL_spinlock.c
+++ b/src/atomic/SDL_spinlock.c
@@ -158,25 +158,6 @@ SDL_AtomicTryLock(SDL_SpinLock *lock)
#endif
}
-/* "REP NOP" is PAUSE, coded for tools that don't know it by that name. */
-#if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
- #define PAUSE_INSTRUCTION() __asm__ __volatile__("pause\n") /* Some assemblers can't do REP NOP, so go with PAUSE. */
-#elif (defined(__arm__) && __ARM_ARCH__ >= 7) || defined(__aarch64__)
- #define PAUSE_INSTRUCTION() __asm__ __volatile__("yield" ::: "memory")
-#elif (defined(__powerpc__) || defined(__powerpc64__))
- #define PAUSE_INSTRUCTION() __asm__ __volatile__("or 27,27,27");
-#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
- #define PAUSE_INSTRUCTION() _mm_pause() /* this is actually "rep nop" and not a SIMD instruction. No inline asm in MSVC x86-64! */
-#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
- #define PAUSE_INSTRUCTION() __yield()
-#elif defined(__WATCOMC__) && defined(__386__)
- /* watcom assembler rejects PAUSE if CPU < i686, and it refuses REP NOP as an invalid combination. Hardcode the bytes. */
- extern __inline void PAUSE_INSTRUCTION(void);
- #pragma aux PAUSE_INSTRUCTION = "db 0f3h,90h"
-#else
- #define PAUSE_INSTRUCTION()
-#endif
-
void
SDL_AtomicLock(SDL_SpinLock *lock)
{
@@ -185,7 +166,7 @@ SDL_AtomicLock(SDL_SpinLock *lock)
while (!SDL_AtomicTryLock(lock)) {
if (iterations < 32) {
iterations++;
- PAUSE_INSTRUCTION();
+ SDL_CPUPauseInstruction();
} else {
/* !!! FIXME: this doesn't definitely give up the current timeslice, it does different things on various platforms. */
SDL_Delay(0);