Skip to content

Commit 7f6e470

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 f572de7 commit 7f6e470

File tree

10 files changed

+459
-49
lines changed

10 files changed

+459
-49
lines changed

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

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ SimpleDebugger::SimpleDebugger(Params& params) :
5050
[this](std::vector<std::string>& tokens) { cmd_help(tokens); } },
5151
{ "verbose", "v", "[mask]: set verbosity mask or print if no mask specified", ConsoleCommandGroup::GENERAL,
5252
[this](std::vector<std::string>& tokens) { cmd_verbose(tokens); } },
53+
{ "info", "info", "\"current\"|\"all\" print summary for current thread or all threads", ConsoleCommandGroup::GENERAL,
54+
[this](std::vector<std::string>& tokens) { cmd_info(tokens); } },
55+
{ "thread", "thd", "[threadID]: switch to specified thread ID", ConsoleCommandGroup::GENERAL,
56+
[this](std::vector<std::string>& tokens) { cmd_thread(tokens); } },
5357
{ "confirm", "cfm", "<true/false>: set confirmation requests on (default) or off", ConsoleCommandGroup::GENERAL,
5458
[this](std::vector<std::string>& tokens) { cmd_setConfirm(tokens); } },
5559
{ "pwd", "pwd", "print the current working directory in the object map", ConsoleCommandGroup::NAVIGATION,
@@ -216,15 +220,52 @@ SimpleDebugger::~SimpleDebugger()
216220
}
217221

218222
void
223+
SimpleDebugger::summary()
224+
{
225+
#if 0
226+
RankInfo info = getRank();
227+
RankInfo nRanks = getNumRanks();
228+
std::count << "\n(Rank:" << info.rank << " / " << nRanks.rank
229+
<< " Thread:" << info.thread << "/" << nRanks.thread
230+
<< ")\n";
231+
std::cout << " -- Trigger Status\n";
232+
#endif
233+
234+
std::cout << " -- Component Summary\n";
235+
#if 0
236+
std::vector<std::string> tokens;
237+
if (nullptr == obj_) {
238+
obj_ = getComponentObjectMap();
239+
}
240+
cmd_ls(tokens);
241+
#else
242+
SST::Core::Serialization::ObjectMap* baseObj = getComponentObjectMap();
243+
auto& vars = baseObj->getVariables();
244+
for (auto& x : vars) {
245+
if (x.second->isFundamental()) {
246+
std::cout << x.first << " = " << x.second->get() << " (" << x.second->getType() << ")" << std::endl;
247+
}
248+
else {
249+
std::cout << x.first.c_str() << "/ (" << x.second->getType() << ")\n";
250+
}
251+
}
252+
#endif
253+
}
254+
255+
int
219256
SimpleDebugger::execute(const std::string& msg)
220257
{
221-
printf("Entering interactive mode at time %" PRI_SIMTIME " \n", getCurrentSimCycle());
258+
RankInfo info = getRank();
259+
RankInfo nRanks = getNumRanks();
260+
printf("\n---- Rank%d:Thread%d: Entering interactive mode at time %" PRI_SIMTIME " \n", info.rank, info.thread, getCurrentSimCycle());
222261
printf("%s\n", msg.c_str());
223262

224263
if ( nullptr == obj_ ) {
225264
obj_ = getComponentObjectMap();
226265
}
227266
done = false;
267+
retState = -1;
268+
228269

229270
// Select the input source and next command line
230271
std::string line;
@@ -236,6 +277,9 @@ SimpleDebugger::execute(const std::string& msg)
236277
// Logging disable has edge cases for stack push/pop
237278
bool squashLogging = false;
238279

280+
// User input prompt
281+
std::cout << "R" << info.rank << ":T" << info.thread << "> " << std::flush;
282+
239283
if ( !injectedCommand.str().empty() ) {
240284
// Injected commands allow sst command line options to cause actions (currently only replay)
241285
line = injectedCommand.str();
@@ -289,6 +333,7 @@ SimpleDebugger::execute(const std::string& msg)
289333
std::cout << "Parsing error. Ignoring " << line << std::endl;
290334
}
291335
}
336+
return retState;
292337
}
293338

294339
// Invoke the command.
@@ -490,6 +535,78 @@ SimpleDebugger::cmd_verbose(std::vector<std::string>& tokens)
490535
}
491536
}
492537

538+
void
539+
SimpleDebugger::cmd_info(std::vector<std::string>& UNUSED(tokens)) {
540+
541+
if (tokens.size() != 2) {
542+
printf("Invalid format for info command (info \"current\"|\"all\")\n");
543+
return;
544+
}
545+
546+
RankInfo info = getRank();
547+
RankInfo nRanks = getNumRanks();
548+
if (tokens[1] == "current") {
549+
std::cout << "Rank " << info.rank << "/" << nRanks.rank
550+
<< ", Thread " << info.thread << "/" << nRanks.thread << std::endl;
551+
}
552+
else if (tokens[1] == "all") {
553+
if (nRanks.rank == 1 && nRanks.thread == 1) {
554+
std::cout << "Rank " << info.rank << "/" << nRanks.rank
555+
<< ", Thread " << info.thread << "/" << nRanks.thread << std::endl;
556+
}
557+
else {
558+
// Return to syncmanager to print summary for all threads
559+
retState = -2; // summary info
560+
done = true;
561+
}
562+
}
563+
else {
564+
printf("Invalid argument for info command: %s (info \"current\"|\"all\")\n", tokens[1].c_str());
565+
return;
566+
}
567+
}
568+
569+
// thread <threadID> : switches to new thread
570+
void
571+
SimpleDebugger::cmd_thread(std::vector<std::string>& tokens) {
572+
573+
if (tokens.size() != 2) {
574+
printf("Invalid format for thread command (thread <threadID>)\n");
575+
return;
576+
}
577+
578+
RankInfo info = getRank();
579+
RankInfo nRanks = getNumRanks();
580+
int threadID;
581+
582+
// Get threadID
583+
try {
584+
threadID = std::stoi(tokens[1]);
585+
}
586+
catch (const std::invalid_argument& e) {
587+
std::cout << "Invalid argument for threadID: " << tokens[1] << std::endl;
588+
return;
589+
}
590+
catch (const std::out_of_range& e) {
591+
std::cout << "Out of range for threadID: " << tokens[1] << std::endl;
592+
return;
593+
}
594+
595+
// Check if valid threadID
596+
if (threadID < 0 || threadID >= nRanks.thread) {
597+
printf("ThreadID %d out of range (0:%d)\n", threadID, nRanks.thread-1);
598+
return;
599+
}
600+
601+
// If not current thread, set retState and done flag
602+
if (threadID != info.thread) {
603+
retState = threadID;
604+
done = true;
605+
}
606+
return;
607+
}
608+
609+
493610
// pwd: print current working directory
494611
void
495612
SimpleDebugger::cmd_pwd(std::vector<std::string>& UNUSED(tokens))
@@ -541,10 +658,18 @@ SimpleDebugger::get_listing_strings(std::list<std::string>& list)
541658
void
542659
SimpleDebugger::cmd_cd(std::vector<std::string>& tokens)
543660
{
661+
#if 1
544662
if ( tokens.size() != 2 ) {
545663
printf("Invalid format for cd command (cd <obj>)\n");
546664
return;
547665
}
666+
#else
667+
// skk This works but doesn't delete/deactivate like objmap selectParent
668+
if (tokens.size() == 1) {
669+
obj_ = getComponentObjectMap();
670+
return;
671+
}
672+
#endif
548673

549674
// Allow for trailing '/'
550675
std::string selection = tokens[1];

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ class SimpleDebugger : public SST::InteractiveConsole
250250
explicit SimpleDebugger(Params& params);
251251
~SimpleDebugger();
252252
253-
void execute(const std::string& msg) override;
253+
int execute(const std::string& msg) override;
254+
void summary() override;
254255
255256
// Callbacks from command line completions
256257
void get_listing_strings(std::list<std::string>&);
@@ -265,6 +266,7 @@ class SimpleDebugger : public SST::InteractiveConsole
265266
266267
SST::Core::Serialization::ObjectMap* obj_ = nullptr;
267268
bool done = false;
269+
int retState = -1; // -1 done, positive number is threadID
268270
269271
bool autoCompleteEnable = true;
270272
@@ -297,7 +299,9 @@ class SimpleDebugger : public SST::InteractiveConsole
297299
298300
// Navigation
299301
void cmd_help(std::vector<std::string>& UNUSED(tokens));
300-
void cmd_verbose(std::vector<std::string>&(tokens));
302+
void cmd_verbose(std::vector<std::string>& (tokens));
303+
void cmd_info(std::vector<std::string>& UNUSED(tokens));
304+
void cmd_thread(std::vector<std::string>& tokens);
301305
void cmd_pwd(std::vector<std::string>& UNUSED(tokens));
302306
void cmd_ls(std::vector<std::string>& UNUSED(tokens));
303307
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)