2012-02-03 17:12:18 -06:00
|
|
|
#include "rust_scheduler.h"
|
|
|
|
#include "rust_util.h"
|
|
|
|
|
|
|
|
rust_scheduler::rust_scheduler(rust_kernel *kernel,
|
|
|
|
rust_srv *srv,
|
|
|
|
size_t num_threads) :
|
|
|
|
kernel(kernel),
|
|
|
|
srv(srv),
|
|
|
|
env(srv->env),
|
2012-02-04 16:54:10 -06:00
|
|
|
live_threads(num_threads),
|
2012-02-03 17:12:18 -06:00
|
|
|
num_threads(num_threads)
|
|
|
|
{
|
2012-02-03 20:42:12 -06:00
|
|
|
isaac_init(kernel, &rctx);
|
2012-02-03 17:12:18 -06:00
|
|
|
create_task_threads();
|
|
|
|
}
|
|
|
|
|
|
|
|
rust_scheduler::~rust_scheduler() {
|
|
|
|
destroy_task_threads();
|
|
|
|
}
|
|
|
|
|
|
|
|
rust_task_thread *
|
|
|
|
rust_scheduler::create_task_thread(int id) {
|
|
|
|
rust_srv *srv = this->srv->clone();
|
|
|
|
rust_task_thread *thread =
|
|
|
|
new (kernel, "rust_task_thread") rust_task_thread(this, srv, id);
|
|
|
|
KLOG(kernel, kern, "created task thread: " PTR ", id: %d, index: %d",
|
|
|
|
thread, id, thread->list_index);
|
|
|
|
return thread;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rust_scheduler::destroy_task_thread(rust_task_thread *thread) {
|
|
|
|
KLOG(kernel, kern, "deleting task thread: " PTR ", name: %s, index: %d",
|
|
|
|
thread, thread->name, thread->list_index);
|
|
|
|
rust_srv *srv = thread->srv;
|
|
|
|
delete thread;
|
|
|
|
delete srv;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rust_scheduler::create_task_threads() {
|
|
|
|
KLOG(kernel, kern, "Using %d scheduler threads.", num_threads);
|
|
|
|
|
|
|
|
for(size_t i = 0; i < num_threads; ++i) {
|
|
|
|
threads.push(create_task_thread(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rust_scheduler::destroy_task_threads() {
|
|
|
|
for(size_t i = 0; i < num_threads; ++i) {
|
|
|
|
destroy_task_thread(threads[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rust_scheduler::start_task_threads()
|
|
|
|
{
|
2012-02-05 01:42:27 -06:00
|
|
|
// Copy num_threads because it's possible for the last thread
|
|
|
|
// to terminate and have the kernel delete us before we
|
|
|
|
// hit the last check against num_threads, in which case
|
|
|
|
// we would be accessing invalid memory.
|
|
|
|
uintptr_t num_threads = this->num_threads;
|
2012-02-03 17:12:18 -06:00
|
|
|
for(size_t i = 0; i < num_threads; ++i) {
|
|
|
|
rust_task_thread *thread = threads[i];
|
|
|
|
thread->start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rust_scheduler::kill_all_tasks() {
|
|
|
|
for(size_t i = 0; i < num_threads; ++i) {
|
|
|
|
rust_task_thread *thread = threads[i];
|
|
|
|
thread->kill_all_tasks();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rust_task_id
|
|
|
|
rust_scheduler::create_task(rust_task *spawner, const char *name,
|
|
|
|
size_t init_stack_sz) {
|
|
|
|
size_t thread_no;
|
|
|
|
{
|
|
|
|
scoped_lock with(lock);
|
|
|
|
thread_no = isaac_rand(&rctx) % num_threads;
|
|
|
|
}
|
|
|
|
rust_task_thread *thread = threads[thread_no];
|
2012-02-03 19:26:54 -06:00
|
|
|
return thread->create_task(spawner, name, init_stack_sz);
|
2012-02-03 17:12:18 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
rust_task_id
|
|
|
|
rust_scheduler::create_task(rust_task *spawner, const char *name) {
|
|
|
|
return create_task(spawner, name, env->min_stack_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rust_scheduler::exit() {
|
|
|
|
for(size_t i = 0; i < num_threads; ++i) {
|
|
|
|
threads[i]->exit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t
|
|
|
|
rust_scheduler::number_of_threads() {
|
|
|
|
return num_threads;
|
|
|
|
}
|
2012-02-04 16:54:10 -06:00
|
|
|
|
|
|
|
void
|
|
|
|
rust_scheduler::release_task_thread() {
|
|
|
|
I(this, !lock.lock_held_by_current_thread());
|
|
|
|
uintptr_t new_live_threads;
|
|
|
|
{
|
|
|
|
scoped_lock with(lock);
|
|
|
|
new_live_threads = --live_threads;
|
|
|
|
}
|
|
|
|
if (new_live_threads == 0) {
|
|
|
|
kernel->release_scheduler();
|
|
|
|
}
|
|
|
|
}
|