Skip to content

Commit e185888

Browse files
committed
rt: Run a single-threaded scheduler on the main thread
1 parent 3654ef0 commit e185888

File tree

7 files changed

+57
-21
lines changed

7 files changed

+57
-21
lines changed

src/rt/rust.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
9393
root_task->start((spawn_fn)main_fn, NULL, args->args);
9494
root_task = NULL;
9595

96-
int ret = kernel->wait_for_exit();
96+
int ret = kernel->run();
9797
delete args;
9898
delete kernel;
9999
delete srv;

src/rt/rust_kernel.cpp

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#include "rust_internal.h"
22
#include "rust_util.h"
33
#include "rust_scheduler.h"
4+
#include "rust_sched_launcher.h"
45

56
#include <vector>
67

@@ -18,8 +19,15 @@ rust_kernel::rust_kernel(rust_srv *srv) :
1819
rval(0),
1920
max_sched_id(0),
2021
sched_reaper(this),
22+
osmain_driver(NULL),
2123
env(srv->env)
2224
{
25+
// Create the single threaded scheduler that will run on the platform's
26+
// main thread
27+
rust_manual_sched_launcher_factory launchfac;
28+
osmain_scheduler = create_scheduler(&launchfac, 1, false);
29+
osmain_driver = launchfac.get_driver();
30+
sched_reaper.start();
2331
}
2432

2533
void
@@ -59,24 +67,25 @@ void rust_kernel::free(void *mem) {
5967

6068
rust_sched_id
6169
rust_kernel::create_scheduler(size_t num_threads) {
70+
rust_thread_sched_launcher_factory launchfac;
71+
return create_scheduler(&launchfac, num_threads, true);
72+
}
73+
74+
rust_sched_id
75+
rust_kernel::create_scheduler(rust_sched_launcher_factory *launchfac,
76+
size_t num_threads, bool allow_exit) {
6277
rust_sched_id id;
6378
rust_scheduler *sched;
6479
{
6580
scoped_lock with(sched_lock);
66-
// If this is the first scheduler then we need to launch
67-
// the scheduler reaper.
68-
bool start_reaper = sched_table.empty();
6981
id = max_sched_id++;
7082
K(srv, id != INTPTR_MAX, "Hit the maximum scheduler id");
7183
sched = new (this, "rust_scheduler")
72-
rust_scheduler(this, srv, num_threads, id, true);
84+
rust_scheduler(this, srv, num_threads, id, allow_exit, launchfac);
7385
bool is_new = sched_table
7486
.insert(std::pair<rust_sched_id,
7587
rust_scheduler*>(id, sched)).second;
7688
A(this, is_new, "Reusing a sched id?");
77-
if (start_reaper) {
78-
sched_reaper.start();
79-
}
8089
}
8190
sched->start_task_threads();
8291
return id;
@@ -123,16 +132,28 @@ rust_kernel::wait_for_schedulers()
123132
sched_table.erase(iter);
124133
sched->join_task_threads();
125134
delete sched;
135+
if (sched_table.size() == 1) {
136+
KLOG_("Allowing osmain scheduler to exit");
137+
sched_lock.unlock();
138+
// It's only the osmain scheduler left. Tell it to exit
139+
rust_scheduler *sched = get_scheduler_by_id(osmain_scheduler);
140+
assert(sched != NULL);
141+
sched_lock.lock();
142+
sched->allow_exit();
143+
}
126144
}
127145
if (!sched_table.empty()) {
128146
sched_lock.wait();
129147
}
130148
}
131149
}
132150

133-
/* Called on the main thread to wait for the kernel to exit */
151+
/* Called on the main thread to run the osmain scheduler to completion,
152+
then wait for schedulers to exit */
134153
int
135-
rust_kernel::wait_for_exit() {
154+
rust_kernel::run() {
155+
assert(osmain_driver != NULL);
156+
osmain_driver->start_main_loop();
136157
sched_reaper.join();
137158
return rval;
138159
}

src/rt/rust_kernel.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ class rust_scheduler;
1313

1414
typedef std::map<rust_sched_id, rust_scheduler*> sched_map;
1515

16+
class rust_sched_driver;
17+
class rust_sched_launcher_factory;
18+
1619
/**
1720
* A global object shared by all thread domains. Most of the data structures
1821
* in this class are synchronized since they are accessed from multiple
@@ -48,6 +51,11 @@ class rust_kernel {
4851
std::vector<rust_sched_id> join_list;
4952

5053
rust_sched_reaper sched_reaper;
54+
// The single-threaded scheduler that uses the main thread
55+
rust_sched_id osmain_scheduler;
56+
// Runs the single-threaded scheduler that executes tasks
57+
// on the main thread
58+
rust_sched_driver *osmain_driver;
5159

5260
public:
5361

@@ -66,11 +74,13 @@ class rust_kernel {
6674
void fail();
6775

6876
rust_sched_id create_scheduler(size_t num_threads);
77+
rust_sched_id create_scheduler(rust_sched_launcher_factory *launchfac,
78+
size_t num_threads, bool allow_exit);
6979
rust_scheduler* get_scheduler_by_id(rust_sched_id id);
7080
// Called by a scheduler to indicate that it is terminating
7181
void release_scheduler_id(rust_sched_id id);
7282
void wait_for_schedulers();
73-
int wait_for_exit();
83+
int run();
7484

7585
#ifdef __WIN32__
7686
void win32_require(LPCTSTR fn, BOOL ok);

src/rt/rust_sched_launcher.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ rust_sched_launcher *
3232
rust_manual_sched_launcher_factory::create(rust_scheduler *sched, int id) {
3333
assert(launcher == NULL && "I can only track one sched_launcher");
3434
rust_srv *srv = sched->srv->clone();
35-
return new(sched->kernel, "rust_manual_sched_launcher")
35+
launcher = new(sched->kernel, "rust_manual_sched_launcher")
3636
rust_manual_sched_launcher(sched, srv, id);
37+
return launcher;
3738
}

src/rt/rust_sched_launcher.h

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ class rust_thread_sched_launcher
3636

3737
class rust_manual_sched_launcher : public rust_sched_launcher {
3838
public:
39-
rust_manual_sched_launcher(rust_scheduler *sched, rust_srv *srv, int id);
40-
virtual void start() { }
41-
virtual void join() { }
42-
void start_main_loop() { driver.start_main_loop(); }
39+
rust_manual_sched_launcher(rust_scheduler *sched, rust_srv *srv, int id);
40+
virtual void start() { }
41+
virtual void join() { }
42+
rust_sched_driver *get_driver() { return &driver; };
4343
};
4444

4545
class rust_sched_launcher_factory {
@@ -62,7 +62,10 @@ class rust_manual_sched_launcher_factory
6262
public:
6363
rust_manual_sched_launcher_factory() : launcher(NULL) { }
6464
virtual rust_sched_launcher *create(rust_scheduler *sched, int id);
65-
rust_manual_sched_launcher *get_launcher() { return launcher; }
65+
rust_sched_driver *get_driver() {
66+
assert(launcher != NULL);
67+
return launcher->get_driver();
68+
}
6669
};
6770

6871
#endif // RUST_SCHED_LAUNCHER_H

src/rt/rust_scheduler.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ rust_scheduler::rust_scheduler(rust_kernel *kernel,
66
rust_srv *srv,
77
size_t num_threads,
88
rust_sched_id id,
9-
bool allow_exit) :
9+
bool allow_exit,
10+
rust_sched_launcher_factory *launchfac) :
1011
kernel(kernel),
1112
srv(srv),
1213
env(srv->env),
@@ -17,8 +18,7 @@ rust_scheduler::rust_scheduler(rust_kernel *kernel,
1718
num_threads(num_threads),
1819
id(id)
1920
{
20-
rust_thread_sched_launcher_factory launchfac;
21-
create_task_threads(&launchfac);
21+
create_task_threads(launchfac);
2222
}
2323

2424
rust_scheduler::~rust_scheduler() {

src/rt/rust_scheduler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ class rust_scheduler : public kernel_owned<rust_scheduler> {
3838

3939
public:
4040
rust_scheduler(rust_kernel *kernel, rust_srv *srv, size_t num_threads,
41-
rust_sched_id id, bool allow_exit);
41+
rust_sched_id id, bool allow_exit,
42+
rust_sched_launcher_factory *launchfac);
4243
~rust_scheduler();
4344

4445
void start_task_threads();

0 commit comments

Comments
 (0)