diff --git a/rai/lib/CMakeLists.txt b/rai/lib/CMakeLists.txt index f2a460c3..aaf40bc9 100644 --- a/rai/lib/CMakeLists.txt +++ b/rai/lib/CMakeLists.txt @@ -1,11 +1,11 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - set (platform_sources plat/default/priority.cpp plat/posix/perms.cpp) + set (platform_sources plat/default/priority.cpp plat/posix/perms.cpp plat/darwin/thread_role.cpp) elseif (${CMAKE_SYSTEM_NAME} MATCHES "Windows") - set (platform_sources plat/windows/priority.cpp plat/windows/perms.cpp) + set (platform_sources plat/windows/priority.cpp plat/windows/perms.cpp plat/windows/thread_role.cpp) elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - set (platform_sources plat/linux/priority.cpp plat/posix/perms.cpp) + set (platform_sources plat/linux/priority.cpp plat/posix/perms.cpp plat/linux/thread_role.cpp) elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - set (platform_sources plat/default/priority.cpp plat/posix/perms.cpp) + set (platform_sources plat/default/priority.cpp plat/posix/perms.cpp plat/freebsd/thread_role.cpp) else () error ("Unknown platform: ${CMAKE_SYSTEM_NAME}") endif () diff --git a/rai/lib/plat/darwin/thread_role.cpp b/rai/lib/plat/darwin/thread_role.cpp new file mode 100644 index 00000000..014b5040 --- /dev/null +++ b/rai/lib/plat/darwin/thread_role.cpp @@ -0,0 +1,7 @@ +#include +#include + +void rai::thread_role::set_name (std::string thread_name) +{ + pthread_setname_np (thread_name.c_str ()); +} diff --git a/rai/lib/plat/freebsd/thread_role.cpp b/rai/lib/plat/freebsd/thread_role.cpp new file mode 100644 index 00000000..870f9832 --- /dev/null +++ b/rai/lib/plat/freebsd/thread_role.cpp @@ -0,0 +1,8 @@ +#include +#include +#include + +void rai::thread_role::set_name (std::string thread_name) +{ + pthread_set_name_np (pthread_self (), thread_name.c_str ()); +} diff --git a/rai/lib/plat/linux/thread_role.cpp b/rai/lib/plat/linux/thread_role.cpp new file mode 100644 index 00000000..d4c038ed --- /dev/null +++ b/rai/lib/plat/linux/thread_role.cpp @@ -0,0 +1,7 @@ +#include +#include + +void rai::thread_role::set_name (std::string thread_name) +{ + pthread_setname_np (pthread_self (), thread_name.c_str ()); +} diff --git a/rai/lib/plat/windows/thread_role.cpp b/rai/lib/plat/windows/thread_role.cpp new file mode 100644 index 00000000..fa0b775b --- /dev/null +++ b/rai/lib/plat/windows/thread_role.cpp @@ -0,0 +1,18 @@ +#include + +#include +#include + +typedef HRESULT (*SetThreadDescription_t) (HANDLE, PCWSTR); + +void rai::thread_role::set_name (std::string thread_name) +{ + SetThreadDescription_t SetThreadDescription_local; + + SetThreadDescription_local = (SetThreadDescription_t)GetProcAddress (GetModuleHandle (TEXT ("kernel32.dll")), "SetThreadDescription"); + if (SetThreadDescription_local) + { + std::wstring thread_name_wide (thread_name.begin (), thread_name.end ()); + SetThreadDescription_local (GetCurrentThread (), thread_name_wide.c_str ()); + } +} diff --git a/rai/lib/utility.cpp b/rai/lib/utility.cpp index 31647e4e..032fc682 100644 --- a/rai/lib/utility.cpp +++ b/rai/lib/utility.cpp @@ -1,6 +1,77 @@ #include #include +namespace rai +{ +namespace thread_role +{ + /* + * rai::thread_role namespace + * + * Manage thread role + */ + static thread_local rai::thread_role::name current_thread_role = rai::thread_role::name::unknown; + rai::thread_role::name get (void) + { + return current_thread_role; + } + + void set (rai::thread_role::name role) + { + std::string thread_role_name_string; + + switch (role) + { + case rai::thread_role::name::unknown: + thread_role_name_string = ""; + break; + case rai::thread_role::name::io: + thread_role_name_string = "I/O"; + break; + case rai::thread_role::name::work: + thread_role_name_string = "Work pool"; + break; + case rai::thread_role::name::packet_processing: + thread_role_name_string = "Pkt processing"; + break; + case rai::thread_role::name::alarm: + thread_role_name_string = "Alarm"; + break; + case rai::thread_role::name::vote_processing: + thread_role_name_string = "Vote processing"; + break; + case rai::thread_role::name::block_processing: + thread_role_name_string = "Blck processing"; + break; + case rai::thread_role::name::announce_loop: + thread_role_name_string = "Announce loop"; + break; + case rai::thread_role::name::wallet_actions: + thread_role_name_string = "Wallet actions"; + break; + case rai::thread_role::name::bootstrap_initiator: + thread_role_name_string = "Bootstrap init"; + break; + } + + /* + * We want to constrain the thread names to 15 + * characters, since this is the smallest maximum + * length supported by the platforms we support + * (specifically, Linux) + */ + assert (thread_role_name_string.size () < 16); + + rai::thread_role::set_name (thread_role_name_string); + + rai::thread_role::current_thread_role = role; + } +} +} + +/* + * Backing code for "release_assert", which is itself a macro + */ void release_assert_internal (bool check, const char * check_expr, const char * file, unsigned int line) { if (check) diff --git a/rai/lib/utility.hpp b/rai/lib/utility.hpp index 1c7bd3d7..aee88961 100644 --- a/rai/lib/utility.hpp +++ b/rai/lib/utility.hpp @@ -22,6 +22,29 @@ void set_secure_perm_directory (boost::filesystem::path const & path, boost::sys void set_secure_perm_file (boost::filesystem::path const & path); void set_secure_perm_file (boost::filesystem::path const & path, boost::system::error_code & ec); +/* + * Functions for understanding the role of the current thread + */ +namespace thread_role +{ + enum class name + { + unknown, + io, + work, + packet_processing, + alarm, + vote_processing, + block_processing, + announce_loop, + wallet_actions, + bootstrap_initiator, + }; + rai::thread_role::name get (void); + void set (rai::thread_role::name); + void set_name (std::string); +} + template class observer_set { diff --git a/rai/lib/work.cpp b/rai/lib/work.cpp index 2388797d..b25cbec5 100644 --- a/rai/lib/work.cpp +++ b/rai/lib/work.cpp @@ -36,6 +36,7 @@ opencl (opencl_a) for (auto i (0); i < count; ++i) { auto thread (std::thread ([this, i]() { + rai::thread_role::set (rai::thread_role::name::work); rai::work_thread_reprioritize (); loop (i); })); diff --git a/rai/node/bootstrap.cpp b/rai/node/bootstrap.cpp index 44a5b294..7b4e7598 100644 --- a/rai/node/bootstrap.cpp +++ b/rai/node/bootstrap.cpp @@ -1126,7 +1126,10 @@ void rai::bootstrap_attempt::add_bulk_push_target (rai::block_hash const & head, rai::bootstrap_initiator::bootstrap_initiator (rai::node & node_a) : node (node_a), stopped (false), -thread ([this]() { run_bootstrap (); }) +thread ([this]() { + rai::thread_role::set (rai::thread_role::name::bootstrap_initiator); + run_bootstrap (); +}) { } diff --git a/rai/node/node.cpp b/rai/node/node.cpp index dbb755cd..3c339c33 100644 --- a/rai/node/node.cpp +++ b/rai/node/node.cpp @@ -49,6 +49,7 @@ on (true) for (size_t i = 0; i < node.config.io_threads; ++i) { packet_processing_threads.push_back (std::thread ([this]() { + rai::thread_role::set (rai::thread_role::name::packet_processing); try { process_packets (); @@ -706,7 +707,10 @@ bool rai::operation::operator> (rai::operation const & other_a) const rai::alarm::alarm (boost::asio::io_service & service_a) : service (service_a), -thread ([this]() { run (); }) +thread ([this]() { + rai::thread_role::set (rai::thread_role::name::alarm); + run (); +}) { } @@ -1324,7 +1328,10 @@ node (node_a), started (false), stopped (false), active (false), -thread ([this]() { process_loop (); }) +thread ([this]() { + rai::thread_role::set (rai::thread_role::name::vote_processing); + process_loop (); +}) { std::unique_lock lock (mutex); while (!started) @@ -1799,7 +1806,10 @@ port_mapping (*this), vote_processor (*this), warmed_up (0), block_processor (*this), -block_processor_thread ([this]() { this->block_processor.process_blocks (); }), +block_processor_thread ([this]() { + rai::thread_role::set (rai::thread_role::name::block_processing); + this->block_processor.process_blocks (); +}), online_reps (*this), stats (config.stat_config) { @@ -4189,7 +4199,10 @@ rai::active_transactions::active_transactions (rai::node & node_a) : node (node_a), started (false), stopped (false), -thread ([this]() { announce_loop (); }) +thread ([this]() { + rai::thread_role::set (rai::thread_role::name::announce_loop); + announce_loop (); +}) { std::unique_lock lock (mutex); while (!started) @@ -4230,6 +4243,7 @@ rai::thread_runner::thread_runner (boost::asio::io_service & service_a, unsigned for (auto i (0); i < service_threads_a; ++i) { threads.push_back (std::thread ([&service_a]() { + rai::thread_role::set (rai::thread_role::name::io); try { service_a.run (); diff --git a/rai/node/wallet.cpp b/rai/node/wallet.cpp index a027694a..4944a486 100644 --- a/rai/node/wallet.cpp +++ b/rai/node/wallet.cpp @@ -1238,7 +1238,10 @@ observer ([](bool) {}), node (node_a), env (boost::polymorphic_downcast (node_a.store_impl.get ())->env), stopped (false), -thread ([this]() { do_wallet_actions (); }) +thread ([this]() { + rai::thread_role::set (rai::thread_role::name::wallet_actions); + do_wallet_actions (); +}) { if (!error_a) {