]> git.cworth.org Git - apitrace/commitdiff
First stab at tracing thread IDs.
authorJosé Fonseca <jose.r.fonseca@gmail.com>
Thu, 22 Dec 2011 21:35:10 +0000 (21:35 +0000)
committerJosé Fonseca <jose.r.fonseca@gmail.com>
Thu, 22 Dec 2011 21:35:10 +0000 (21:35 +0000)
TODO.markdown
cli/cli_dump.cpp
common/os_thread.hpp [new file with mode: 0644]
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_model.cpp

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 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;
diff --git a/common/os_thread.hpp b/common/os_thread.hpp
new file mode 100644 (file)
index 0000000..727ad6a
--- /dev/null
@@ -0,0 +1,79 @@
+/**************************************************************************
+ *
+ * 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 {
+
+
+    namespace thread {
+
+        /**
+         * Thread ID
+         *
+         * XXX: Actually C++11 thread::id is not an integral type, but we rely on that.
+         */
+#ifdef _WIN32
+        typedef DWORD id;
+#else
+        typedef pthread_t id;
+#endif
+
+    } /* namespace thread */
+
+
+    namespace this_thread {
+
+        /**
+         * Get current thread ID.
+         */
+        inline thread::id
+        get_id(void) {
+#ifdef _WIN32
+            return GetCurrentThreadId();
+#else
+            return pthread_self();
+#endif
+        }
+
+    } /* namespace this_thread */
+
+
+} /* namespace os */
+
+#endif /* _OS_THREAD_HPP_ */
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..f7105880d0d63c31cf0d82dda214d15f7e1bd8bd 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);
index 0730150e0f228d5fbb0fb6d8e9d6c611d1383002..bb06d90f74783f53f9d7bed795811fc7ac9fa251 100644 (file)
@@ -31,6 +31,7 @@
 #include <string.h>
 
 #include "os.hpp"
+#include "os_thread.hpp"
 #include "os_string.hpp"
 #include "trace_file.hpp"
 #include "trace_writer.hpp"
@@ -131,7 +132,9 @@ unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
         open();
     }
 
-    return Writer::beginEnter(sig);
+    os::thread::id id = os::this_thread::get_id();
+
+    return Writer::beginEnter(sig, static_cast<unsigned>(id));
 }
 
 void LocalWriter::endEnter(void) {
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);