diff --git a/source/lib/debug.cpp b/source/lib/debug.cpp index d55bcae83c..b186614af7 100644 --- a/source/lib/debug.cpp +++ b/source/lib/debug.cpp @@ -55,40 +55,6 @@ ERROR_ASSOCIATE(ERR::SYM_SINGLE_SYMBOL_LIMIT, L"Symbol has produced too much out ERROR_ASSOCIATE(INFO::SYM_SUPPRESS_OUTPUT, L"Symbol was suppressed", -1); -// needed when writing crashlog -static const size_t LOG_CHARS = 16384; -wchar_t debug_log[LOG_CHARS]; -wchar_t* debug_log_pos = debug_log; - -// write to memory buffer (fast) -void debug_wprintf_mem(const wchar_t* fmt, ...) -{ - const ssize_t charsLeft = (ssize_t)(LOG_CHARS - (debug_log_pos-debug_log)); - debug_assert(charsLeft >= 0); - - // potentially not enough room for the new string; throw away the - // older half of the log. we still protect against overflow below. - if(charsLeft < 512) - { - const size_t copySize = sizeof(wchar_t) * LOG_CHARS/2; - wchar_t* const middle = &debug_log[LOG_CHARS/2]; - memcpy(debug_log, middle, copySize); - memset(middle, 0, copySize); - debug_log_pos -= LOG_CHARS/2; // don't assign middle (may leave gap) - } - - // write into buffer (in-place) - va_list args; - va_start(args, fmt); - int len = vswprintf_s(debug_log_pos, charsLeft-2, fmt, args); - - va_end(args); - debug_log_pos += len+2; - wcscpy_s(debug_log_pos-2, 3, L"\r\n"); -} - - - // need to shoehorn printf-style variable params into // the OutputDebugString call. // - don't want to split into multiple calls - would add newlines to output. @@ -224,8 +190,6 @@ LibError debug_WriteCrashlog(const wchar_t* text) // allow user to bundle whatever information they want ah_bundle_logs(f); - fwprintf(f, L"Last known activity:\n\n %ls\n", debug_log); - fclose(f); state = IDLE; return INFO::OK; @@ -383,11 +347,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 bool isExiting; +static atomic_bool 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(u8* suppress) +static bool ShouldSuppressError(atomic_bool* suppress) { if(isExiting) return true; @@ -412,7 +376,7 @@ static ErrorReaction CallDisplayError(const wchar_t* text, size_t flags) return er; } -static ErrorReaction PerformErrorReaction(ErrorReaction er, size_t flags, u8* suppress) +static ErrorReaction PerformErrorReaction(ErrorReaction er, size_t flags, atomic_bool* suppress) { const bool shouldHandleBreak = (flags & DE_MANUAL_BREAK) == 0; @@ -429,12 +393,13 @@ static ErrorReaction PerformErrorReaction(ErrorReaction er, size_t flags, u8* su break; case ER_SUPPRESS: - *suppress = DEBUG_SUPPRESS; + (void)cpu_CAS(suppress, 0, DEBUG_SUPPRESS); er = ER_CONTINUE; break; case ER_EXIT: - isExiting = true; // see declaration + isExiting = 1; // see declaration + COMPILER_FENCE; #if OS_WIN // prevent (slow) heap reporting since we're exiting abnormally and @@ -451,7 +416,7 @@ static ErrorReaction PerformErrorReaction(ErrorReaction er, size_t flags, u8* su 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, - u8* suppress) + atomic_bool* suppress) { // "suppressing" this error means doing nothing and returning ER_CONTINUE. if(ShouldSuppressError(suppress)) @@ -500,7 +465,7 @@ enum SkipStatus { INVALID, VALID, BUSY }; -static intptr_t skipStatus = INVALID; // cpu_CAS requires uintptr_t +static intptr_t skipStatus = INVALID; static LibError errorToSkip; static size_t numSkipped; @@ -547,7 +512,7 @@ static bool ShouldSkipError(LibError err) } -ErrorReaction debug_OnError(LibError err, u8* suppress, const wchar_t* file, int line, const char* func) +ErrorReaction debug_OnError(LibError err, atomic_bool* suppress, const wchar_t* file, int line, const char* func) { if(ShouldSkipError(err)) return ER_CONTINUE; @@ -561,7 +526,7 @@ ErrorReaction debug_OnError(LibError err, u8* suppress, const wchar_t* file, int } -ErrorReaction debug_OnAssertionFailure(const wchar_t* expr, u8* suppress, const wchar_t* file, int line, const char* func) +ErrorReaction debug_OnAssertionFailure(const wchar_t* expr, atomic_bool* suppress, const wchar_t* file, int line, const char* func) { void* context = 0; const std::wstring lastFuncToSkip = L"debug_OnAssertionFailure"; diff --git a/source/lib/debug.h b/source/lib/debug.h index 57a4c4dcd3..66e4dc8fe4 100644 --- a/source/lib/debug.h +++ b/source/lib/debug.h @@ -105,6 +105,13 @@ enum DebugDisplayErrorFlags DE_MANUAL_BREAK = 4 }; +/** + * 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 @@ -112,7 +119,7 @@ enum DebugDisplayErrorFlags * initial value is 0 rather that another constant; this avoids * allocating .rdata space. **/ -const u8 DEBUG_SUPPRESS = 0xAB; +const atomic_bool DEBUG_SUPPRESS = 0xAB; /** * choices offered by the shared error dialog @@ -170,7 +177,7 @@ enum ErrorReaction * provides the storage. values: see DEBUG_SUPPRESS above. * @return ErrorReaction (user's choice: continue running or stop?) **/ -LIB_API 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, u8* suppress); +LIB_API 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); /** * convenience version, in case the advanced parameters aren't needed. @@ -201,8 +208,9 @@ LIB_API ErrorReaction debug_DisplayError(const wchar_t* description, size_t flag * - filter changes only affect subsequent debug_*printf calls; * output that didn't pass the filter is permanently discarded. * - strings not starting with a tag are always displayed. - * - debug_filter_* can be called at any time and from the debugger. - + * - debug_filter_* can be called at any time and from the debugger, + * but are not reentrant. + * * in future, allow output with the given tag to proceed. * no effect if already added. **/ @@ -227,15 +235,6 @@ LIB_API void debug_filter_clear(); **/ LIB_API bool debug_filter_allows(const wchar_t* text); - -/** - * write to memory buffer (fast) - * used for "last activity" reporting in the crashlog. - * - * @param fmt Format string and varags; see printf. - **/ -LIB_API void debug_wprintf_mem(const wchar_t* fmt, ...) WPRINTF_ARGS(1); - /** * write an error description and all logs into crashlog.txt * (in unicode format). @@ -273,7 +272,7 @@ LIB_API LibError debug_WriteCrashlog(const wchar_t* text); **/ #define debug_assert(expr) \ STMT(\ - static u8 suppress__;\ + static atomic_bool suppress__;\ if(!(expr))\ {\ switch(debug_OnAssertionFailure(WIDEN(#expr), &suppress__, WIDEN(__FILE__), __LINE__, __func__))\ @@ -302,7 +301,7 @@ STMT(\ **/ #define debug_warn(expr) \ STMT(\ - static u8 suppress__;\ + static atomic_bool suppress__;\ switch(debug_OnAssertionFailure(expr, &suppress__, WIDEN(__FILE__), __LINE__, __func__))\ {\ case ER_BREAK:\ @@ -321,7 +320,7 @@ STMT(\ **/ #define DEBUG_WARN_ERR(err)\ STMT(\ - static u8 suppress__;\ + static atomic_bool suppress__;\ switch(debug_OnError(err, &suppress__, WIDEN(__FILE__), __LINE__, __func__))\ {\ case ER_BREAK:\ @@ -344,7 +343,7 @@ STMT(\ * @param func name of the function containing it * @return ErrorReaction (user's choice: continue running or stop?) **/ -LIB_API ErrorReaction debug_OnAssertionFailure(const wchar_t* assert_expr, u8* suppress, const wchar_t* file, int line, const char* func); +LIB_API ErrorReaction debug_OnAssertionFailure(const wchar_t* assert_expr, atomic_bool* suppress, const wchar_t* file, int line, const char* func); /** * called when a DEBUG_WARN_ERR indicates an error occurred; @@ -356,7 +355,7 @@ LIB_API ErrorReaction debug_OnAssertionFailure(const wchar_t* assert_expr, u8* s * @param func name of the function containing it * @return ErrorReaction (user's choice: continue running or stop?) **/ -LIB_API ErrorReaction debug_OnError(LibError err, u8* suppress, const wchar_t* file, int line, const char* func); +LIB_API ErrorReaction debug_OnError(LibError err, atomic_bool* suppress, const wchar_t* file, int line, const char* func); /** diff --git a/source/lib/res/graphics/ogl_tex.cpp b/source/lib/res/graphics/ogl_tex.cpp index 29dfc34281..d6f1ac2a9b 100644 --- a/source/lib/res/graphics/ogl_tex.cpp +++ b/source/lib/res/graphics/ogl_tex.cpp @@ -1022,7 +1022,7 @@ LibError ogl_tex_bind(Handle ht, size_t unit) // we don't bother catching that and disabling texturing because a // debug warning is raised anyway, and it's quite unlikely. H_DEREF(ht, OglTex, ot); - ot->tmu = unit; + ot->tmu = (u8)unit; // if 0, there's a problem in the OglTex reload/dtor logic. // binding it results in whiteness, which can have many causes;