From f214221bb26190381d56a3555cce51130672f1fe Mon Sep 17 00:00:00 2001 From: Evgeny Date: Mon, 27 Jan 2020 14:30:44 -0600 Subject: [PATCH] control of trace buffer thread start --- inc/roctracer.h | 12 +--- src/core/roctracer.cpp | 37 ++++++------ src/core/trace_buffer.h | 116 ++++++++++++++++++++++++++++++-------- test/tool/tracer_tool.cpp | 105 +++++++++++++++++----------------- 4 files changed, 169 insertions(+), 101 deletions(-) diff --git a/inc/roctracer.h b/inc/roctracer.h index 1db73cee77..deffb0f6d3 100644 --- a/inc/roctracer.h +++ b/inc/roctracer.h @@ -250,20 +250,14 @@ roctracer_status_t roctracer_get_timestamp( uint64_t* timestamp); // [out] return timestamp // Load/Unload methods +bool roctracer_load(); +void roctracer_unload(); + // Set properties roctracer_status_t roctracer_set_properties( roctracer_domain_t domain, // tracing domain void* propertes); // tracing properties -typedef struct HsaApiTable HsaApiTable; -bool roctracer_load( - HsaApiTable* table, - uint64_t runtime_version, - uint64_t failed_tool_count, - const char* const* failed_tool_names); - -void roctracer_unload(bool destruct); - #ifdef __cplusplus } // extern "C" block #endif // __cplusplus diff --git a/src/core/roctracer.cpp b/src/core/roctracer.cpp index 7221be3460..b975117ae6 100644 --- a/src/core/roctracer.cpp +++ b/src/core/roctracer.cpp @@ -548,6 +548,7 @@ unsigned set_stopped(unsigned val) { } // namespace roctracer LOADER_INSTANTIATE(); +TRACE_BUFFER_INSTANTIATE(); /////////////////////////////////////////////////////////////////////////////////////////////////// // Public library methods @@ -989,6 +990,7 @@ PUBLIC_API roctracer_status_t roctracer_flush_activity_expl(roctracer_pool_t* po if (pool == NULL) pool = roctracer_default_pool(); roctracer::MemoryPool* memory_pool = reinterpret_cast(pool); memory_pool->Flush(); + roctracer::TraceBufferBase::FlushAll(); API_METHOD_SUFFIX } @@ -1045,6 +1047,12 @@ PUBLIC_API void roctracer_stop() { } } +PUBLIC_API roctracer_status_t roctracer_get_timestamp(uint64_t* timestamp) { + API_METHOD_PREFIX + *timestamp = util::HsaRsrcFactory::Instance().TimestampNs(); + API_METHOD_SUFFIX +} + // Set properties PUBLIC_API roctracer_status_t roctracer_set_properties( roctracer_domain_t domain, @@ -1053,6 +1061,8 @@ PUBLIC_API roctracer_status_t roctracer_set_properties( API_METHOD_PREFIX switch (domain) { case ACTIVITY_DOMAIN_HSA_OPS: { + roctracer::trace_buffer.StartWorkerThread(); + // HSA OPS properties roctracer::hsa_ops_properties_t* ops_properties = reinterpret_cast(properties); HsaApiTable* table = reinterpret_cast(ops_properties->table); @@ -1112,11 +1122,10 @@ PUBLIC_API roctracer_status_t roctracer_set_properties( API_METHOD_SUFFIX } -// HSA-runtime tool on-load method -PUBLIC_API bool roctracer_load(HsaApiTable* table, uint64_t runtime_version, uint64_t failed_tool_count, - const char* const* failed_tool_names) { - ONLOAD_TRACE_BEG(); +PUBLIC_API bool roctracer_load() { static bool is_loaded = false; + ONLOAD_TRACE("begin, loaded(" << is_loaded << ")"); + if (is_loaded) return true; is_loaded = true; @@ -1124,11 +1133,10 @@ PUBLIC_API bool roctracer_load(HsaApiTable* table, uint64_t runtime_version, uin return true; } -PUBLIC_API void roctracer_unload(bool destruct) { +PUBLIC_API void roctracer_unload() { static bool is_unloaded = false; - ONLOAD_TRACE("begin (" << destruct << ", " << is_unloaded << ")"); + ONLOAD_TRACE("begin, unloaded(" << is_unloaded << ")"); - if (destruct == false) return; if (is_unloaded == true) return; is_unloaded = true; @@ -1137,23 +1145,16 @@ PUBLIC_API void roctracer_unload(bool destruct) { ONLOAD_TRACE_END(); } -PUBLIC_API roctracer_status_t roctracer_get_timestamp(uint64_t* timestamp) { - API_METHOD_PREFIX - *timestamp = util::HsaRsrcFactory::Instance().TimestampNs(); - API_METHOD_SUFFIX -} - +// HSA-runtime tool on-load/unload methods PUBLIC_API bool OnLoad(HsaApiTable* table, uint64_t runtime_version, uint64_t failed_tool_count, const char* const* failed_tool_names) { ONLOAD_TRACE_BEG(); - const bool ret = roctracer_load(table, runtime_version, failed_tool_count, failed_tool_names); + const bool ret = roctracer_load(); ONLOAD_TRACE_END(); return ret; } PUBLIC_API void OnUnload() { - ONLOAD_TRACE_BEG(); - roctracer_unload(false); - ONLOAD_TRACE_END(); + ONLOAD_TRACE("done"); } CONSTRUCTOR_API void constructor() { @@ -1166,7 +1167,7 @@ CONSTRUCTOR_API void constructor() { DESTRUCTOR_API void destructor() { ONLOAD_TRACE_BEG(); - roctracer_unload(true); + roctracer_unload(); util::HsaRsrcFactory::Destroy(); roctracer::util::Logger::Destroy(); ONLOAD_TRACE_END(); diff --git a/src/core/trace_buffer.h b/src/core/trace_buffer.h index 0cbcb5bdda..05bc3c47b6 100644 --- a/src/core/trace_buffer.h +++ b/src/core/trace_buffer.h @@ -2,12 +2,23 @@ #define SRC_CORE_TRACE_BUFFER_H_ #include +#include #include #include +#include + #include #include #include +#define FATAL(stream) \ + do { \ + std::ostringstream oss; \ + oss << __FUNCTION__ << "(), " << stream; \ + std::cout << oss.str() << std::endl; \ + abort(); \ + } while (0) + #define PTHREAD_CALL(call) \ do { \ int err = call; \ @@ -53,8 +64,55 @@ struct trace_entry_t { }; }; +template +struct push_element_fun { + T* const elem_; + void fun(T* node) { if (node->next_elem_ == NULL) node->next_elem_ = elem_; } + push_element_fun(T* elem) : elem_(elem) {} +}; + +template +struct call_element_fun { + void (T::*fptr_)(); + void fun(T* node) { (node->*fptr_)(); } + call_element_fun(void (T::*f)()) : fptr_(f) {} +}; + +struct TraceBufferBase { + typedef std::mutex mutex_t; + + virtual void StartWorkerThread() = 0; + virtual void Flush() = 0; + + static void StartWorkerThreadAll() { foreach(call_element_fun(&TraceBufferBase::StartWorkerThread)); } + static void FlushAll() { foreach(call_element_fun(&TraceBufferBase::Flush)); } + + static void Push(TraceBufferBase* elem) { + if (head_elem_ == NULL) head_elem_ = elem; + else foreach(push_element_fun(elem)); + } + + TraceBufferBase() : next_elem_(NULL) {} + + template + static void foreach(const F& f_in) { + std::lock_guard lck(mutex_); + F f = f_in; + TraceBufferBase* p = head_elem_; + while (p != NULL) { + TraceBufferBase* next = p->next_elem_; + f.fun(p); + p = next; + } + } + + TraceBufferBase* next_elem_; + static TraceBufferBase* head_elem_; + static mutex_t mutex_; +}; + template -class TraceBuffer { +class TraceBuffer : protected TraceBufferBase { public: typedef void (*callback_t)(Entry*); typedef TraceBuffer Obj; @@ -67,7 +125,8 @@ class TraceBuffer { }; TraceBuffer(const char* name, uint32_t size, flush_prm_t* flush_prm_arr, uint32_t flush_prm_count) : - is_flushed_(false) + is_flushed_(false), + work_thread_started_(false) { name_ = strdup(name); size_ = size; @@ -80,31 +139,43 @@ class TraceBuffer { flush_prm_arr_ = flush_prm_arr; flush_prm_count_ = flush_prm_count; - PTHREAD_CALL(pthread_mutex_init(&work_mutex_, NULL)); - PTHREAD_CALL(pthread_cond_init(&work_cond_, NULL)); - PTHREAD_CALL(pthread_create(&work_thread_, NULL, allocate_worker, this)); + TraceBufferBase::Push(this); } ~TraceBuffer() { - PTHREAD_CALL(pthread_cancel(work_thread_)); - void *res; - PTHREAD_CALL(pthread_join(work_thread_, &res)); - if (res != PTHREAD_CANCELED) abort_run("~TraceBuffer: consumer thread wasn't stopped correctly"); - + StopWorkerThread(); Flush(); } + void StartWorkerThread() { + std::lock_guard lck(mutex_); + if (work_thread_started_ == false) { + PTHREAD_CALL(pthread_mutex_init(&work_mutex_, NULL)); + PTHREAD_CALL(pthread_cond_init(&work_cond_, NULL)); + PTHREAD_CALL(pthread_create(&work_thread_, NULL, allocate_worker, this)); + work_thread_started_ = true; + } + } + + void StopWorkerThread() { + std::lock_guard lck(mutex_); + if (work_thread_started_ == true) { + PTHREAD_CALL(pthread_cancel(work_thread_)); + void *res; + PTHREAD_CALL(pthread_join(work_thread_, &res)); + if (res != PTHREAD_CANCELED) FATAL("consumer thread wasn't stopped correctly"); + work_thread_started_ = false; + } + } Entry* GetEntry() { const pointer_t pointer = read_pointer_.fetch_add(1); if (pointer >= end_pointer_) wrap_buffer(pointer); - if (pointer >= end_pointer_) abort_run("pointer >= end_pointer_ after buffer wrap"); + if (pointer >= end_pointer_) FATAL("pointer >= end_pointer_ after buffer wrap"); return data_ + (pointer + size_ - end_pointer_); } - void Flush() { - flush_buf(); - } + void Flush() { flush_buf(); } private: void flush_buf() { @@ -134,7 +205,7 @@ class TraceBuffer { inline Entry* allocate_fun() { Entry* ptr = (Entry*) malloc(size_ * sizeof(Entry)); - if (ptr == NULL) abort_run("TraceBuffer::allocate_fun: calloc failed"); + if (ptr == NULL) FATAL("malloc failed"); //memset(ptr, 0, size_ * sizeof(Entry)); return ptr; } @@ -156,24 +227,20 @@ class TraceBuffer { void wrap_buffer(const pointer_t pointer) { std::lock_guard lck(mutex_); + if (work_thread_started_ == false) FATAL("worker thread is not started"); + PTHREAD_CALL(pthread_mutex_lock(&work_mutex_)); if (pointer >= end_pointer_) { data_ = next_; next_ = NULL; PTHREAD_CALL(pthread_cond_signal(&work_cond_)); end_pointer_ += size_; - if (end_pointer_ == 0) abort_run("TraceBuffer::wrap_buffer: pointer overflow"); + if (end_pointer_ == 0) FATAL("pointer overflow"); buf_list_.push_back(data_); } PTHREAD_CALL(pthread_mutex_unlock(&work_mutex_)); } - void abort_run(const char* str) { - fprintf(stderr, "%s\n", str); - fflush(stderr); - abort(); - } - const char* name_; uint32_t size_; Entry* data_; @@ -189,9 +256,14 @@ class TraceBuffer { pthread_t work_thread_; pthread_mutex_t work_mutex_; pthread_cond_t work_cond_; + bool work_thread_started_; mutex_t mutex_; }; } // namespace roctracer +#define TRACE_BUFFER_INSTANTIATE() \ + roctracer::TraceBufferBase* roctracer::TraceBufferBase::head_elem_ = NULL; \ + roctracer::TraceBufferBase::mutex_t roctracer::TraceBufferBase::mutex_; + #endif // SRC_CORE_TRACE_BUFFER_H_ diff --git a/test/tool/tracer_tool.cpp b/test/tool/tracer_tool.cpp index 75c72dd09f..fc79195f6f 100644 --- a/test/tool/tracer_tool.cpp +++ b/test/tool/tracer_tool.cpp @@ -77,6 +77,7 @@ bool trace_hip_activity = false; bool trace_kfd = false; LOADER_INSTANTIATE(); +TRACE_BUFFER_INSTANTIATE(); // Global output file handle FILE* roctx_file_handle = NULL; @@ -524,9 +525,55 @@ void close_output_file(FILE* file_handle) { if ((file_handle != NULL) && (file_handle != stdout)) fclose(file_handle); } +// tool unload method +void tool_unload() { + static bool is_unloaded = false; + ONLOAD_TRACE("begin, unloaded(" << is_unloaded << ")"); + + if (is_unloaded == true) return; + is_unloaded = true; + + roctracer_unload(); + + if (trace_roctx) { + ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_ROCTX)); + + roctx_trace_buffer.Flush(); + close_output_file(roctx_file_handle); + } + if (trace_hsa_api) { + ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_HSA_API)); + + hsa_api_trace_buffer.Flush(); + close_output_file(hsa_api_file_handle); + } + if (trace_hsa_activity) { + ROCTRACER_CALL(roctracer_disable_domain_activity(ACTIVITY_DOMAIN_HSA_OPS)); + + close_output_file(hsa_async_copy_file_handle); + } + if (trace_hip_api || trace_hip_activity) { + ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_HIP_API)); + ROCTRACER_CALL(roctracer_disable_domain_activity(ACTIVITY_DOMAIN_HIP_API)); + ROCTRACER_CALL(roctracer_disable_domain_activity(ACTIVITY_DOMAIN_HCC_OPS)); + ROCTRACER_CALL(roctracer_flush_activity()); + ROCTRACER_CALL(roctracer_close_pool()); + + hip_api_trace_buffer.Flush(); + close_output_file(hip_api_file_handle); + close_output_file(hcc_activity_file_handle); + } + + if (trace_kfd) { + ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_KFD_API)); + fclose(kfd_api_file_handle); + } + ONLOAD_TRACE_END(); +} + // HSA-runtime tool on-load method extern "C" PUBLIC_API bool OnLoad(HsaApiTable* table, uint64_t runtime_version, uint64_t failed_tool_count, - const char* const* failed_tool_names) { + const char* const* failed_tool_names) { ONLOAD_TRACE_BEG(); timer = new hsa_rt_utils::Timer(table->core_->hsa_system_get_info_fn); @@ -758,61 +805,15 @@ extern "C" PUBLIC_API bool OnLoad(HsaApiTable* table, uint64_t runtime_version, printf(")\n"); } + roctracer::TraceBufferBase::StartWorkerThreadAll(); + const bool ret = roctracer_load(); ONLOAD_TRACE_END(); - return roctracer_load(table, runtime_version, failed_tool_count, failed_tool_names); -} - -// tool unload method -void tool_unload(bool destruct) { - static bool is_unloaded = false; - ONLOAD_TRACE("begin (" << destruct <<", " << is_unloaded << ")"); - - if (destruct == false) return; - if (is_unloaded == true) return; - is_unloaded = true; - roctracer_unload(destruct); - - if (trace_roctx) { - ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_ROCTX)); - - roctx_trace_buffer.Flush(); - close_output_file(roctx_file_handle); - } - if (trace_hsa_api) { - ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_HSA_API)); - - hsa_api_trace_buffer.Flush(); - close_output_file(hsa_api_file_handle); - } - if (trace_hsa_activity) { - ROCTRACER_CALL(roctracer_disable_domain_activity(ACTIVITY_DOMAIN_HSA_OPS)); - - close_output_file(hsa_async_copy_file_handle); - } - if (trace_hip_api || trace_hip_activity) { - ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_HIP_API)); - ROCTRACER_CALL(roctracer_disable_domain_activity(ACTIVITY_DOMAIN_HIP_API)); - ROCTRACER_CALL(roctracer_disable_domain_activity(ACTIVITY_DOMAIN_HCC_OPS)); - ROCTRACER_CALL(roctracer_flush_activity()); - ROCTRACER_CALL(roctracer_close_pool()); - - hip_api_trace_buffer.Flush(); - close_output_file(hip_api_file_handle); - close_output_file(hcc_activity_file_handle); - } - - if (trace_kfd) { - ROCTRACER_CALL(roctracer_disable_domain_callback(ACTIVITY_DOMAIN_KFD_API)); - fclose(kfd_api_file_handle); - } - ONLOAD_TRACE_END(); + return ret; } // HSA-runtime on-unload method extern "C" PUBLIC_API void OnUnload() { - ONLOAD_TRACE_BEG(); - tool_unload(false); - ONLOAD_TRACE_END(); + ONLOAD_TRACE(""); } extern "C" CONSTRUCTOR_API void constructor() { @@ -820,6 +821,6 @@ extern "C" CONSTRUCTOR_API void constructor() { } extern "C" DESTRUCTOR_API void destructor() { ONLOAD_TRACE_BEG(); - tool_unload(true); + tool_unload(); ONLOAD_TRACE_END(); }