Skip to content

Commit

Permalink
#50 Process initialization is now parallel
Browse files Browse the repository at this point in the history
Also adds some `info` level prints to make demos a bit more friendly to new users

closes #50
  • Loading branch information
MatejKafka committed Apr 28, 2021
1 parent fc4e21d commit 6ae3a54
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 54 deletions.
2 changes: 1 addition & 1 deletion src/demos_scheduler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ class DemosScheduler

void start_scheduler()
{
logger->debug("Starting scheduler");
logger->info("Starting scheduler");
memory_tracker::enable();
mf.start(std::chrono::steady_clock::now());
}
Expand Down
85 changes: 33 additions & 52 deletions src/partition_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ class PartitionManager
{
private:
Partitions partitions;
Partitions::iterator init_iter = partitions.begin();
Process *initialized_proc = nullptr;
std::function<void()> completion_cb = [] {};
// initialized in `run_process_init`
std::function<void()> init_cb = nullptr;
int remaining_process_inits = 0;

public:
explicit PartitionManager(Partitions &&partitions)
Expand Down Expand Up @@ -54,12 +53,33 @@ class PartitionManager
}

// overwrite process exit callback set in constructor
// we need this to be able to detect that a process exited during initialization
// and we should move on to the next one, otherwise a deadlock would occur
// we need this to be able to detect that a process exited during initialization,
// otherwise a deadlock would occur, waiting for the completion of an exited process
// this will be reset to the original callback after initialization is finished
set_exit_cb(&PartitionManager::process_init_exit_cb);

init_next_process();
// count and start all processes that needs initialization in parallel
for (auto &part : partitions) {
for (auto &proc : part.processes) {
if (!proc.needs_initialization()) continue;
logger->trace("Initializing process '{}'", proc.get_pid());
remaining_process_inits++;
// resume the process; it should stop on its own after initialization is completed
// then, it will call proc_init_completion_cb as callback; if it exits instead
// (probably due to an error), `process_init_exit_cb` will be called
proc.resume();
}
}

if (remaining_process_inits == 0) {
logger->info("No processes need initialization");
// no process needs initialization, we're done
finish_process_init();
} else {
logger->info("Initializing {} {}",
remaining_process_inits,
remaining_process_inits == 1 ? "process" : "processes");
}
}

/** Spawns suspended processes from all partitions. */
Expand Down Expand Up @@ -113,45 +133,6 @@ class PartitionManager
completion_cb();
}

Process *find_next_uninitialized_process()
{
Process *proc;
for (; init_iter != partitions.end(); init_iter++) {
proc = init_iter->seek_pending_process();
if (proc) return proc;
}
return nullptr;
}

void init_next_process()
{
initialized_proc = find_next_uninitialized_process();
if (initialized_proc) {
init_process(initialized_proc);
} else {
finish_process_init();
}
}

/**
* Initializes a single process.
* Completion is handled by `process_init_completion_cb()`.
*/
void init_process(Process *p)
{
if (!p->needs_initialization()) {
p->mark_completed();
init_next_process();
return;
}

logger->trace("Initializing process '{}'", p->get_pid());
// resume the process; it should stop on its own after initialization is completed
// then, it will call init_next_process as callback; if it exits instead (probably
// due to an error), `process_init_exit_cb` will be called
p->resume();
}

void finish_process_init()
{
// reset process exit cb to the original one
Expand All @@ -165,20 +146,20 @@ class PartitionManager
}

/** Called as a completion callback from process. */
void process_init_completion_cb(Process &)
void process_init_completion_cb(Process &proc)
{
initialized_proc->suspend();
initialized_proc->mark_completed();
init_next_process();
proc.suspend();
remaining_process_inits--;
if (remaining_process_inits == 0) {
finish_process_init();
}
}

/** Called when a process exits during initialization. */
void process_init_exit_cb(Process &proc, bool partition_empty)
{
// if this is false, it means some other process exited,
// this may happen for example on receiving SIGINT
if (!initialized_proc->is_running()) {
// end initialization of this process and move on to the next one
if (proc.needs_initialization()) {
// consider this process initialized
process_init_completion_cb(proc);
}
// call original callback
Expand Down
2 changes: 1 addition & 1 deletion test/0100-api.t
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ partitions:
')
is "$out" \
"init start
init done
init start
init done
init done
<test>"
15 changes: 15 additions & 0 deletions test_config/api_init_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
windows:
- length: 200
slices:
- cpu: 0
sc_partition: SC1

partitions:
- name: SC1
processes:
- cmd: ../build/src/tests/api-init-test
budget: 100
init: yes
- cmd: ../build/src/tests/api-init-test
budget: 100
init: yes

0 comments on commit 6ae3a54

Please sign in to comment.