From: José Fonseca Date: Thu, 25 Nov 2010 16:14:45 +0000 (+0000) Subject: Fix multithreaded reentrancy. X-Git-Url: https://git.cworth.org/git?a=commitdiff_plain;h=3495713d02b8f9ef28981ac54c22c4c8ee9b2299;p=apitrace Fix multithreaded reentrancy. Happens on windows when SetPixelFormat is called... --- diff --git a/log.cpp b/log.cpp index e373f69..23a3393 100644 --- a/log.cpp +++ b/log.cpp @@ -50,8 +50,6 @@ static void _Close(void) { } } -static int reentrancy = 0; - static void _Open(const char *szExtension) { _Close(); @@ -101,9 +99,6 @@ static inline void Write(const void *sBuffer, size_t dwBytesToWrite) { if (g_gzFile == NULL) return; - if (reentrancy > 1) - return; - gzwrite(g_gzFile, sBuffer, dwBytesToWrite); } @@ -177,16 +172,30 @@ void Close(void) { _Close(); } -void BeginCall(const char *function) { +static unsigned call_no = 0; + +unsigned BeginEnter(const char *function) { OS::AcquireMutex(); Open(); - ++reentrancy; + WriteByte(Trace::EVENT_ENTER); WriteName(function); + return call_no++; +} + +void EndEnter(void) { + WriteByte(Trace::CALL_END); + gzflush(g_gzFile, Z_SYNC_FLUSH); + OS::ReleaseMutex(); +} + +void BeginLeave(unsigned call) { + OS::AcquireMutex(); + WriteByte(Trace::EVENT_LEAVE); + WriteUInt(call); } -void EndCall(void) { +void EndLeave(void) { WriteByte(Trace::CALL_END); - --reentrancy; gzflush(g_gzFile, Z_SYNC_FLUSH); OS::ReleaseMutex(); } diff --git a/log.hpp b/log.hpp index c012d78..edbf002 100644 --- a/log.hpp +++ b/log.hpp @@ -31,8 +31,11 @@ namespace Log { void Open(void); void Close(void); - void BeginCall(const char *function); - void EndCall(void); + unsigned BeginEnter(const char *function); + void EndEnter(void); + + void BeginLeave(unsigned call); + void EndLeave(void); void BeginArg(unsigned index, const char *name); inline void EndArg(void) {} diff --git a/os_win32.cpp b/os_win32.cpp index e96cc93..0849ab0 100644 --- a/os_win32.cpp +++ b/os_win32.cpp @@ -46,14 +46,14 @@ CriticalSection = { void AcquireMutex(void) { - //EnterCriticalSection(&CriticalSection); + EnterCriticalSection(&CriticalSection); } void ReleaseMutex(void) { - //LeaveCriticalSection(&CriticalSection); + LeaveCriticalSection(&CriticalSection); } diff --git a/trace.py b/trace.py index f7f10b8..677faf3 100644 --- a/trace.py +++ b/trace.py @@ -320,19 +320,21 @@ class Tracer: print ' %s __result;' % function.type result = '__result = ' self._get_true_pointer(function) - print ' Log::BeginCall("%s");' % (function.name) + print ' unsigned __call = Log::BeginEnter("%s");' % (function.name) for arg in function.args: if not arg.output: self.unwrap_arg(function, arg) self.dump_arg(function, arg) + print ' Log::EndEnter();' print ' %s%s(%s);' % (result, pvalue, ', '.join([str(arg.name) for arg in function.args])) + print ' Log::BeginLeave(__call);' for arg in function.args: if arg.output: self.dump_arg(function, arg) self.wrap_arg(function, arg) if function.type is not stdapi.Void: self.dump_ret(function, "__result") - print ' Log::EndCall();' + print ' Log::EndLeave();' if function.type is not stdapi.Void: self.wrap_ret(function, "__result") print ' return __result;' diff --git a/trace_format.hpp b/trace_format.hpp index d2ea6af..1f5871e 100644 --- a/trace_format.hpp +++ b/trace_format.hpp @@ -30,6 +30,12 @@ namespace Trace { #define TRACE_VERSION 0 +enum Event { + EVENT_ENTER = 0, + EVENT_LEAVE, + EVENT_MESSAGE +}; + enum CallDetail { CALL_END = 0, CALL_ARG, diff --git a/trace_model.hpp b/trace_model.hpp index 8cf1951..8a87e0f 100644 --- a/trace_model.hpp +++ b/trace_model.hpp @@ -236,6 +236,7 @@ typedef std::pair Arg; class Call { public: + unsigned no; std::string name; std::vector args; Value *ret; diff --git a/trace_parser.hpp b/trace_parser.hpp index 6a2c92f..850dc8d 100644 --- a/trace_parser.hpp +++ b/trace_parser.hpp @@ -53,9 +53,15 @@ protected: typedef std::map namemap; namemap names; + typedef std::map callmap; + callmap calls; + + unsigned next_call_no; + public: Parser() { file = NULL; + next_call_no = 0; } ~Parser() { @@ -87,13 +93,52 @@ public: } Call *parse_call(void) { + do { + int c = read_byte(); + switch(c) { + case Trace::EVENT_ENTER: + parse_enter(); + break; + case Trace::EVENT_LEAVE: + return parse_leave(); + case Trace::EVENT_MESSAGE: + std::cerr << "message: " << read_string() << "\n"; + break; + default: + std::cerr << "error: unknown call detail " << c << "\n"; + assert(0); + /* fallthrough */ + case -1: + return NULL; + } + } while(true); + } + + void parse_enter(void) { Call *call = new Call; + call->no = next_call_no++; call->name = read_name(); + parse_call_details(call); + calls[call->no] = call; + } + + Call *parse_leave(void) { + unsigned call_no = read_uint(); + Call *call = calls[call_no]; + assert(call); + if (!call) { + return NULL; + } + parse_call_details(call); + return call; + } + + void parse_call_details(Call *call) { do { int c = read_byte(); switch(c) { case Trace::CALL_END: - return call; + return; case Trace::CALL_ARG: parse_arg(call); break; @@ -105,8 +150,7 @@ public: assert(0); /* fallthrough */ case -1: - delete call; - return NULL; + return; } } while(true); }