Skip to content

Commit 1c4f298

Browse files
committed
Working prototype
1 parent ee11f5b commit 1c4f298

File tree

9 files changed

+240
-36
lines changed

9 files changed

+240
-36
lines changed

source/bin/rocprof-sys-sample/impl.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,15 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
343343
%{INDENT}%- discard : new data is ignored
344344
%{INDENT}%- ring_buffer : new data overwrites oldest data)";
345345

346+
const auto* _pre_attach_desc =
347+
R"(Launch the application in pre-attach mode. This mode sets up and configures the profiling tools without initiating them.
348+
Applications running in pre-attach mode can later be profiled by executing rocprof-sys-sample with the --attach option.
349+
Please note that using pre-attach mode may negatively impact application performance. The extent of this impact varies based
350+
on the specific profiling configuration and the nature of the application.)";
351+
352+
const auto* _attach_desc =
353+
R"(Attach to a running process launched in pre-attach mode. )";
354+
346355
parser.set_use_color(true);
347356
parser.enable_help();
348357
parser.enable_version("rocprof-sys-sample", ROCPROFSYS_ARGPARSE_VERSION_INFO);
@@ -823,6 +832,21 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
823832
update_env(_env, "HSA_ENABLE_INTERRUPT", p.get<int>("hsa-interrupt"));
824833
});
825834

835+
parser.add_argument({ "--pre-attach" }, _pre_attach_desc)
836+
.count(0)
837+
.action([&](parser_t& p) { update_env(_env, "ROCPROFSYS_ATTACH", true); });
838+
839+
parser.add_argument({ "--attach" }, _attach_desc)
840+
.count(1)
841+
.dtype("pid")
842+
.action([&](parser_t& p) {
843+
auto _v = p.get<std::deque<std::string>>("attach");
844+
if(!_v.empty())
845+
{
846+
*(get_attach_pid()) = std::stoi(_v.front());
847+
_v.pop_front();
848+
}
849+
});
826850
parser.end_group();
827851

828852
auto _inpv = std::vector<char*>{};
@@ -861,3 +885,21 @@ parse_args(int argc, char** argv, std::vector<char*>& _env)
861885

862886
return _outv;
863887
}
888+
889+
int*
890+
get_attach_pid()
891+
{
892+
static int _v = -1;
893+
return &_v;
894+
}
895+
896+
int
897+
attach(int _pid)
898+
{
899+
kill(_pid, 10);
900+
stream(std::cout, color::info())
901+
<< "Entering into attach mode. Press any key to detach.\n";
902+
std::cin.get();
903+
kill(_pid, 10);
904+
return 0;
905+
}

source/bin/rocprof-sys-sample/rocprof-sys-sample.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ main(int argc, char** argv)
5353
_argv.emplace_back(argv[i]);
5454
}
5555

56+
if(int _pid = *(get_attach_pid()); _pid > 0)
57+
{
58+
return attach(_pid);
59+
}
60+
5661
print_updated_environment(_env);
5762

5863
if(!_argv.empty())

source/bin/rocprof-sys-sample/rocprof-sys-sample.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,9 @@ remove_env(std::vector<char*>& _environ, std::string_view _env_var);
5959

6060
std::vector<char*>
6161
parse_args(int argc, char** argv, std::vector<char*>& envp);
62+
63+
int*
64+
get_attach_pid();
65+
66+
int
67+
attach(int _pid);

source/lib/core/config.cpp

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,8 @@ configure_settings(bool _init)
247247
ROCPROFSYS_ROCM_VERSION_PATCH);
248248
#endif
249249

250+
is_pre_attach_mode() = tim::get_env("ROCPROFSYS_ATTACH", false);
251+
250252
auto _config = *get_config_impl();
251253

252254
// if using timemory, default to perfetto being off
@@ -258,6 +260,10 @@ configure_settings(bool _init)
258260
auto _rocprofsys_debug = _config->get<bool>("ROCPROFSYS_DEBUG");
259261
if(_rocprofsys_debug) tim::set_env("TIMEMORY_DEBUG_SETTINGS", "1", 0);
260262

263+
ROCPROFSYS_CONFIG_SETTING(bool, "ROCPROFSYS_ATTACH",
264+
"Determines if rocprofsys is launched in pre-attach mode.",
265+
false, "attach");
266+
261267
ROCPROFSYS_CONFIG_SETTING(
262268
std::string, "ROCPROFSYS_MODE",
263269
"Data collection mode. Used to set default values for ROCPROFSYS_USE_* options. "
@@ -1184,18 +1190,73 @@ get_signal_handler()
11841190
return _v;
11851191
}
11861192

1193+
std::atomic<signal_handler_t>&
1194+
get_attach_signal_handler()
1195+
{
1196+
static auto _v = std::atomic<signal_handler_t>{ nullptr };
1197+
return _v;
1198+
}
1199+
11871200
void
11881201
rocprofsys_exit_action(int nsig)
11891202
{
11901203
tim::signals::block_signals(get_sampling_signals(),
11911204
tim::signals::sigmask_scope::process);
11921205
ROCPROFSYS_BASIC_PRINT("Finalizing after signal %i :: %s\n", nsig,
11931206
signal_settings::str(static_cast<sys_signal>(nsig)).c_str());
1194-
auto _handler = get_signal_handler().load();
1195-
if(_handler) (*_handler)();
1207+
1208+
// Tim: Handles the case where State is never active i.e. attaching never occured.
1209+
if(get_state() == State::Active)
1210+
{
1211+
auto _handler = get_signal_handler().load();
1212+
if(_handler) (*_handler)();
1213+
}
11961214
kill(process::get_id(), nsig);
11971215
}
11981216

1217+
// Tim: This handles signals for triggering attach/detach. It prevents the process from
1218+
// being killed at the end.
1219+
void
1220+
rocprofsys_attach_detach_action(int, siginfo_t*, void*)
1221+
{
1222+
if(!config::is_pre_attach_mode())
1223+
{
1224+
ROCPROFSYS_BASIC_PRINT(R"(
1225+
EEEEEEEEEEEEEEEEEEEEEERRRRRRRRRRRRRRRRR RRRRRRRRRRRRRRRRR OOOOOOOOO RRRRRRRRRRRRRRRRR
1226+
E::::::::::::::::::::ER::::::::::::::::R R::::::::::::::::R OO:::::::::OO R::::::::::::::::R
1227+
E::::::::::::::::::::ER::::::RRRRRR:::::R R::::::RRRRRR:::::R OO:::::::::::::OO R::::::RRRRRR:::::R
1228+
EE::::::EEEEEEEEE::::ERR:::::R R:::::RRR:::::R R:::::RO:::::::OOO:::::::ORR:::::R R:::::R
1229+
E:::::E EEEEEE R::::R R:::::R R::::R R:::::RO::::::O O::::::O R::::R R:::::R
1230+
E:::::E R::::R R:::::R R::::R R:::::RO:::::O O:::::O R::::R R:::::R
1231+
E::::::EEEEEEEEEE R::::RRRRRR:::::R R::::RRRRRR:::::R O:::::O O:::::O R::::RRRRRR:::::R
1232+
E:::::::::::::::E R:::::::::::::RR R:::::::::::::RR O:::::O O:::::O R:::::::::::::RR
1233+
E:::::::::::::::E R::::RRRRRR:::::R R::::RRRRRR:::::R O:::::O O:::::O R::::RRRRRR:::::R
1234+
E::::::EEEEEEEEEE R::::R R:::::R R::::R R:::::RO:::::O O:::::O R::::R R:::::R
1235+
E:::::E R::::R R:::::R R::::R R:::::RO:::::O O:::::O R::::R R:::::R
1236+
E:::::E EEEEEE R::::R R:::::R R::::R R:::::RO::::::O O::::::O R::::R R:::::R
1237+
EE::::::EEEEEEEE:::::ERR:::::R R:::::RRR:::::R R:::::RO:::::::OOO:::::::ORR:::::R R:::::R
1238+
E::::::::::::::::::::ER::::::R R:::::RR::::::R R:::::R OO:::::::::::::OO R::::::R R:::::R
1239+
E::::::::::::::::::::ER::::::R R:::::RR::::::R R:::::R OO:::::::::OO R::::::R R:::::R
1240+
EEEEEEEEEEEEEEEEEEEEEERRRRRRRR RRRRRRRRRRRRRRR RRRRRRR OOOOOOOOO RRRRRRRR RRRRRR
1241+
1242+
Trying to attach to an uninitialized process. Only applications launched by rocprof-sys in
1243+
pre-attach mode can be attached to.
1244+
1245+
To launch an application in pre-attach mode, either
1246+
1247+
- set env var `ROCPROFSYS_ATTACH = true` or,
1248+
- launch the process with `rocprof-sys-sample --pre-attach <OPTIONS> -- <APP> <ARGS>`
1249+
1250+
Ignoring attach attempt and continuing...
1251+
)");
1252+
return;
1253+
}
1254+
tim::signals::block_signals(get_sampling_signals(),
1255+
tim::signals::sigmask_scope::process);
1256+
auto _handler = get_attach_signal_handler().load();
1257+
if(_handler) (*_handler)();
1258+
}
1259+
11991260
void
12001261
rocprofsys_trampoline_handler(int _v)
12011262
{
@@ -1234,6 +1295,28 @@ set_signal_handler(signal_handler_t _func)
12341295
return get_signal_handler().load();
12351296
}
12361297

1298+
signal_handler_t
1299+
set_attach_signal_handler(signal_handler_t _func)
1300+
{
1301+
if(_func)
1302+
{
1303+
auto _handler = get_attach_signal_handler().load(std::memory_order_relaxed);
1304+
if(get_attach_signal_handler().compare_exchange_strong(_handler, _func,
1305+
std::memory_order_relaxed))
1306+
{
1307+
return _handler;
1308+
}
1309+
else
1310+
{
1311+
_handler = get_attach_signal_handler().load(std::memory_order_seq_cst);
1312+
get_attach_signal_handler().store(_func);
1313+
return _handler;
1314+
}
1315+
}
1316+
1317+
return get_attach_signal_handler().load();
1318+
}
1319+
12371320
void
12381321
configure_signal_handler(const std::shared_ptr<settings>& _config)
12391322
{
@@ -1266,6 +1349,15 @@ configure_signal_handler(const std::shared_ptr<settings>& _config)
12661349
_action.sa_handler = rocprofsys_trampoline_handler;
12671350
sigaction(_dyninst_trampoline_signal, &_action, nullptr);
12681351
}
1352+
1353+
// Set up custom signals handlers for detaching.
1354+
// Avoid using timeory's signal handler because it kills the process.
1355+
int DETACH_SIG = 10; // SIGUSR1
1356+
struct sigaction sa;
1357+
memset(&sa, 0, sizeof(sa));
1358+
sa.sa_sigaction = rocprofsys_attach_detach_action;
1359+
sa.sa_flags = SA_SIGINFO;
1360+
sigaction(DETACH_SIG, &sa, nullptr);
12691361
}
12701362

12711363
bool
@@ -1722,6 +1814,13 @@ is_attached()
17221814
return _v;
17231815
}
17241816

1817+
bool&
1818+
is_pre_attach_mode()
1819+
{
1820+
static bool _v = false;
1821+
return _v;
1822+
}
1823+
17251824
bool&
17261825
is_binary_rewrite()
17271826
{

source/lib/core/config.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ using signal_handler_t = void (*)(void);
4848
// if arg is non-null, returns replaced signal handler
4949
signal_handler_t set_signal_handler(signal_handler_t);
5050

51+
signal_handler_t set_attach_signal_handler(signal_handler_t);
52+
5153
bool
5254
settings_are_configured() ROCPROFSYS_HOT;
5355

@@ -162,6 +164,9 @@ get_mode();
162164
bool&
163165
is_attached();
164166

167+
bool&
168+
is_pre_attach_mode();
169+
165170
bool&
166171
is_binary_rewrite();
167172

source/lib/rocprof-sys-dl/dl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,11 +1522,17 @@ extern "C"
15221522
}
15231523
}
15241524

1525+
auto _attach = get_env("ROCPROFSYS_ATTACH", false);
1526+
1527+
// Tim: Disable tooling initalization in attach mode.
1528+
if(_attach) setenv("ROCPROFSYS_INIT_TOOLING", "false", 1);
15251529
auto _mode = get_env("ROCPROFSYS_MODE", get_default_mode());
15261530
rocprofsys_init(_mode.c_str(),
15271531
dl::get_instrumented() == dl::InstrumentMode::BinaryRewrite,
15281532
argv[0]);
15291533

1534+
// Tim: Enable tooling initialization during runtime.
1535+
if(_attach) setenv("ROCPROFSYS_INIT_TOOLING", "true", 1);
15301536
int ret = (*::rocprofsys::dl::main_real)(argc, argv, envp);
15311537

15321538
rocprofsys_pop_trace(basename(argv[0]));

0 commit comments

Comments
 (0)