rt: Run a single-threaded scheduler on the main thread
This commit is contained in:
@@ -93,7 +93,7 @@ rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
|
|||||||
root_task->start((spawn_fn)main_fn, NULL, args->args);
|
root_task->start((spawn_fn)main_fn, NULL, args->args);
|
||||||
root_task = NULL;
|
root_task = NULL;
|
||||||
|
|
||||||
int ret = kernel->wait_for_exit();
|
int ret = kernel->run();
|
||||||
delete args;
|
delete args;
|
||||||
delete kernel;
|
delete kernel;
|
||||||
delete srv;
|
delete srv;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "rust_internal.h"
|
#include "rust_internal.h"
|
||||||
#include "rust_util.h"
|
#include "rust_util.h"
|
||||||
#include "rust_scheduler.h"
|
#include "rust_scheduler.h"
|
||||||
|
#include "rust_sched_launcher.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -18,8 +19,15 @@ rust_kernel::rust_kernel(rust_srv *srv) :
|
|||||||
rval(0),
|
rval(0),
|
||||||
max_sched_id(0),
|
max_sched_id(0),
|
||||||
sched_reaper(this),
|
sched_reaper(this),
|
||||||
|
osmain_driver(NULL),
|
||||||
env(srv->env)
|
env(srv->env)
|
||||||
{
|
{
|
||||||
|
// Create the single threaded scheduler that will run on the platform's
|
||||||
|
// main thread
|
||||||
|
rust_manual_sched_launcher_factory launchfac;
|
||||||
|
osmain_scheduler = create_scheduler(&launchfac, 1, false);
|
||||||
|
osmain_driver = launchfac.get_driver();
|
||||||
|
sched_reaper.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -59,24 +67,25 @@ void rust_kernel::free(void *mem) {
|
|||||||
|
|
||||||
rust_sched_id
|
rust_sched_id
|
||||||
rust_kernel::create_scheduler(size_t num_threads) {
|
rust_kernel::create_scheduler(size_t num_threads) {
|
||||||
|
rust_thread_sched_launcher_factory launchfac;
|
||||||
|
return create_scheduler(&launchfac, num_threads, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
rust_sched_id
|
||||||
|
rust_kernel::create_scheduler(rust_sched_launcher_factory *launchfac,
|
||||||
|
size_t num_threads, bool allow_exit) {
|
||||||
rust_sched_id id;
|
rust_sched_id id;
|
||||||
rust_scheduler *sched;
|
rust_scheduler *sched;
|
||||||
{
|
{
|
||||||
scoped_lock with(sched_lock);
|
scoped_lock with(sched_lock);
|
||||||
// If this is the first scheduler then we need to launch
|
|
||||||
// the scheduler reaper.
|
|
||||||
bool start_reaper = sched_table.empty();
|
|
||||||
id = max_sched_id++;
|
id = max_sched_id++;
|
||||||
K(srv, id != INTPTR_MAX, "Hit the maximum scheduler id");
|
K(srv, id != INTPTR_MAX, "Hit the maximum scheduler id");
|
||||||
sched = new (this, "rust_scheduler")
|
sched = new (this, "rust_scheduler")
|
||||||
rust_scheduler(this, srv, num_threads, id, true);
|
rust_scheduler(this, srv, num_threads, id, allow_exit, launchfac);
|
||||||
bool is_new = sched_table
|
bool is_new = sched_table
|
||||||
.insert(std::pair<rust_sched_id,
|
.insert(std::pair<rust_sched_id,
|
||||||
rust_scheduler*>(id, sched)).second;
|
rust_scheduler*>(id, sched)).second;
|
||||||
A(this, is_new, "Reusing a sched id?");
|
A(this, is_new, "Reusing a sched id?");
|
||||||
if (start_reaper) {
|
|
||||||
sched_reaper.start();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
sched->start_task_threads();
|
sched->start_task_threads();
|
||||||
return id;
|
return id;
|
||||||
@@ -123,6 +132,15 @@ rust_kernel::wait_for_schedulers()
|
|||||||
sched_table.erase(iter);
|
sched_table.erase(iter);
|
||||||
sched->join_task_threads();
|
sched->join_task_threads();
|
||||||
delete sched;
|
delete sched;
|
||||||
|
if (sched_table.size() == 1) {
|
||||||
|
KLOG_("Allowing osmain scheduler to exit");
|
||||||
|
sched_lock.unlock();
|
||||||
|
// It's only the osmain scheduler left. Tell it to exit
|
||||||
|
rust_scheduler *sched = get_scheduler_by_id(osmain_scheduler);
|
||||||
|
assert(sched != NULL);
|
||||||
|
sched_lock.lock();
|
||||||
|
sched->allow_exit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!sched_table.empty()) {
|
if (!sched_table.empty()) {
|
||||||
sched_lock.wait();
|
sched_lock.wait();
|
||||||
@@ -130,9 +148,12 @@ rust_kernel::wait_for_schedulers()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Called on the main thread to wait for the kernel to exit */
|
/* Called on the main thread to run the osmain scheduler to completion,
|
||||||
|
then wait for schedulers to exit */
|
||||||
int
|
int
|
||||||
rust_kernel::wait_for_exit() {
|
rust_kernel::run() {
|
||||||
|
assert(osmain_driver != NULL);
|
||||||
|
osmain_driver->start_main_loop();
|
||||||
sched_reaper.join();
|
sched_reaper.join();
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,9 @@ class rust_scheduler;
|
|||||||
|
|
||||||
typedef std::map<rust_sched_id, rust_scheduler*> sched_map;
|
typedef std::map<rust_sched_id, rust_scheduler*> sched_map;
|
||||||
|
|
||||||
|
class rust_sched_driver;
|
||||||
|
class rust_sched_launcher_factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A global object shared by all thread domains. Most of the data structures
|
* A global object shared by all thread domains. Most of the data structures
|
||||||
* in this class are synchronized since they are accessed from multiple
|
* in this class are synchronized since they are accessed from multiple
|
||||||
@@ -48,6 +51,11 @@ private:
|
|||||||
std::vector<rust_sched_id> join_list;
|
std::vector<rust_sched_id> join_list;
|
||||||
|
|
||||||
rust_sched_reaper sched_reaper;
|
rust_sched_reaper sched_reaper;
|
||||||
|
// The single-threaded scheduler that uses the main thread
|
||||||
|
rust_sched_id osmain_scheduler;
|
||||||
|
// Runs the single-threaded scheduler that executes tasks
|
||||||
|
// on the main thread
|
||||||
|
rust_sched_driver *osmain_driver;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -66,11 +74,13 @@ public:
|
|||||||
void fail();
|
void fail();
|
||||||
|
|
||||||
rust_sched_id create_scheduler(size_t num_threads);
|
rust_sched_id create_scheduler(size_t num_threads);
|
||||||
|
rust_sched_id create_scheduler(rust_sched_launcher_factory *launchfac,
|
||||||
|
size_t num_threads, bool allow_exit);
|
||||||
rust_scheduler* get_scheduler_by_id(rust_sched_id id);
|
rust_scheduler* get_scheduler_by_id(rust_sched_id id);
|
||||||
// Called by a scheduler to indicate that it is terminating
|
// Called by a scheduler to indicate that it is terminating
|
||||||
void release_scheduler_id(rust_sched_id id);
|
void release_scheduler_id(rust_sched_id id);
|
||||||
void wait_for_schedulers();
|
void wait_for_schedulers();
|
||||||
int wait_for_exit();
|
int run();
|
||||||
|
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
void win32_require(LPCTSTR fn, BOOL ok);
|
void win32_require(LPCTSTR fn, BOOL ok);
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ rust_sched_launcher *
|
|||||||
rust_manual_sched_launcher_factory::create(rust_scheduler *sched, int id) {
|
rust_manual_sched_launcher_factory::create(rust_scheduler *sched, int id) {
|
||||||
assert(launcher == NULL && "I can only track one sched_launcher");
|
assert(launcher == NULL && "I can only track one sched_launcher");
|
||||||
rust_srv *srv = sched->srv->clone();
|
rust_srv *srv = sched->srv->clone();
|
||||||
return new(sched->kernel, "rust_manual_sched_launcher")
|
launcher = new(sched->kernel, "rust_manual_sched_launcher")
|
||||||
rust_manual_sched_launcher(sched, srv, id);
|
rust_manual_sched_launcher(sched, srv, id);
|
||||||
|
return launcher;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ public:
|
|||||||
|
|
||||||
class rust_manual_sched_launcher : public rust_sched_launcher {
|
class rust_manual_sched_launcher : public rust_sched_launcher {
|
||||||
public:
|
public:
|
||||||
rust_manual_sched_launcher(rust_scheduler *sched, rust_srv *srv, int id);
|
rust_manual_sched_launcher(rust_scheduler *sched, rust_srv *srv, int id);
|
||||||
virtual void start() { }
|
virtual void start() { }
|
||||||
virtual void join() { }
|
virtual void join() { }
|
||||||
void start_main_loop() { driver.start_main_loop(); }
|
rust_sched_driver *get_driver() { return &driver; };
|
||||||
};
|
};
|
||||||
|
|
||||||
class rust_sched_launcher_factory {
|
class rust_sched_launcher_factory {
|
||||||
@@ -62,7 +62,10 @@ private:
|
|||||||
public:
|
public:
|
||||||
rust_manual_sched_launcher_factory() : launcher(NULL) { }
|
rust_manual_sched_launcher_factory() : launcher(NULL) { }
|
||||||
virtual rust_sched_launcher *create(rust_scheduler *sched, int id);
|
virtual rust_sched_launcher *create(rust_scheduler *sched, int id);
|
||||||
rust_manual_sched_launcher *get_launcher() { return launcher; }
|
rust_sched_driver *get_driver() {
|
||||||
|
assert(launcher != NULL);
|
||||||
|
return launcher->get_driver();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // RUST_SCHED_LAUNCHER_H
|
#endif // RUST_SCHED_LAUNCHER_H
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ rust_scheduler::rust_scheduler(rust_kernel *kernel,
|
|||||||
rust_srv *srv,
|
rust_srv *srv,
|
||||||
size_t num_threads,
|
size_t num_threads,
|
||||||
rust_sched_id id,
|
rust_sched_id id,
|
||||||
bool allow_exit) :
|
bool allow_exit,
|
||||||
|
rust_sched_launcher_factory *launchfac) :
|
||||||
kernel(kernel),
|
kernel(kernel),
|
||||||
srv(srv),
|
srv(srv),
|
||||||
env(srv->env),
|
env(srv->env),
|
||||||
@@ -17,8 +18,7 @@ rust_scheduler::rust_scheduler(rust_kernel *kernel,
|
|||||||
num_threads(num_threads),
|
num_threads(num_threads),
|
||||||
id(id)
|
id(id)
|
||||||
{
|
{
|
||||||
rust_thread_sched_launcher_factory launchfac;
|
create_task_threads(launchfac);
|
||||||
create_task_threads(&launchfac);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rust_scheduler::~rust_scheduler() {
|
rust_scheduler::~rust_scheduler() {
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
rust_scheduler(rust_kernel *kernel, rust_srv *srv, size_t num_threads,
|
rust_scheduler(rust_kernel *kernel, rust_srv *srv, size_t num_threads,
|
||||||
rust_sched_id id, bool allow_exit);
|
rust_sched_id id, bool allow_exit,
|
||||||
|
rust_sched_launcher_factory *launchfac);
|
||||||
~rust_scheduler();
|
~rust_scheduler();
|
||||||
|
|
||||||
void start_task_threads();
|
void start_task_threads();
|
||||||
|
|||||||
Reference in New Issue
Block a user