Skip to content

Commit 6aa1440

Browse files
committed
Initial support for multithreading in debug console. Sync manager handles checking if enter interactive console is set and switching between threads. New console commands are info (get thread and rank) for current or all threads and thread <threadID> to switch to a new thread.
1 parent 48ea028 commit 6aa1440

File tree

10 files changed

+450
-55
lines changed

10 files changed

+450
-55
lines changed

src/sst/core/impl/interactive/simpleDebug.cc

Lines changed: 118 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,10 @@ SimpleDebugger::SimpleDebugger(Params& params) :
4747
[this](std::vector<std::string>& tokens) { cmd_help(tokens); } },
4848
{ "verbose", "v", "[mask]: set verbosity mask or print if no mask specified", ConsoleCommandGroup::GENERAL,
4949
[this](std::vector<std::string>& tokens) { cmd_verbose(tokens); } },
50-
{ "rankinfo", "ri", "print current rank and thread IDs", ConsoleCommandGroup::GENERAL,
51-
[this](std::vector<std::string>& tokens) { cmd_rankInfo(tokens); } },
50+
{ "info", "info", "\"current\"|\"all\" print summary for current thread or all threads", ConsoleCommandGroup::GENERAL,
51+
[this](std::vector<std::string>& tokens) { cmd_info(tokens); } },
52+
{ "thread", "thd", "[threadID]: switch to specified thread ID", ConsoleCommandGroup::GENERAL,
53+
[this](std::vector<std::string>& tokens) { cmd_thread(tokens); } },
5254
{ "confirm", "cfm", "<true/false>: set confirmation requests on (default) or off", ConsoleCommandGroup::GENERAL,
5355
[this](std::vector<std::string>& tokens) { cmd_setConfirm(tokens); } },
5456
{ "pwd", "pwd", "print the current working directory in the object map", ConsoleCommandGroup::NAVIGATION,
@@ -195,22 +197,59 @@ SimpleDebugger::~SimpleDebugger()
195197
}
196198

197199
void
200+
SimpleDebugger::summary()
201+
{
202+
#if 0
203+
RankInfo info = getRank();
204+
RankInfo nRanks = getNumRanks();
205+
std::count << "\n(Rank:" << info.rank << " / " << nRanks.rank
206+
<< " Thread:" << info.thread << "/" << nRanks.thread
207+
<< ")\n";
208+
std::cout << " -- Trigger Status\n";
209+
#endif
210+
211+
std::cout << " -- Component Summary\n";
212+
#if 0
213+
std::vector<std::string> tokens;
214+
if (nullptr == obj_) {
215+
obj_ = getComponentObjectMap();
216+
}
217+
cmd_ls(tokens);
218+
#else
219+
SST::Core::Serialization::ObjectMap* baseObj = getComponentObjectMap();
220+
auto& vars = baseObj->getVariables();
221+
for (auto& x : vars) {
222+
if (x.second->isFundamental()) {
223+
std::cout << x.first << " = " << x.second->get() << " (" << x.second->getType() << ")" << std::endl;
224+
}
225+
else {
226+
std::cout << x.first.c_str() << "/ (" << x.second->getType() << ")\n";
227+
}
228+
}
229+
#endif
230+
}
231+
232+
int
198233
SimpleDebugger::execute(const std::string& msg)
199234
{
200-
printf("Entering interactive mode at time %" PRI_SIMTIME " \n", getCurrentSimCycle());
235+
RankInfo info = getRank();
236+
RankInfo nRanks = getNumRanks();
237+
printf("\n---- Rank%d:Thread%d: Entering interactive mode at time %" PRI_SIMTIME " \n", info.rank, info.thread, getCurrentSimCycle());
201238
printf("%s\n", msg.c_str());
202239

203240
if ( nullptr == obj_ ) {
204241
obj_ = getComponentObjectMap();
205242
}
206243
done = false;
244+
retState = -1;
245+
207246

208247
std::string line;
209248
while ( !done ) {
210249

211250
try {
212251
// User input prompt
213-
std::cout << "> " << std::flush;
252+
std::cout << "R" << info.rank << ":T" << info.thread << "> " << std::flush;
214253

215254
if ( !injectedCommand.str().empty() ) {
216255
// Injected command stream (currently just one command)
@@ -252,6 +291,7 @@ SimpleDebugger::execute(const std::string& msg)
252291
std::cout << "Parsing error. Ignoring " << line << std::endl;
253292
}
254293
}
294+
return retState;
255295
}
256296

257297
// Invoke the command.
@@ -397,12 +437,75 @@ SimpleDebugger::cmd_verbose(std::vector<std::string>& tokens)
397437
}
398438
}
399439

400-
SimpleDebugger::cmd_rankInfo(std::vector<std::string>& UNUSED(tokens)) {
440+
void
441+
SimpleDebugger::cmd_info(std::vector<std::string>& UNUSED(tokens)) {
442+
443+
if (tokens.size() != 2) {
444+
printf("Invalid format for info command (info \"current\"|\"all\")\n");
445+
return;
446+
}
447+
448+
RankInfo info = getRank();
449+
RankInfo nRanks = getNumRanks();
450+
if (tokens[1] == "current") {
451+
std::cout << "Rank " << info.rank << "/" << nRanks.rank
452+
<< ", Thread " << info.thread << "/" << nRanks.thread << std::endl;
453+
}
454+
else if (tokens[1] == "all") {
455+
if (nRanks.rank == 1 && nRanks.thread == 1) {
456+
std::cout << "Rank " << info.rank << "/" << nRanks.rank
457+
<< ", Thread " << info.thread << "/" << nRanks.thread << std::endl;
458+
}
459+
else {
460+
// Return to syncmanager to print summary for all threads
461+
retState = -2; // summary info
462+
done = true;
463+
}
464+
}
465+
else {
466+
printf("Invalid argument for info command: %s (info \"current\"|\"all\")\n", tokens[1].c_str());
467+
return;
468+
}
469+
}
470+
471+
// thread <threadID> : switches to new thread
472+
void
473+
SimpleDebugger::cmd_thread(std::vector<std::string>& tokens) {
474+
475+
if (tokens.size() != 2) {
476+
printf("Invalid format for thread command (thread <threadID>)\n");
477+
return;
478+
}
401479

402480
RankInfo info = getRank();
403481
RankInfo nRanks = getNumRanks();
404-
std::cout << "Rank " << info.rank << "/" << nRanks.rank
405-
<< ", Thread " << info.thread << "/" << nRanks.thread << std::endl;
482+
int threadID;
483+
484+
// Get threadID
485+
try {
486+
threadID = std::stoi(tokens[1]);
487+
}
488+
catch (const std::invalid_argument& e) {
489+
std::cout << "Invalid argument for threadID: " << tokens[1] << std::endl;
490+
return;
491+
}
492+
catch (const std::out_of_range& e) {
493+
std::cout << "Out of range for threadID: " << tokens[1] << std::endl;
494+
return;
495+
}
496+
497+
// Check if valid threadID
498+
if (threadID < 0 || threadID >= nRanks.thread) {
499+
printf("ThreadID %d out of range (0:%d)\n", threadID, nRanks.thread-1);
500+
return;
501+
}
502+
503+
// If not current thread, set retState and done flag
504+
if (threadID != info.thread) {
505+
retState = threadID;
506+
done = true;
507+
}
508+
return;
406509
}
407510

408511

@@ -457,10 +560,18 @@ SimpleDebugger::get_listing_strings(std::list<std::string>& list)
457560
void
458561
SimpleDebugger::cmd_cd(std::vector<std::string>& tokens)
459562
{
563+
#if 1
460564
if ( tokens.size() != 2 ) {
461565
printf("Invalid format for cd command (cd <obj>)\n");
462566
return;
463567
}
568+
#else
569+
// skk This works but doesn't delete/deactivate like objmap selectParent
570+
if (tokens.size() == 1) {
571+
obj_ = getComponentObjectMap();
572+
return;
573+
}
574+
#endif
464575

465576
// Allow for trailing '/'
466577
std::string selection = tokens[1];

src/sst/core/impl/interactive/simpleDebug.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,8 @@ class SimpleDebugger : public SST::InteractiveConsole
137137
explicit SimpleDebugger(Params& params);
138138
~SimpleDebugger();
139139
140-
void execute(const std::string& msg) override;
140+
int execute(const std::string& msg) override;
141+
void summary() override;
141142
142143
// Callbacks from command line completions
143144
void get_listing_strings(std::list<std::string>&);
@@ -152,6 +153,7 @@ class SimpleDebugger : public SST::InteractiveConsole
152153
153154
SST::Core::Serialization::ObjectMap* obj_ = nullptr;
154155
bool done = false;
156+
int retState = -1; // -1 done, positive number is threadID
155157
156158
bool autoCompleteEnable = true;
157159
@@ -181,7 +183,8 @@ class SimpleDebugger : public SST::InteractiveConsole
181183
// Navigation
182184
void cmd_help(std::vector<std::string>& UNUSED(tokens));
183185
void cmd_verbose(std::vector<std::string>& (tokens));
184-
void cmd_rankInfo(std::vector<std::string>& UNUSED(tokens));
186+
void cmd_info(std::vector<std::string>& UNUSED(tokens));
187+
void cmd_thread(std::vector<std::string>& tokens);
185188
void cmd_pwd(std::vector<std::string>& UNUSED(tokens));
186189
void cmd_ls(std::vector<std::string>& UNUSED(tokens));
187190
void cmd_cd(std::vector<std::string>& tokens);

src/sst/core/interactiveAction.h

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "sst/core/action.h"
1616
// Can include this because this header is not installed
1717
#include "sst/core/simulation_impl.h"
18+
#include "sst/core/interactiveConsole.h"
1819

1920
#include <string>
2021

@@ -31,26 +32,54 @@ class InteractiveAction : public Action
3132
Create a new InteractiveAction object for the simulation core to initiate interactive mode
3233
*/
3334
InteractiveAction(Simulation_impl* sim, const std::string& msg) :
34-
Action(),
3535
sim_(sim),
3636
msg_(msg)
3737
{
3838
setPriority(INTERACTIVEPRIOIRTY);
3939
}
4040

4141
~InteractiveAction() {}
42+
#if 1
43+
/**
44+
Indicates InteractiveAction should be inserted into the
45+
TimeVortex. The insertion will only happen for serial runs, as
46+
InteractiveAction is managed by the SyncManager in parallel
47+
runs.
48+
*/
49+
void insertIntoTimeVortex(SimTime_t time) {
50+
// If this is a serial job, insert this into
51+
// the time TimeVortex. If it is parallel, then the
52+
// InteractiveAction is managed by the SyncManager.
53+
//std::cout << "skk: insertIntoTimeVortex called\n";
54+
RankInfo num_ranks = sim_->getNumRanks();
55+
//if (num_ranks.rank == 1 && num_ranks.thread == 1) {
56+
//std::cout << " skk: insertIntoTimeVortex insertActivity\n";
57+
sim_->insertActivity(time, this);
58+
//}
59+
}
60+
#endif
61+
#if 0
62+
/** Break to interactive console next time check() is called */
63+
void setInteractiveConsole() {
64+
sim_->enter_interactive_ = true;
65+
}
66+
#endif
4267

4368
/** Called by TimeVortex to trigger interactive mode. */
4469
void execute() override
4570
{
4671
sim_->enter_interactive_ = true;
47-
sim_->interactive_msg_ = msg_;
72+
sim_->interactive_msg_ = msg_;
4873
delete this;
4974
}
5075

76+
5177
private:
5278
Simulation_impl* sim_;
5379
std::string msg_;
80+
81+
// Do I need flag here for break to interactive like ckptAction?
82+
// Currently using sim_->enter_interactive_
5483
};
5584

5685
} // namespace SST

src/sst/core/interactiveConsole.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ InteractiveConsole::getTimeConverter(const std::string& time)
100100
void
101101
InteractiveConsole::schedule_interactive(SimTime_t time_offset, const std::string& msg)
102102
{
103+
//std::cout << "skk: IC: schedule_interactive\n";
103104
Simulation_impl* sim = Simulation_impl::getSimulation();
104105
InteractiveAction* act = new InteractiveAction(sim, msg);
105106
sim->insertActivity(getCurrentSimCycle() + time_offset, act);
@@ -114,7 +115,8 @@ InteractiveConsole::getComponentObjectMap()
114115
void
115116
InteractiveConsole::simulationShutdown()
116117
{
117-
Simulation_impl::getSimulation()->endSimulation();
118+
//Simulation_impl::getSimulation()->endSimulation();
119+
Simulation_impl::getSimulation()->signalShutdown(false);
118120
}
119121

120122

src/sst/core/interactiveConsole.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ class InteractiveConsole
5858
virtual ~InteractiveConsole() = default;
5959

6060
/** Called by TimeVortex to trigger checkpoint on simulation clock interval - not used in parallel simulation */
61-
virtual void execute(const std::string& msg) = 0;
61+
virtual int execute(const std::string& msg) = 0;
62+
/** Called by SyncManager to get summary info for each thread */
63+
virtual void summary() = 0;
6264

6365
protected:
6466
// Functions that can be called by child class

0 commit comments

Comments
 (0)