#include "trace_file.hpp"
#include "trace_writer_local.hpp"
#include "trace_format.hpp"
+#include "trace_backtrace.hpp"
namespace trace {
#endif
process.trimDirectory();
- os::String prefix = os::getCurrentDir();
+#ifdef ANDROID
+ os::String prefix = "/data";
+#else
+ os::String prefix = os::getCurrentDir();
+#endif
prefix.join(process);
for (;;) {
#endif
}
-static unsigned next_thread_id = 0;
-static os::thread_specific_ptr<unsigned> thread_id_specific_ptr;
+static uintptr_t next_thread_num = 1;
+
+static OS_THREAD_SPECIFIC_PTR(void)
+thread_num;
-unsigned LocalWriter::beginEnter(const FunctionSig *sig) {
- os::acquireMutex();
+unsigned LocalWriter::beginEnter(const FunctionSig *sig, bool fake) {
+ mutex.lock();
++acquired;
if (!m_file->isOpened()) {
open();
}
- 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);
+ // Although thread_num is a void *, we actually use it as a uintptr_t
+ uintptr_t this_thread_num =
+ reinterpret_cast<uintptr_t>(static_cast<void *>(thread_num));
+ if (!this_thread_num) {
+ this_thread_num = next_thread_num++;
+ thread_num = reinterpret_cast<void *>(this_thread_num);
}
- return Writer::beginEnter(sig, thread_id);
+ assert(this_thread_num);
+ unsigned thread_id = this_thread_num - 1;
+ unsigned call_no = Writer::beginEnter(sig, thread_id);
+ if (!fake) {
+ std::vector<RawStackFrame> backtrace = get_backtrace();
+ beginBacktrace();
+ writeBacktrace(backtrace);
+ endBacktrace();
+ }
+ return call_no;
}
void LocalWriter::endEnter(void) {
Writer::endEnter();
--acquired;
- os::releaseMutex();
+ mutex.unlock();
}
void LocalWriter::beginLeave(unsigned call) {
- os::acquireMutex();
+ mutex.lock();
++acquired;
Writer::beginLeave(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.
*/
- os::acquireMutex();
+ mutex.lock();
if (acquired) {
os::log("apitrace: ignoring exception while tracing\n");
} else {
}
--acquired;
}
- os::releaseMutex();
+ mutex.unlock();
}