rocprofiler library unit tests (#81)
* Update CI and linting workflows
- delete linting workflow
- compile default CI job with clang-tidy
- split out code coverage matrix entry to separate job
- code coverage job runs code coverage 3x
- once for total code coverage
- once for unittests code coverage
- once for samples code coverage
* Update PTL submodule
- improves handling of when thread pool is destroyed in atexit handler
* Update lib/rocprofiler/buffer
- buffer::instance::get_internal_buffer()
- allocate_buffer invokes internal_threading::initialize() on first entry
- update flush routine
- if wait is false, does not wait for task group to finish syncing
- checks for callback pointer
* Update lib/rocprofiler/internal_threading
- modifications to handle destruction of statics before atexit handler is invoked
* Update lib/rocprofiler/registration.cpp
- reorder atexit call in initialize()
- protect finalize from executing more than once
* Add unittests for rocprofiler buffer
* Update CI workflow
- disable fail-fast for sanitizers
- move AddressSanitizer job to top of the list
* Update lib/rocprofiler/tests/buffer/CMakeLists.txt
- do not set memcheck LD_PRELOAD for rocprofiler-lib-buffer-tests
* Update lib/rocprofiler/registration.{hpp,cpp}
- only invoke client finalizers if initialized
- remove invoke_client_initializer
- move invoke_client functions to anonymous namespace (no declaration in header)
- set fini status in finalize
* Update scripts/thread-sanitizer-suppr.txt
- suppress false positive for double mutex lock in external/ptl/source/PTL/TaskGroup.hh
* Restructure lib/rocprofiler/tests
* Update lib/common
- add utility.cpp
- move read_command_line to utility.{hpp,cpp}
- was formerly in config.cpp
* Update lib/rocprofiler
- checks for init status return configuration locked if status is not greater than -1
- in other words, this prevents calling these functions directly (which was possible when check was for greater than 0
* Update lib/rocprofiler/context/context.{hpp,cpp}
- provide deactivate_client_contexts and deregister_client_contexts
- these functions are used when the tool fails to configure
* Update lib/rocprofiler/registration.{hpp,cpp}
- internal "public" get_client_offet()
- client ids are offset by a random value to avoid default values behaving correctly
* Update lib/rocprofiler/tests
- fix rocprofiler_lib.registration_lambda_no_result
* Update lib/rocprofiler/tests
- fix rocprofiler_lib.registration_lambda_with_result
* Update lib/rocprofiler/tests
- remove deep bind from rocprofiler_lib.registration_lambda_with_result
* Update lib/rocprofiler/tests
- use RTLD_NOW when dlopen'ing in rocprofiler_lib.registration_lambda_with_result
* Update rocprofiler registration tests
- split registration tests into separate exe that links to shared library
* Formatting
* Update CI workflow
- always checkout submodules via actions/checkout
* Update lib/rocprofiler/buffer.{hpp,cpp}
- fix issue with buffer flushing not working when only called once
* Update rocprofiler lib registration test
- test for buffered callback
* Update include/rocprofiler/rocprofiler.h
- include internal_threading.h header
* Update rocprofiler lib registration test
- add in internal threading for buffered test
[ROCm/rocprofiler-sdk commit: a646c1546c]
此提交包含在:
@@ -28,9 +28,11 @@
|
||||
#include "lib/rocprofiler/buffer.hpp"
|
||||
#include "lib/rocprofiler/context/context.hpp"
|
||||
#include "lib/rocprofiler/internal_threading.hpp"
|
||||
#include "lib/rocprofiler/registration.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -139,17 +141,21 @@ execute_creation_notifiers(rocprofiler_internal_thread_library_t libs,
|
||||
(execute(get_creation_notifier<Idx>()), ...);
|
||||
}
|
||||
|
||||
auto&
|
||||
auto*&
|
||||
get_thread_pools()
|
||||
{
|
||||
static auto _v = thread_pool_vec_t{};
|
||||
// use raw pointers here because of the access to this variable via atexit function call.
|
||||
// if not a raw pointer, this may be destroyed automatically when the atexit handler is invoked
|
||||
static auto* _v = new thread_pool_vec_t{};
|
||||
return _v;
|
||||
}
|
||||
|
||||
auto&
|
||||
auto*&
|
||||
get_task_groups()
|
||||
{
|
||||
static auto _v = task_group_vec_t{};
|
||||
// use raw pointers here because of the access to this variable via atexit function call.
|
||||
// if not a raw pointer, this may be destroyed automatically when the atexit handler is invoked
|
||||
static auto* _v = new task_group_vec_t{};
|
||||
return _v;
|
||||
}
|
||||
} // namespace
|
||||
@@ -159,28 +165,34 @@ void
|
||||
initialize()
|
||||
{
|
||||
static auto _once = std::once_flag{};
|
||||
std::call_once(_once, create_callback_thread);
|
||||
std::call_once(_once, []() {
|
||||
atexit(®istration::finalize);
|
||||
create_callback_thread();
|
||||
});
|
||||
}
|
||||
|
||||
// sync all the task groups and destroy the thread pools
|
||||
void
|
||||
finalize()
|
||||
{
|
||||
for(auto& itr : get_task_groups())
|
||||
if(get_task_groups())
|
||||
{
|
||||
if(itr) itr->join();
|
||||
for(auto& itr : *get_task_groups())
|
||||
if(itr) itr->join();
|
||||
get_task_groups()->clear();
|
||||
}
|
||||
|
||||
for(auto& itr : get_thread_pools())
|
||||
if(get_thread_pools())
|
||||
{
|
||||
if(itr) itr->destroy_threadpool();
|
||||
for(auto& itr : *get_thread_pools())
|
||||
if(itr) itr->destroy_threadpool();
|
||||
get_thread_pools()->clear();
|
||||
}
|
||||
|
||||
for(auto& itr : get_task_groups())
|
||||
itr.reset();
|
||||
|
||||
for(auto& itr : get_thread_pools())
|
||||
itr.reset();
|
||||
delete get_task_groups();
|
||||
delete get_thread_pools();
|
||||
get_task_groups() = nullptr;
|
||||
get_thread_pools() = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -198,20 +210,20 @@ notify_post_internal_thread_create(rocprofiler_internal_thread_library_t libs)
|
||||
rocprofiler_callback_thread_t
|
||||
create_callback_thread()
|
||||
{
|
||||
if(!get_thread_pools()) throw std::runtime_error{"thread pools already deleted"};
|
||||
if(!get_task_groups()) throw std::runtime_error{"task groups already deleted"};
|
||||
|
||||
// notify that rocprofiler library is about to create an inernal thread
|
||||
notify_pre_internal_thread_create(ROCPROFILER_LIBRARY);
|
||||
|
||||
// this will be index after emplace_back
|
||||
auto idx = get_thread_pools().size();
|
||||
auto idx = get_thread_pools()->size();
|
||||
|
||||
auto& thr_pool = get_thread_pools().emplace_back(
|
||||
new thread_pool_t{thread_pool_config_t{.pool_size = 1}}, [](thread_pool_t* v) {
|
||||
v->destroy_threadpool();
|
||||
delete v;
|
||||
});
|
||||
auto& thr_pool =
|
||||
get_thread_pools()->emplace_back(new thread_pool_t{thread_pool_config_t{.pool_size = 1}});
|
||||
|
||||
// construct the task group to use the newly created thread pool
|
||||
get_task_groups().emplace_back(new task_group_t{thr_pool.get()});
|
||||
get_task_groups()->emplace_back(new task_group_t{thr_pool.get()});
|
||||
|
||||
// notify that rocprofiler library finished creating an internal thread
|
||||
notify_post_internal_thread_create(ROCPROFILER_LIBRARY);
|
||||
@@ -223,7 +235,7 @@ create_callback_thread()
|
||||
task_group_t*
|
||||
get_task_group(rocprofiler_callback_thread_t cb_tid)
|
||||
{
|
||||
return get_task_groups().at(cb_tid.handle).get();
|
||||
return (get_task_groups()) ? get_task_groups()->at(cb_tid.handle).get() : nullptr;
|
||||
}
|
||||
} // namespace internal_threading
|
||||
} // namespace rocprofiler
|
||||
@@ -263,7 +275,8 @@ rocprofiler_status_t ROCPROFILER_API
|
||||
rocprofiler_assign_callback_thread(rocprofiler_buffer_id_t buffer_id,
|
||||
rocprofiler_callback_thread_t cb_thread_id)
|
||||
{
|
||||
if(cb_thread_id.handle >= rocprofiler::internal_threading::get_task_groups().size())
|
||||
if(!rocprofiler::internal_threading::get_task_groups() ||
|
||||
cb_thread_id.handle >= rocprofiler::internal_threading::get_task_groups()->size())
|
||||
return ROCPROFILER_STATUS_ERROR_THREAD_NOT_FOUND;
|
||||
|
||||
for(auto& bitr : rocprofiler::buffer::get_buffers())
|
||||
|
||||
新增問題並參考
封鎖使用者