diff --git a/util/dprintf.c b/util/dprintf.c index 34941f7..098988c 100644 --- a/util/dprintf.c +++ b/util/dprintf.c @@ -9,6 +9,8 @@ #include "util/dprintf.h" +static long dbg_buf_lock_init; +static CRITICAL_SECTION dbg_buf_lock; static char dbg_buf[16384]; static size_t dbg_buf_pos; @@ -23,6 +25,26 @@ void dprintf(const char *fmt, ...) void dprintfv(const char *fmt, va_list ap) { + long init; + + /* Static constructors in C are difficult to do in a way that works under + both GCC and MSVC, so we have to use atomic ops to ensure that the + buffer mutex is correctly initialized instead. */ + + do { + init = InterlockedCompareExchange(&dbg_buf_lock_init, 0, 1); + + if (init == 0) { + /* We won the init race, global variable is now set to 1, other + threads will spin until it becomes -1. */ + InitializeCriticalSection(&dbg_buf_lock); + dbg_buf_lock_init = -1; + init = -1; + } + } while (init >= 0); + + EnterCriticalSection(&dbg_buf_lock); + dbg_buf_pos += vsnprintf_s( dbg_buf + dbg_buf_pos, sizeof(dbg_buf) - dbg_buf_pos, @@ -34,13 +56,13 @@ void dprintfv(const char *fmt, va_list ap) abort(); } - if (strchr(dbg_buf, '\n') == NULL) { - return; + if (strchr(dbg_buf, '\n') != NULL) { + OutputDebugStringA(dbg_buf); + dbg_buf_pos = 0; + dbg_buf[0] = '\0'; } - OutputDebugStringA(dbg_buf); - dbg_buf_pos = 0; - dbg_buf[0] = '\0'; + LeaveCriticalSection(&dbg_buf_lock); } void dwprintf(const wchar_t *fmt, ...)