]> git.cworth.org Git - apitrace/commitdiff
Merge branch 'trace-threads'
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Tue, 10 Jan 2012 20:20:37 +0000 (20:20 +0000)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Tue, 10 Jan 2012 20:20:37 +0000 (20:20 +0000)
23 files changed:
CMakeLists.txt
TODO.markdown
cgltrace.py
cli/cli_dump.cpp
common/os.hpp
common/os_posix.cpp
common/os_thread.hpp [new file with mode: 0644]
common/os_win32.cpp
common/trace_format.hpp
common/trace_model.hpp
common/trace_parser.cpp
common/trace_writer.cpp
common/trace_writer.hpp
common/trace_writer_local.cpp
common/trace_writer_local.hpp [new file with mode: 0644]
common/trace_writer_model.cpp
d3d10trace.py
d3d8trace.py
d3d9trace.py
ddrawtrace.py
egltrace.py
glxtrace.py
wgltrace.py

index 6f1315a1313577a7eec5a5953acf3230c8113c64..f25a5ddfb54e2b23c93050babd3afdf485b639ca 100755 (executable)
@@ -423,7 +423,10 @@ elseif (APPLE)
         LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers
     )
 
-    target_link_libraries (cgltrace dl)
+    target_link_libraries (cgltrace
+        pthread
+        dl
+    )
 
     install (TARGETS cgltrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
 elseif (X11_FOUND)
@@ -452,7 +455,11 @@ elseif (X11_FOUND)
         LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers
     )
 
-    target_link_libraries (glxtrace dl ${X11_X11_LIB})
+    target_link_libraries (glxtrace
+        ${X11_X11_LIB}
+        pthread
+        dl
+    )
 
     install (TARGETS glxtrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
 endif ()
@@ -490,7 +497,10 @@ if (EGL_FOUND)
         LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/wrappers
     )
 
-    target_link_libraries (egltrace dl)
+    target_link_libraries (egltrace
+        pthread
+        dl
+    )
 
     install (TARGETS egltrace LIBRARY DESTINATION ${WRAPPER_INSTALL_DIR})
 endif ()
index 3cd4e4ea4e8c1900ddef2eb1a3afac24a99221cc..2fd23831aa55beec34ef9d7db5a30f5058a39650 100644 (file)
@@ -9,12 +9,6 @@ Tracing
 
 * Allow clamping to a GL version or a number of extensions.
 
-* Trace multiple threads:
-
-  * `GetCurrentThreadId()`
-
-  * `pthread_self()`
-
 * Put (de)compression in a separate thread.
 
 * Trace TSCs
index 21007237d9e8e725152550e5ffd4a9d8da99c7b7..e2e98745fe4808b2fa309d6a447bb27d973c76f1 100644 (file)
@@ -45,7 +45,7 @@ if __name__ == '__main__':
     print '#include <stdlib.h>'
     print '#include <string.h>'
     print
-    print '#include "trace_writer.hpp"'
+    print '#include "trace_writer_local.hpp"'
     print
     print '// To validate our prototypes'
     print '#define GL_GLEXT_PROTOTYPES'
index f6c51291af3597e6d5f2067a1c7a2bb401ed491a..adecb22e4abd1d0178f0f25d64a13f8d669756fe 100644 (file)
@@ -58,6 +58,7 @@ usage(void)
         "    --colour=<WHEN>     Colored syntax highlighting\n"
         "                        WHEN is 'auto', 'always', or 'never'\n"
         "    --no-arg-names      Don't dump argument names\n"
+        "    --thread-ids        Dump thread ids\n"
     ;
 }
 
@@ -65,6 +66,7 @@ static int
 command(int argc, char *argv[])
 {
     trace::DumpFlags dumpFlags = 0;
+    bool dumpThreadIds = false;
 
     int i;
 
@@ -98,6 +100,8 @@ command(int argc, char *argv[])
             color = COLOR_OPTION_NEVER;
         } else if (!strcmp(arg, "--no-arg-names")) {
             dumpFlags |= trace::DUMP_FLAG_NO_ARG_NAMES;
+        } else if (!strcmp(arg, "--thread-ids")) {
+            dumpThreadIds = true;
         } else {
             std::cerr << "error: unknown option " << arg << "\n";
             usage();
@@ -130,6 +134,9 @@ command(int argc, char *argv[])
         while ((call = p.parse_call())) {
             if (verbose ||
                 !(call->flags & trace::CALL_FLAG_VERBOSE)) {
+                if (dumpThreadIds) {
+                    std::cout << std::hex << call->thread_id << std::dec << " ";
+                }
                 trace::dump(*call, std::cout, dumpFlags);
             }
             delete call;
index 6a3b8c82f33840929b688de60ceb6f69fe9901b7..caf9dc3d2cc66e4243d819571beaf1082c7bd723 100644 (file)
 
 namespace os {
 
-void acquireMutex(void);
-
-void releaseMutex(void);
-
 void log(const char *format, ...)
 #ifdef __GNUC__
     __attribute__ ((format (printf, 1, 2)))
index 7dc2bb46a0d54400aee1a297e1064d10a01043f0..65c5404e3c0e64dd92c2184143474e05fe815b10 100644 (file)
@@ -32,7 +32,6 @@
 #include <unistd.h>
 #include <sys/time.h>
 #include <sys/wait.h>
-#include <pthread.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <signal.h>
 namespace os {
 
 
-static pthread_mutex_t 
-mutex = PTHREAD_MUTEX_INITIALIZER;
-
-
-void
-acquireMutex(void)
-{
-    pthread_mutex_lock(&mutex);
-}
-
-
-void
-releaseMutex(void)
-{
-    pthread_mutex_unlock(&mutex);
-}
-
-
 String
 getProcessName(void)
 {
diff --git a/common/os_thread.hpp b/common/os_thread.hpp
new file mode 100644 (file)
index 0000000..b17563f
--- /dev/null
@@ -0,0 +1,163 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Simple OS abstraction.
+ *
+ * Mimics C++11 / boost threads.
+ */
+
+#ifndef _OS_THREAD_HPP_
+#define _OS_THREAD_HPP_
+
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <pthread.h>
+#endif
+
+namespace os {
+
+
+    class recursive_mutex
+    {
+    public:
+#ifdef _WIN32
+        typedef CRITICAL_SECTION native_handle_type;
+#else
+        typedef pthread_mutex_t native_handle_type;
+#endif
+
+        recursive_mutex(void) {
+#ifdef _WIN32
+            InitializeCriticalSection(&_native_handle);
+#else
+            pthread_mutexattr_t attr;
+            pthread_mutexattr_init(&attr);
+            pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+            pthread_mutex_init(&_native_handle, NULL);
+            pthread_mutexattr_destroy(&attr);
+#endif
+        }
+
+        ~recursive_mutex() {
+#ifdef _WIN32
+            DeleteCriticalSection(&_native_handle);
+#else
+            pthread_mutex_destroy(&_native_handle);
+#endif
+        }
+
+        inline void
+        lock(void) {
+#ifdef _WIN32
+            EnterCriticalSection(&_native_handle);
+#else
+            pthread_mutex_lock(&_native_handle);
+#endif
+        }
+
+        inline void
+        unlock(void) {
+#ifdef _WIN32
+            LeaveCriticalSection(&_native_handle);
+#else
+            pthread_mutex_unlock(&_native_handle);
+#endif
+        }
+
+    private:
+        native_handle_type _native_handle;
+    };
+
+
+    template <typename T>
+    class thread_specific_ptr
+    {
+    private:
+#ifdef _WIN32
+        DWORD dwTlsIndex;
+#else
+        pthread_key_t key;
+
+        static void destructor(void *ptr) {
+            delete static_cast<T *>(ptr);
+        }
+#endif
+
+    public:
+        thread_specific_ptr(void) {
+#ifdef _WIN32
+            dwTlsIndex = TlsAlloc();
+#else
+            pthread_key_create(&key, &destructor);
+#endif
+        }
+
+        ~thread_specific_ptr() {
+#ifdef _WIN32
+            TlsFree(dwTlsIndex);
+#else
+            pthread_key_delete(key);
+#endif
+        }
+
+        T* get(void) const {
+            void *ptr;
+#ifdef _WIN32
+            ptr = TlsGetValue(dwTlsIndex);
+#else
+            ptr = pthread_getspecific(key);
+#endif
+            return static_cast<T*>(ptr);
+        }
+
+        T* operator -> (void) const
+        {
+            return get();
+        }
+
+        T& operator * (void) const
+        {
+            return *get();
+        }
+
+        void reset(T* new_value=0) {
+            T * old_value = get();
+#ifdef _WIN32
+            TlsSetValue(dwTlsIndex, new_value);
+#else
+            pthread_setspecific(key, new_value);
+#endif
+            if (old_value) {
+                delete old_value;
+            }
+        }
+    };
+
+} /* namespace os */
+
+#endif /* _OS_THREAD_HPP_ */
index 0b7243305a8408152d3308f797d75b5b2458829b..b35346e1af5fb788743cdfb17f45f1641b4b7738 100644 (file)
 namespace os {
 
 
-/* 
- * Trick from http://locklessinc.com/articles/pthreads_on_windows/
- */
-static CRITICAL_SECTION
-criticalSection = {
-    (PCRITICAL_SECTION_DEBUG)-1, -1, 0, 0, 0, 0
-};
-
-
-void
-acquireMutex(void)
-{
-    EnterCriticalSection(&criticalSection);
-}
-
-
-void
-releaseMutex(void)
-{
-    LeaveCriticalSection(&criticalSection);
-}
-
-
 String
 getProcessName(void)
 {
@@ -258,21 +235,56 @@ abort(void)
 }
 
 
-static LPTOP_LEVEL_EXCEPTION_FILTER prevExceptionFilter = NULL;
+static PVOID prevExceptionFilter = NULL;
 static void (*gCallback)(void) = NULL;
 
-static LONG WINAPI
-unhandledExceptionFilter(PEXCEPTION_POINTERS pExceptionInfo)
+static LONG CALLBACK
+unhandledExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo)
 {
-    if (gCallback) {
-        gCallback();
+    PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
+
+    /*
+     * Ignore OutputDebugStringA exception.
+     */
+    if (pExceptionRecord->ExceptionCode == DBG_PRINTEXCEPTION_C) {
+        return EXCEPTION_CONTINUE_SEARCH;
+    }
+
+    /*
+     * Ignore C++ exceptions
+     *
+     * http://support.microsoft.com/kb/185294
+     * http://blogs.msdn.com/b/oldnewthing/archive/2010/07/30/10044061.aspx
+     */
+    if (pExceptionRecord->ExceptionCode == 0xe06d7363) {
+        return EXCEPTION_CONTINUE_SEARCH;
     }
 
-       if (prevExceptionFilter) {
-               return prevExceptionFilter(pExceptionInfo);
+    // Clear direction flag
+#ifdef _MSC_VER
+#ifndef _WIN64
+    __asm {
+        cld
+    };
+#endif
+#else
+    asm("cld");
+#endif
+
+    log("apitrace: warning: caught exception 0x%08lx\n", pExceptionRecord->ExceptionCode);
+
+    static int recursion_count = 0;
+    if (recursion_count) {
+        fprintf(stderr, "apitrace: warning: recursion handling exception\n");
     } else {
-               return EXCEPTION_CONTINUE_SEARCH;
+        if (gCallback) {
+            ++recursion_count;
+            gCallback();
+            --recursion_count;
+        }
     }
+
+    return EXCEPTION_CONTINUE_SEARCH;
 }
 
 void
@@ -285,19 +297,17 @@ setExceptionCallback(void (*callback)(void))
 
         assert(!prevExceptionFilter);
 
-        /*
-         * TODO: Unfortunately it seems that the CRT will reset the exception
-         * handler in certain circumnstances.  See
-         * http://www.codeproject.com/KB/winsdk/crash_hook.aspx
-         */
-        prevExceptionFilter = SetUnhandledExceptionFilter(unhandledExceptionFilter);
+        prevExceptionFilter = AddVectoredExceptionHandler(0, unhandledExceptionHandler);
     }
 }
 
 void
 resetExceptionCallback(void)
 {
-    gCallback = NULL;
+    if (gCallback) {
+        RemoveVectoredExceptionHandler(prevExceptionFilter);
+        gCallback = NULL;
+    }
 }
 
 
index 5aade00361f4c70d6a6ddb814f30debc355cc271..4e1d9a9911d265bac1a9ef4462c174e21637704c 100644 (file)
@@ -66,8 +66,11 @@ namespace trace {
  *
  * - version 3:
  *   - enums signatures are recorded for the a whole set of values (not as individual values)
+ *
+ * - version 4:
+ *   - call enter events include thread ID
  */
-#define TRACE_VERSION 3
+#define TRACE_VERSION 4
 
 
 /*
@@ -75,7 +78,7 @@ namespace trace {
  *
  *   trace = event* EOF
  *
- *   event = EVENT_ENTER call_sig call_detail+
+ *   event = EVENT_ENTER thread_id call_sig call_detail+
  *         | EVENT_LEAVE call_no call_detail+
  *
  *   call_sig = sig_id ( name arg_names )?
index 4f150bc925caec0162dd21b6e07a28c664049ed4..076ff098d61f9fa25edf72a80aef7c4796663d9f 100644 (file)
@@ -410,6 +410,7 @@ enum {
 class Call
 {
 public:
+    unsigned thread_id;
     unsigned no;
     const FunctionSig *sig;
     std::vector<Value *> args;
@@ -417,7 +418,8 @@ public:
 
     CallFlags flags;
 
-    Call(FunctionSig *_sig, const CallFlags &_flags) :
+    Call(FunctionSig *_sig, const CallFlags &_flags, unsigned _thread_id) :
+        thread_id(_thread_id), 
         sig(_sig), 
         args(_sig->num_args), 
         ret(0),
index f3e623a3ed2dc7a54bf6729e560d51406a389d7a..88afa98521fc46342081e5b7d4a4f4d375001bf7 100644 (file)
@@ -390,9 +390,17 @@ BitmaskSig *Parser::parse_bitmask_sig() {
 
 
 void Parser::parse_enter(Mode mode) {
+    unsigned thread_id;
+
+    if (version >= 4) {
+        thread_id = read_uint();
+    } else {
+        thread_id = 0;
+    }
+
     FunctionSigFlags *sig = parse_function_sig();
 
-    Call *call = new Call(sig, sig->flags);
+    Call *call = new Call(sig, sig->flags, thread_id);
 
     call->no = next_call_no++;
 
index 1679989d6b11f3eed7da17ca61a6af5c3ceaea40..5708e50464abd097ac80dde3ef13a7a872a0a6a0 100644 (file)
@@ -134,8 +134,9 @@ inline bool lookup(std::vector<bool> &map, size_t index) {
     }
 }
 
-unsigned Writer::beginEnter(const FunctionSig *sig) {
+unsigned Writer::beginEnter(const FunctionSig *sig, unsigned thread_id) {
     _writeByte(trace::EVENT_ENTER);
+    _writeUInt(thread_id);
     _writeUInt(sig->id);
     if (!lookup(functions, sig->id)) {
         _writeString(sig->name);
index f89eb65ee99982ec50cd9353038f65ccad9652e8..e012a9b24a0cf25787f7b95182066ad96ef0cc56 100644 (file)
@@ -58,7 +58,7 @@ namespace trace {
         bool open(const char *filename);
         void close(void);
 
-        unsigned beginEnter(const FunctionSig *sig);
+        unsigned beginEnter(const FunctionSig *sig, unsigned thread_id);
         void endEnter(void);
 
         void beginLeave(unsigned call);
@@ -105,46 +105,6 @@ namespace trace {
 
     };
 
-    extern const FunctionSig memcpy_sig;
-    extern const FunctionSig malloc_sig;
-    extern const FunctionSig free_sig;
-    extern const FunctionSig realloc_sig;
-
-    /**
-     * A specialized Writer class, mean to trace the current process.
-     *
-     * In particular:
-     * - it creates a trace file based on the current process name
-     * - uses mutexes to allow tracing from multiple threades
-     * - flushes the output to ensure the last call is traced in event of
-     *   abnormal termination
-     */
-    class LocalWriter : public Writer {
-    protected:
-        int acquired;
-
-    public:
-        /**
-         * Should never called directly -- use localWriter singleton below instead.
-         */
-        LocalWriter();
-        ~LocalWriter();
-
-        void open(void);
-
-        unsigned beginEnter(const FunctionSig *sig);
-        void endEnter(void);
-
-        void beginLeave(unsigned call);
-        void endLeave(void);
-
-        void flush(void);
-    };
-
-    /**
-     * Singleton.
-     */
-    extern LocalWriter localWriter;
-}
+} /* namespace trace */
 
 #endif /* _TRACE_WRITER_HPP_ */
index 0730150e0f228d5fbb0fb6d8e9d6c611d1383002..a3ab720b2dd13f9c89536e4905ed63981ead0b2f 100644 (file)
 #include <string.h>
 
 #include "os.hpp"
+#include "os_thread.hpp"
 #include "os_string.hpp"
 #include "trace_file.hpp"
-#include "trace_writer.hpp"
+#include "trace_writer_local.hpp"
 #include "trace_format.hpp"
 
 
@@ -123,25 +124,39 @@ LocalWriter::open(void) {
 #endif
 }
 
+static unsigned next_thread_id = 0;
+static os::thread_specific_ptr<unsigned> thread_id_specific_ptr;
+
 unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
-    os::acquireMutex();
+    mutex.lock();
     ++acquired;
 
     if (!m_file->isOpened()) {
         open();
     }
 
-    return Writer::beginEnter(sig);
+    unsigned *thread_id_ptr = thread_id_specific_ptr.get();
+    unsigned thread_id;
+    if (thread_id_ptr) {
+        thread_id = *thread_id_ptr;
+    } else {
+        thread_id = next_thread_id++;
+        thread_id_ptr = new unsigned;
+        *thread_id_ptr = thread_id;
+        thread_id_specific_ptr.reset(thread_id_ptr);
+    }
+
+    return Writer::beginEnter(sig, thread_id);
 }
 
 void LocalWriter::endEnter(void) {
     Writer::endEnter();
     --acquired;
-    os::releaseMutex();
+    mutex.unlock();
 }
 
 void LocalWriter::beginLeave(unsigned call) {
-    os::acquireMutex();
+    mutex.lock();
     ++acquired;
     Writer::beginLeave(call);
 }
@@ -149,23 +164,28 @@ void LocalWriter::beginLeave(unsigned call) {
 void LocalWriter::endLeave(void) {
     Writer::endLeave();
     --acquired;
-    os::releaseMutex();
+    mutex.unlock();
 }
 
 void LocalWriter::flush(void) {
     /*
      * Do nothing if the mutex is already acquired (e.g., if a segfault happen
-     * while writing the file) to prevent dead-lock.
+     * while writing the file) as state could be inconsistent, therefore yield
+     * inconsistent trace files and/or repeated segfaults till infinity.
      */
 
-    if (!acquired) {
-        os::acquireMutex();
+    mutex.lock();
+    if (acquired) {
+        os::log("apitrace: ignoring exception while tracing\n");
+    } else {
+        ++acquired;
         if (m_file->isOpened()) {
             os::log("apitrace: flushing trace due to an exception\n");
             m_file->flush();
         }
-        os::releaseMutex();
+        --acquired;
     }
+    mutex.unlock();
 }
 
 
diff --git a/common/trace_writer_local.hpp b/common/trace_writer_local.hpp
new file mode 100644 (file)
index 0000000..e54142f
--- /dev/null
@@ -0,0 +1,87 @@
+/**************************************************************************
+ *
+ * Copyright 2007-2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Trace writing functions.
+ */
+
+#ifndef _TRACE_WRITER_LOCAL_HPP_
+#define _TRACE_WRITER_LOCAL_HPP_
+
+
+#include "os_thread.hpp"
+#include "trace_writer.hpp"
+
+
+namespace trace {
+
+    extern const FunctionSig memcpy_sig;
+    extern const FunctionSig malloc_sig;
+    extern const FunctionSig free_sig;
+    extern const FunctionSig realloc_sig;
+
+    /**
+     * A specialized Writer class, mean to trace the current process.
+     *
+     * In particular:
+     * - it creates a trace file based on the current process name
+     * - uses mutexes to allow tracing from multiple threades
+     * - flushes the output to ensure the last call is traced in event of
+     *   abnormal termination
+     */
+    class LocalWriter : public Writer {
+    protected:
+        /**
+         * We need a recursive mutex so that it doesn't dead lock when a segfault happens when the mutex is held.
+         */
+        os::recursive_mutex mutex;
+        int acquired;
+
+    public:
+        /**
+         * Should never called directly -- use localWriter singleton below instead.
+         */
+        LocalWriter();
+        ~LocalWriter();
+
+        void open(void);
+
+        unsigned beginEnter(const FunctionSig *sig);
+        void endEnter(void);
+
+        void beginLeave(unsigned call);
+        void endLeave(void);
+
+        void flush(void);
+    };
+
+    /**
+     * Singleton.
+     */
+    extern LocalWriter localWriter;
+
+} /* namespace trace */
+
+#endif /* _TRACE_WRITER_LOCAL_HPP_ */
index ccd7b2266c39b0bc98d9c4e4eeb685636abc7501..cc3af284d3f9db7c18c042a51d1cce2a3bfc45cf 100644 (file)
@@ -101,7 +101,7 @@ public:
     }
 
     void visit(Call *call) {
-        unsigned call_no = writer.beginEnter(call->sig);
+        unsigned call_no = writer.beginEnter(call->sig, call->thread_id);
         for (unsigned i = 0; i < call->args.size(); ++i) {
             if (call->args[i]) {
                 writer.beginArg(i);
index edcf38a8df6ab4c19e2ca635378e2c3755878e6e..b94527c5ca99e70adce070d5b1abd5329fc50b28 100644 (file)
@@ -29,7 +29,7 @@ from trace import DllTracer
 
 
 if __name__ == '__main__':
-    print '#include "trace_writer.hpp"'
+    print '#include "trace_writer_local.hpp"'
     print '#include "os.hpp"'
     print
     print '#include <windows.h>'
index 65e13edb09447886c43f66d220545a28c51bd62f..d3754e5eb1ff3988b1b7af57266bc4750909b1c5 100644 (file)
@@ -44,7 +44,7 @@ if __name__ == '__main__':
     print '#include <d3d8.h>'
     print '#include "d3dshader.hpp"'
     print
-    print '#include "trace_writer.hpp"'
+    print '#include "trace_writer_local.hpp"'
     print '#include "os.hpp"'
     print
     tracer = D3D8Tracer('d3d8.dll')
index e6bf0001b6b70db15784135f5d33301fe3fb54cd..27fbc354a088383608f35ec8f3385f7658fe0cce 100644 (file)
@@ -40,7 +40,7 @@ class D3D9Tracer(DllTracer):
 
 
 if __name__ == '__main__':
-    print '#include "trace_writer.hpp"'
+    print '#include "trace_writer_local.hpp"'
     print '#include "os.hpp"'
     print
     print '#include "d3d9imports.hpp"'
index fb8f2a583927f8a4f654735daaf04e959d7605ff..7022e1304cfc764aae1f594c6b9dabccab793696 100644 (file)
@@ -74,7 +74,7 @@ if __name__ == '__main__':
 #endif
 
 '''
-    print '#include "trace_writer.hpp"'
+    print '#include "trace_writer_local.hpp"'
     print '#include "os.hpp"'
     print
     tracer = DDrawTracer('ddraw.dll')
index de90799bf1ccc35056d94f50886e04efec3cc986..8fa313a2117b37a5d4c4298b62fbffa90f6a7b59 100644 (file)
@@ -76,7 +76,7 @@ if __name__ == '__main__':
     print '#include <string.h>'
     print '#include <dlfcn.h>'
     print
-    print '#include "trace_writer.hpp"'
+    print '#include "trace_writer_local.hpp"'
     print
     print '// To validate our prototypes'
     print '#define GL_GLEXT_PROTOTYPES'
index c9e9518f00df5d00ee387ad686d4f994d1392c87..9adcaaf98a50f8b89b5ff39650b5018e92662b4f 100644 (file)
@@ -58,7 +58,7 @@ if __name__ == '__main__':
     print '#endif'
     print '#include <dlfcn.h>'
     print
-    print '#include "trace_writer.hpp"'
+    print '#include "trace_writer_local.hpp"'
     print
     print '// To validate our prototypes'
     print '#define GL_GLEXT_PROTOTYPES'
index d5a5248f9e1a018738a5da22ea898ae03147c6f9..9dab406360918a11aaaadccc988c78b576b57463 100644 (file)
@@ -66,7 +66,7 @@ if __name__ == '__main__':
     print '#include <string.h>'
     print '#include <windows.h>'
     print
-    print '#include "trace_writer.hpp"'
+    print '#include "trace_writer_local.hpp"'
     print '#include "os.hpp"'
     print
     print '// To validate our prototypes'