Spawn new tasks onto the primary scheduler by default. #3760

This commit is contained in:
Brian Anderson
2013-01-08 19:46:12 -08:00
parent 989667e545
commit 090b247056
6 changed files with 147 additions and 91 deletions

View File

@@ -30,6 +30,7 @@ rust_kernel::rust_kernel(rust_env *env) :
rval(0),
max_sched_id(1),
killed(false),
already_exiting(false),
sched_reaper(this),
osmain_driver(NULL),
non_weak_tasks(0),
@@ -38,13 +39,20 @@ rust_kernel::rust_kernel(rust_env *env) :
env(env)
{
// Create the single threaded scheduler that will run on the platform's
// main thread
rust_manual_sched_launcher_factory *launchfac =
rust_manual_sched_launcher_factory *osmain_launchfac =
new rust_manual_sched_launcher_factory();
osmain_scheduler = create_scheduler(launchfac, 1, false);
osmain_driver = launchfac->get_driver();
osmain_scheduler = create_scheduler(osmain_launchfac, 1, false);
osmain_driver = osmain_launchfac->get_driver();
// Create the primary scheduler
rust_thread_sched_launcher_factory *main_launchfac =
new rust_thread_sched_launcher_factory();
main_scheduler = create_scheduler(main_launchfac,
env->num_sched_threads,
false);
sched_reaper.start();
}
@@ -103,15 +111,22 @@ rust_kernel::create_scheduler(rust_sched_launcher_factory *launchfac,
{
scoped_lock with(sched_lock);
if (sched_table.size() == 1) {
// The OS main scheduler may not exit while there are other
// schedulers
KLOG_("Disallowing osmain scheduler to exit");
rust_scheduler *sched =
get_scheduler_by_id_nolock(osmain_scheduler);
assert(sched != NULL);
sched->disallow_exit();
/*if (sched_table.size() == 2) {
// The main and OS main schedulers may not exit while there are
// other schedulers
KLOG_("Disallowing main scheduler to exit");
rust_scheduler *main_sched =
get_scheduler_by_id_nolock(main_scheduler);
assert(main_sched != NULL);
main_sched->disallow_exit();
}
if (sched_table.size() == 1) {
KLOG_("Disallowing osmain scheduler to exit");
rust_scheduler *osmain_sched =
get_scheduler_by_id_nolock(osmain_scheduler);
assert(osmain_sched != NULL);
osmain_sched->disallow_exit();
}*/
id = max_sched_id++;
assert(id != INTPTR_MAX && "Hit the maximum scheduler id");
@@ -175,14 +190,21 @@ rust_kernel::wait_for_schedulers()
sched_table.erase(iter);
sched->join_task_threads();
sched->deref();
/*if (sched_table.size() == 2) {
KLOG_("Allowing main scheduler to exit");
// It's only the main schedulers left. Tell them to exit
rust_scheduler *main_sched =
get_scheduler_by_id_nolock(main_scheduler);
assert(main_sched != NULL);
main_sched->allow_exit();
}
if (sched_table.size() == 1) {
KLOG_("Allowing osmain scheduler to exit");
// It's only the osmain scheduler left. Tell it to exit
rust_scheduler *sched =
rust_scheduler *osmain_sched =
get_scheduler_by_id_nolock(osmain_scheduler);
assert(sched != NULL);
sched->allow_exit();
}
assert(osmain_sched != NULL);
osmain_sched->allow_exit();
}*/
}
if (!sched_table.empty()) {
sched_lock.wait();
@@ -318,13 +340,31 @@ rust_kernel::register_task() {
KLOG_("New non-weak tasks %" PRIdPTR, new_non_weak_tasks);
}
void
rust_kernel::allow_scheduler_exit() {
scoped_lock with(sched_lock);
KLOG_("Allowing main scheduler to exit");
// It's only the main schedulers left. Tell them to exit
rust_scheduler *main_sched =
get_scheduler_by_id_nolock(main_scheduler);
assert(main_sched != NULL);
main_sched->allow_exit();
KLOG_("Allowing osmain scheduler to exit");
rust_scheduler *osmain_sched =
get_scheduler_by_id_nolock(osmain_scheduler);
assert(osmain_sched != NULL);
osmain_sched->allow_exit();
}
void
rust_kernel::unregister_task() {
KLOG_("Unregistering task");
uintptr_t new_non_weak_tasks = sync::decrement(non_weak_tasks);
KLOG_("New non-weak tasks %" PRIdPTR, new_non_weak_tasks);
if (new_non_weak_tasks == 0) {
end_weak_tasks();
begin_shutdown();
}
}
@@ -338,7 +378,7 @@ rust_kernel::weaken_task(rust_port_id chan) {
uintptr_t new_non_weak_tasks = sync::decrement(non_weak_tasks);
KLOG_("New non-weak tasks %" PRIdPTR, new_non_weak_tasks);
if (new_non_weak_tasks == 0) {
end_weak_tasks();
begin_shutdown();
}
}
@@ -374,6 +414,23 @@ rust_kernel::end_weak_tasks() {
}
}
void
rust_kernel::begin_shutdown() {
{
scoped_lock with(sched_lock);
// FIXME #4410: This shouldn't be necessary, but because of
// unweaken_task this may end up getting called multiple times.
if (already_exiting) {
return;
} else {
already_exiting = true;
}
}
allow_scheduler_exit();
end_weak_tasks();
}
bool
rust_kernel::send_to_port(rust_port_id chan, void *sptr) {
KLOG_("rust_port_id*_send port: 0x%" PRIxPTR, (uintptr_t) chan);