From: José Fonseca Date: Thu, 22 Dec 2011 21:35:10 +0000 (+0000) Subject: First stab at tracing thread IDs. X-Git-Url: https://git.cworth.org/git?p=apitrace;a=commitdiff_plain;h=0af9670e1d6fe6e9dc6d38c7b28e18a5fea7d009 First stab at tracing thread IDs. --- diff --git a/TODO.markdown b/TODO.markdown index 3cd4e4e..2fd2383 100644 --- a/TODO.markdown +++ b/TODO.markdown @@ -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 diff --git a/cli/cli_dump.cpp b/cli/cli_dump.cpp index f6c5129..adecb22 100644 --- a/cli/cli_dump.cpp +++ b/cli/cli_dump.cpp @@ -58,6 +58,7 @@ usage(void) " --colour= 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 index 0000000..727ad6a --- /dev/null +++ b/common/os_thread.hpp @@ -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 +#else +#include +#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_ */ diff --git a/common/trace_format.hpp b/common/trace_format.hpp index 5aade00..4e1d9a9 100644 --- a/common/trace_format.hpp +++ b/common/trace_format.hpp @@ -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 )? diff --git a/common/trace_model.hpp b/common/trace_model.hpp index 4f150bc..076ff09 100644 --- a/common/trace_model.hpp +++ b/common/trace_model.hpp @@ -410,6 +410,7 @@ enum { class Call { public: + unsigned thread_id; unsigned no; const FunctionSig *sig; std::vector 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), diff --git a/common/trace_parser.cpp b/common/trace_parser.cpp index f3e623a..88afa98 100644 --- a/common/trace_parser.cpp +++ b/common/trace_parser.cpp @@ -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++; diff --git a/common/trace_writer.cpp b/common/trace_writer.cpp index 1679989..5708e50 100644 --- a/common/trace_writer.cpp +++ b/common/trace_writer.cpp @@ -134,8 +134,9 @@ inline bool lookup(std::vector &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); diff --git a/common/trace_writer.hpp b/common/trace_writer.hpp index f89eb65..f710588 100644 --- a/common/trace_writer.hpp +++ b/common/trace_writer.hpp @@ -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); diff --git a/common/trace_writer_local.cpp b/common/trace_writer_local.cpp index 0730150..bb06d90 100644 --- a/common/trace_writer_local.cpp +++ b/common/trace_writer_local.cpp @@ -31,6 +31,7 @@ #include #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(id)); } void LocalWriter::endEnter(void) { diff --git a/common/trace_writer_model.cpp b/common/trace_writer_model.cpp index ccd7b22..cc3af28 100644 --- a/common/trace_writer_model.cpp +++ b/common/trace_writer_model.cpp @@ -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);