]> git.cworth.org Git - apitrace/commitdiff
Fix multithreaded reentrancy.
authorJosé Fonseca <jfonseca@vmware.com>
Thu, 25 Nov 2010 16:14:45 +0000 (16:14 +0000)
committerJosé Fonseca <jfonseca@vmware.com>
Thu, 25 Nov 2010 16:14:45 +0000 (16:14 +0000)
Happens on windows when SetPixelFormat is called...

log.cpp
log.hpp
os_win32.cpp
trace.py
trace_format.hpp
trace_model.hpp
trace_parser.hpp

diff --git a/log.cpp b/log.cpp
index e373f698682ee90ad56d20a6d84b49c287efcbea..23a3393fb468efa2a25e3999fcff5f177f2981a8 100644 (file)
--- 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 c012d786ac4cbd6ffcfebcad62dfa779041bfd6a..edbf002e82a02b36c2d12bd9eb353dc84d2d88c5 100644 (file)
--- 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) {}
index e96cc93d63431f9a74b5f5057313b113422986af..0849ab06e522959e5d25b70f27d98ef428b474f3 100644 (file)
@@ -46,14 +46,14 @@ CriticalSection = {
 void
 AcquireMutex(void)
 {
-    //EnterCriticalSection(&CriticalSection); 
+    EnterCriticalSection(&CriticalSection); 
 }
 
 
 void
 ReleaseMutex(void)
 {
-    //LeaveCriticalSection(&CriticalSection); 
+    LeaveCriticalSection(&CriticalSection); 
 }
 
 
index f7f10b871c71aa14e4d49f3c7a179371585f470d..677faf33d4d3823287ad24f296394af15fc0bfcf 100644 (file)
--- 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;'
index d2ea6afc3e9503916615ed3fa681a705ae6f9996..1f5871e243eace46fdf15544ccbf35c884b41052 100644 (file)
@@ -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,
index 8cf1951dbfa27313cf9d965b71cce0fc5daefb84..8a87e0f65ed8443eef840252ce4dee7627817586 100644 (file)
@@ -236,6 +236,7 @@ typedef std::pair<std::string, Value *> Arg;
 class Call
 {
 public:
+   unsigned no;
    std::string name;
    std::vector<Arg> args;
    Value *ret;
index 6a2c92f352ddedfba4b021220d36ef6f9230f76e..850dc8de821cd17d0f437a70b2522ce2d4ad07cc 100644 (file)
@@ -53,9 +53,15 @@ protected:
    typedef std::map<size_t, std::string> namemap;
    namemap names;
 
+   typedef std::map<unsigned, Call *> 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);
    }