diff --git a/source/lib/debug.cpp b/source/lib/debug.cpp index 65cb64ea2c..215c68f224 100644 --- a/source/lib/debug.cpp +++ b/source/lib/debug.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -26,7 +26,6 @@ #include "lib/alignment.h" #include "lib/app_hooks.h" #include "lib/fnv_hash.h" -#include "lib/sysdep/cpu.h" // cpu_CAS #include "lib/sysdep/sysdep.h" #include "lib/sysdep/vm.h" @@ -343,11 +342,11 @@ void debug_DisplayMessage(const wchar_t* caption, const wchar_t* msg) // errors (e.g. caused by atexit handlers) to come up, possibly causing an // infinite loop. hiding errors isn't good, but we assume that whoever clicked // exit really doesn't want to see any more messages. -static atomic_bool isExiting; +static std::atomic isExiting; // this logic is applicable to any type of error. special cases such as // suppressing certain expected WARN_ERRs are done there. -static bool ShouldSuppressError(atomic_bool* suppress) +static bool ShouldSuppressError(std::atomic* suppress) { if(isExiting) return true; @@ -355,7 +354,7 @@ static bool ShouldSuppressError(atomic_bool* suppress) if(!suppress) return false; - if(*suppress == DEBUG_SUPPRESS) + if(*suppress) return true; return false; @@ -372,7 +371,7 @@ static ErrorReactionInternal CallDisplayError(const wchar_t* text, size_t flags) return er; } -static ErrorReaction PerformErrorReaction(ErrorReactionInternal er, size_t flags, atomic_bool* suppress) +static ErrorReaction PerformErrorReaction(ErrorReactionInternal er, size_t flags, std::atomic* suppress) { const bool shouldHandleBreak = (flags & DE_MANUAL_BREAK) == 0; @@ -393,12 +392,13 @@ static ErrorReaction PerformErrorReaction(ErrorReactionInternal er, size_t flags return ER_BREAK; case ERI_SUPPRESS: - (void)cpu_CAS(suppress, 0, DEBUG_SUPPRESS); + { + bool initialSuppress{ false }; + (void)suppress->compare_exchange_strong(initialSuppress, true); return ER_CONTINUE; - + } case ERI_EXIT: - isExiting = 1; // see declaration - COMPILER_FENCE; + isExiting = true; // see declaration exit(EXIT_FAILURE); @@ -412,7 +412,7 @@ static ErrorReaction PerformErrorReaction(ErrorReactionInternal er, size_t flags ErrorReaction debug_DisplayError(const wchar_t* description, size_t flags, void* context, const wchar_t* lastFuncToSkip, const wchar_t* pathname, int line, const char* func, - atomic_bool* suppress) + std::atomic* suppress) { // "suppressing" this error means doing nothing and returning ER_CONTINUE. if(ShouldSuppressError(suppress)) @@ -511,7 +511,7 @@ static bool ShouldSkipError(Status err) return false; } -ErrorReaction debug_OnError(Status err, atomic_bool* suppress, const wchar_t* file, int line, const char* func) +ErrorReaction debug_OnError(Status err, std::atomic* suppress, const wchar_t* file, int line, const char* func) { CACHE_ALIGNED(u8) context[DEBUG_CONTEXT_SIZE]; (void)debug_CaptureContext(context); @@ -526,7 +526,7 @@ ErrorReaction debug_OnError(Status err, atomic_bool* suppress, const wchar_t* fi return debug_DisplayError(buf, DE_MANUAL_BREAK, context, lastFuncToSkip, file,line,func, suppress); } -ErrorReaction debug_OnAssertionFailure(const wchar_t* expr, atomic_bool* suppress, const wchar_t* file, int line, const char* func) +ErrorReaction debug_OnAssertionFailure(const wchar_t* expr, std::atomic* suppress, const wchar_t* file, int line, const char* func) { CACHE_ALIGNED(u8) context[DEBUG_CONTEXT_SIZE]; (void)debug_CaptureContext(context); diff --git a/source/lib/debug.h b/source/lib/debug.h index bab9300657..6c117bc984 100644 --- a/source/lib/debug.h +++ b/source/lib/debug.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2024 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -42,6 +42,8 @@ #include "lib/status.h" #include "lib/types.h" +#include + /** * trigger a breakpoint when reached/"called". * if defined as a macro, the debugger can break directly into the @@ -108,21 +110,6 @@ enum DebugDisplayErrorFlags DE_NO_DEBUG_INFO = 8 }; -/** - * a bool that is reasonably certain to be set atomically. - * we cannot assume support for OpenMP (requires GCC 4.2) or C++0x, - * so we'll have to resort to intptr_t, cpu_CAS and COMPILER_FENCE. - **/ -typedef volatile intptr_t atomic_bool; - -/** - * value for suppress flag once set by debug_DisplayError. - * rationale: this value is fairly distinctive and helps when - * debugging the symbol engine. - * use 0 as the initial value to avoid allocating .rdata space. - **/ -static const atomic_bool DEBUG_SUPPRESS = 0xAB; - /** * choices offered by the error dialog that are returned * by debug_DisplayError. @@ -187,10 +174,10 @@ enum ErrorReactionInternal * suppress this error. if NULL, this functionality is skipped and the * "Suppress" dialog button will be disabled. * note: this flag is read and written exclusively here; caller only - * provides the storage. values: see DEBUG_SUPPRESS above. + * provides the storage. * @return ErrorReaction (user's choice: continue running or stop?) **/ -ErrorReaction debug_DisplayError(const wchar_t* description, size_t flags, void* context, const wchar_t* lastFuncToSkip, const wchar_t* file, int line, const char* func, atomic_bool* suppress); +ErrorReaction debug_DisplayError(const wchar_t* description, size_t flags, void* context, const wchar_t* lastFuncToSkip, const wchar_t* file, int line, const char* func, std::atomic* suppress); // simplified version for just displaying an error message #define DEBUG_DISPLAY_ERROR_IMPL(description, flags)\ @@ -290,7 +277,7 @@ Status debug_WriteCrashlog(const char* text); #define ENSURE(expr)\ do\ {\ - static atomic_bool suppress__;\ + static std::atomic suppress__{ false };\ if(!(expr))\ {\ switch(debug_OnAssertionFailure(WIDEN(#expr), &suppress__, WIDEN(__FILE__), __LINE__, __func__))\ @@ -339,7 +326,7 @@ Status debug_WriteCrashlog(const char* text); #define DEBUG_WARN_ERR(status)\ do\ {\ - static atomic_bool suppress__;\ + static std::atomic suppress__{ false };\ switch(debug_OnError(status, &suppress__, WIDEN(__FILE__), __LINE__, __func__))\ {\ case ER_CONTINUE:\ @@ -363,7 +350,7 @@ Status debug_WriteCrashlog(const char* text); * @param func name of the function containing it * @return ErrorReaction (user's choice: continue running or stop?) **/ -ErrorReaction debug_OnAssertionFailure(const wchar_t* assert_expr, atomic_bool* suppress, const wchar_t* file, int line, const char* func) ANALYZER_NORETURN; +ErrorReaction debug_OnAssertionFailure(const wchar_t* assert_expr, std::atomic* suppress, const wchar_t* file, int line, const char* func) ANALYZER_NORETURN; /** * called when a DEBUG_WARN_ERR indicates an error occurred; @@ -375,7 +362,7 @@ ErrorReaction debug_OnAssertionFailure(const wchar_t* assert_expr, atomic_bool* * @param func name of the function containing it * @return ErrorReaction (user's choice: continue running or stop?) **/ -ErrorReaction debug_OnError(Status err, atomic_bool* suppress, const wchar_t* file, int line, const char* func) ANALYZER_NORETURN; +ErrorReaction debug_OnError(Status err, std::atomic* suppress, const wchar_t* file, int line, const char* func) ANALYZER_NORETURN; /**