diff --git a/CMakeLists.txt b/CMakeLists.txt index 59e5344d..e5f984f5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -950,6 +950,25 @@ else() "Try manually check out https://github.com/khuck/perfstubs.git to ${PROJECT_SOURCE_DIR}") endif() +### Set up taskStubs stuff +git_external(taskStubs + https://github.com/khuck/taskStubs.git + main + VERBOSE) + +find_file( + TASKSTUBS_HEADER + NAMES timer_plugin/tool_api.h + PATHS ${PROJECT_SOURCE_DIR}/taskStubs) + +if(TASKSTUBS_HEADER) + message(INFO " Found taskStubs at ${PROJECT_SOURCE_DIR}/taskStubs") + include_directories(${PROJECT_SOURCE_DIR}/taskStubs) +else() + message(FATAL_ERROR " taskStubs not found. This should have been checked out automatically. " + "Try manually check out https://github.com/khuck/taskStubs.git to ${PROJECT_SOURCE_DIR}") +endif() + if(APEX_WITH_PLUGINS) message(INFO " apex will be built with plugin support.") set(LIBS ${LIBS} ${CMAKE_DL_LIBS}) diff --git a/src/apex/CMakeLists_standalone.cmake b/src/apex/CMakeLists_standalone.cmake index d71f6346..46e5d900 100644 --- a/src/apex/CMakeLists_standalone.cmake +++ b/src/apex/CMakeLists_standalone.cmake @@ -94,6 +94,7 @@ nvtx_listener.cpp ${OTF2_SOURCE} ${perfetto_sources} perftool_implementation.cpp +taskstubs_implementation.cpp policy_handler.cpp ${PROC_SOURCE} profile_reducer.cpp diff --git a/src/apex/taskstubs_implementation.cpp b/src/apex/taskstubs_implementation.cpp new file mode 100644 index 00000000..65512af6 --- /dev/null +++ b/src/apex/taskstubs_implementation.cpp @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2014-2021 Kevin Huck + * Copyright (c) 2014-2021 University of Oregon + * + * Distributed under the Boost Software License, Version 1.0. (See accompanying + * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + */ + +#include "timer_plugin/tool_api.h" +#include +#include "apex_api.hpp" +#include "thread_instance.hpp" +#include +#include + +using maptype = std::unordered_map>; +std::mutex mtx; + +maptype& getCommonMap(void) { + static maptype theMap; + return theMap; +} + +maptype& getMyMap(void) { + static thread_local maptype theMap; + return theMap; +} + +void safeInsert( + tasktimer_guid_t guid, + std::shared_ptr task) { + mtx.lock(); + getCommonMap()[guid] = task; + mtx.unlock(); + getMyMap()[guid] = task; +} + +std::shared_ptr safeLookup( + tasktimer_guid_t guid) { + // in the thread local map? + auto task = getMyMap().find(guid); + if (task == getMyMap().end()) { + // in the common map? + mtx.lock(); + task = getCommonMap().find(guid); + mtx.unlock(); + getMyMap()[guid] = task->second; + } + return task->second; +} + +void safeErase( + tasktimer_guid_t guid) { + getMyMap().erase(guid); + mtx.lock(); + getCommonMap().erase(guid); + mtx.unlock(); +} + +extern "C" { + // library function declarations + void tasktimer_initialize_impl(void) { + apex::init("PerfStubs API", 0, 1); + } + void tasktimer_finalize_impl(void) { + /* Debatable whether we want to do this finalize */ + apex::finalize(); + } + // measurement function declarations + tasktimer_timer_t tasktimer_create_impl( + const tasktimer_function_pointer_t function_address, + const char* timer_name, + const tasktimer_guid_t timer_guid, + const tasktimer_guid_t* parent_guids, + const uint64_t parent_count) { + // TODO: need to handle multiple parents! + // need to look up the parent shared pointers? + std::vector> parent_tasks; + for (uint64_t i = 0 ; i < parent_count ; i++) { + parent_tasks.push_back(safeLookup(parent_guids[i])); + } + // if no name, use address + if (timer_name == nullptr || strlen(timer_name) == 0) { + // TODO: need to handle multiple parents! + if (parent_count > 0) { + auto task = apex::new_task( + (apex_function_address)function_address, + timer_guid, parent_tasks[0]); + safeInsert(timer_guid, task); + } else { + auto task = apex::new_task( + (apex_function_address)function_address, + timer_guid); + safeInsert(timer_guid, task); + } + } else { + // TODO: need to handle multiple parents! + if (parent_count > 0) { + auto task = apex::new_task(timer_name, timer_guid, parent_tasks[0]); + safeInsert(timer_guid, task); + } else { + auto task = apex::new_task(timer_name, timer_guid); + safeInsert(timer_guid, task); + } + } + return (tasktimer_timer_t)(timer_guid); + } + void tasktimer_schedule_impl( + tasktimer_timer_t timer, + tasktimer_argument_value_p arguments, + uint64_t argument_count) { + // TODO: handle the schedule event, somehow + APEX_UNUSED(timer); + APEX_UNUSED(arguments); + APEX_UNUSED(argument_count); + } + +#define MAP_TASK(_timer, _apex_timer) \ + uint64_t _tmp = (uint64_t)(_timer); \ + auto _apex_timer = safeLookup(_tmp); + + void tasktimer_start_impl( + tasktimer_timer_t timer, + tasktimer_execution_space_p) { + // TODO: capture the execution space, somehow...a new task? + MAP_TASK(timer, apex_timer); + apex::start(apex_timer); + } + void tasktimer_yield_impl( + tasktimer_timer_t timer) { + MAP_TASK(timer, apex_timer); + apex::yield(apex_timer); + } + void tasktimer_resume_impl( + tasktimer_timer_t timer, + tasktimer_execution_space_p) { + // TODO: capture the execution space, somehow...a new task? + MAP_TASK(timer, apex_timer); + // TODO: why no resume function for task_wrapper objects? + apex::start(apex_timer); + } + void tasktimer_stop_impl( + tasktimer_timer_t timer) { + MAP_TASK(timer, apex_timer); + apex::stop(apex_timer); + } + void tasktimer_destroy_impl( + tasktimer_timer_t timer) { + MAP_TASK(timer, apex_timer); + // TODO: need to handle the destroy event somehow. + // definitely need to remove it from the local map. + safeErase(apex_timer->guid); + } + void tasktimer_add_parents_impl ( + tasktimer_timer_t timer, + const tasktimer_guid_t* parents, const uint64_t parent_count) { + // TODO: need to handle the add parents event + MAP_TASK(timer, apex_timer); + APEX_UNUSED(apex_timer); + APEX_UNUSED(parents); + APEX_UNUSED(parent_count); + } + void tasktimer_add_children_impl( + tasktimer_timer_t timer, + const tasktimer_guid_t* children, const uint64_t child_count) { + // TODO: need to handle the add children event + MAP_TASK(timer, apex_timer); + APEX_UNUSED(apex_timer); + APEX_UNUSED(children); + APEX_UNUSED(child_count); + } +} +