rt: Extract rust_scheduler from rust_task_thread

This commit is contained in:
Brian Anderson 2012-02-03 15:12:18 -08:00
parent f94339cc1c
commit 8d881967a2
9 changed files with 182 additions and 112 deletions

View file

@ -43,6 +43,7 @@ RUNTIME_CS_$(1) := \
rt/rust_crate_cache.cpp \
rt/rust_env.cpp \
rt/rust_task_thread.cpp \
rt/rust_scheduler.cpp \
rt/rust_task.cpp \
rt/rust_task_list.cpp \
rt/rust_port.cpp \
@ -80,6 +81,7 @@ RUNTIME_HDR_$(1) := rt/globals.h \
rt/rust_upcall.h \
rt/rust_port.h \
rt/rust_task_thread.h \
rt/rust_scheduler.h \
rt/rust_shape.h \
rt/rust_task.h \
rt/rust_task_list.h \

View file

@ -105,7 +105,7 @@ rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
root_task->deref();
root_task = NULL;
int ret = kernel->start_task_threads();
int ret = kernel->start_schedulers();
delete args;
delete kernel;
delete srv;

View file

@ -4,6 +4,7 @@
#include "rust_task_thread.h"
#include "rust_task.h"
#include "rust_util.h"
#include "rust_scheduler.h"
#include "sync/timer.h"
#if !defined(__WIN32__)
@ -416,7 +417,7 @@ start_task(rust_task_id id, fn_env_pair *f) {
extern "C" CDECL int
sched_threads() {
rust_task *task = rust_task_thread::get_task();
return task->kernel->num_threads;
return task->thread->sched->number_of_threads();
}
extern "C" CDECL rust_port*

View file

@ -1,5 +1,6 @@
#include "rust_internal.h"
#include "rust_util.h"
#include "rust_scheduler.h"
#define KLOG_(...) \
KLOG(this, kern, __VA_ARGS__)
@ -12,64 +13,11 @@ rust_kernel::rust_kernel(rust_srv *srv, size_t num_threads) :
srv(srv),
max_id(0),
rval(0),
num_threads(num_threads),
live_tasks(0),
env(srv->env)
{
isaac_init(this, &rctx);
create_schedulers();
}
rust_task_thread *
rust_kernel::create_scheduler(int id) {
_kernel_lock.lock();
rust_srv *srv = this->srv->clone();
rust_task_thread *thread =
new (this, "rust_task_thread") rust_task_thread(this, srv, id);
KLOG_("created scheduler: " PTR ", id: %d, index: %d",
thread, id, thread->list_index);
_kernel_lock.unlock();
return thread;
}
void
rust_kernel::destroy_scheduler(rust_task_thread *thread) {
_kernel_lock.lock();
KLOG_("deleting scheduler: " PTR ", name: %s, index: %d",
thread, thread->name, thread->list_index);
rust_srv *srv = thread->srv;
delete thread;
delete srv;
_kernel_lock.unlock();
}
void rust_kernel::create_schedulers() {
KLOG_("Using %d scheduler threads.", num_threads);
for(size_t i = 0; i < num_threads; ++i) {
threads.push(create_scheduler(i));
}
}
void rust_kernel::destroy_schedulers() {
for(size_t i = 0; i < num_threads; ++i) {
destroy_scheduler(threads[i]);
}
}
void
rust_kernel::log_all_scheduler_state() {
for(size_t i = 0; i < num_threads; ++i) {
threads[i]->log_state();
}
}
/**
* Checks for simple deadlocks.
*/
bool
rust_kernel::is_deadlocked() {
return false;
sched = new (this, "rust_scheduler")
rust_scheduler(this, srv, num_threads);
}
void
@ -94,7 +42,7 @@ rust_kernel::fatal(char const *fmt, ...) {
}
rust_kernel::~rust_kernel() {
destroy_schedulers();
delete sched;
}
void *
@ -111,24 +59,9 @@ void rust_kernel::free(void *mem) {
_region.free(mem);
}
void
rust_kernel::signal_kernel_lock() {
_kernel_lock.lock();
_kernel_lock.unlock();
}
int rust_kernel::start_task_threads()
int rust_kernel::start_schedulers()
{
for(size_t i = 0; i < num_threads; ++i) {
rust_task_thread *thread = threads[i];
thread->start();
}
for(size_t i = 0; i < num_threads; ++i) {
rust_task_thread *thread = threads[i];
thread->join();
}
sched->start_task_threads();
return rval;
}
@ -141,21 +74,13 @@ rust_kernel::fail() {
#if defined(__WIN32__)
exit(rval);
#endif
for(size_t i = 0; i < num_threads; ++i) {
rust_task_thread *thread = threads[i];
thread->kill_all_tasks();
}
sched->kill_all_tasks();
}
rust_task_id
rust_kernel::create_task(rust_task *spawner, const char *name,
size_t init_stack_sz) {
scoped_lock with(_kernel_lock);
rust_task_thread *thread = threads[isaac_rand(&rctx) % num_threads];
rust_task *t = thread->create_task(spawner, name, init_stack_sz);
t->user.id = max_id++;
task_table.put(t->user.id, t);
return t->user.id;
return sched->create_task(spawner, name, init_stack_sz);
}
rust_task_id
@ -163,6 +88,13 @@ rust_kernel::create_task(rust_task *spawner, const char *name) {
return create_task(spawner, name, env->min_stack_size);
}
void
rust_kernel::register_task(rust_task *task) {
scoped_lock with(_kernel_lock);
task->user.id = max_id++;
task_table.put(task->user.id, task);
}
rust_task *
rust_kernel::get_task_by_id(rust_task_id id) {
scoped_lock with(_kernel_lock);
@ -190,9 +122,7 @@ rust_kernel::release_task_id(rust_task_id id) {
}
void rust_kernel::exit_schedulers() {
for(size_t i = 0; i < num_threads; ++i) {
threads[i]->exit();
}
sched->exit();
}
#ifdef __WIN32__

View file

@ -6,6 +6,7 @@
#include "rust_log.h"
struct rust_task_thread;
struct rust_scheduler;
/**
* A global object shared by all thread domains. Most of the data structures
@ -20,36 +21,21 @@ public:
rust_srv *srv;
private:
lock_and_signal _kernel_lock;
array_list<rust_task_thread *> threads;
randctx rctx;
rust_task_thread *create_scheduler(int id);
void destroy_scheduler(rust_task_thread *thread);
void create_schedulers();
void destroy_schedulers();
rust_scheduler *sched;
rust_task_id max_id;
hash_map<rust_task_id, rust_task *> task_table;
int rval;
public:
const size_t num_threads;
volatile int live_tasks;
struct rust_env *env;
rust_kernel(rust_srv *srv, size_t num_threads);
bool is_deadlocked();
void signal_kernel_lock();
void exit_schedulers();
void log_all_scheduler_state();
void log(uint32_t level, char const *fmt, ...);
void fatal(char const *fmt, ...);
virtual ~rust_kernel();
@ -60,7 +46,7 @@ public:
void fail();
int start_task_threads();
int start_schedulers();
#ifdef __WIN32__
void win32_require(LPCTSTR fn, BOOL ok);
@ -69,6 +55,7 @@ public:
rust_task_id create_task(rust_task *spawner, const char *name,
size_t init_stack_size);
rust_task_id create_task(rust_task * spawner, const char *name);
void register_task(rust_task *task);
rust_task *get_task_by_id(rust_task_id id);
void release_task_id(rust_task_id tid);
void set_exit_status(int code);

110
src/rt/rust_scheduler.cpp Normal file
View file

@ -0,0 +1,110 @@
#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),
num_threads(num_threads)
{
isaac_init(this, &rctx);
create_task_threads();
}
rust_scheduler::~rust_scheduler() {
destroy_task_threads();
}
rust_task_thread *
rust_scheduler::create_task_thread(int id) {
lock.lock();
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);
lock.unlock();
return thread;
}
void
rust_scheduler::destroy_task_thread(rust_task_thread *thread) {
lock.lock();
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;
lock.unlock();
}
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()
{
for(size_t i = 0; i < num_threads; ++i) {
rust_task_thread *thread = threads[i];
thread->start();
}
for(size_t i = 0; i < num_threads; ++i) {
rust_task_thread *thread = threads[i];
thread->join();
}
}
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];
rust_task *t = thread->create_task(spawner, name, init_stack_sz);
kernel->register_task(t);
return t->user.id;
}
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;
}

39
src/rt/rust_scheduler.h Normal file
View file

@ -0,0 +1,39 @@
#ifndef RUST_SCHEDULER_H
#define RUST_SCHEDULER_H
#include "rust_internal.h"
class rust_scheduler : public kernel_owned<rust_scheduler> {
// FIXME: Make these private
public:
rust_kernel *kernel;
rust_srv *srv;
rust_env *env;
private:
lock_and_signal lock;
array_list<rust_task_thread *> threads;
randctx rctx;
const size_t num_threads;
int rval;
void create_task_threads();
void destroy_task_threads();
rust_task_thread *create_task_thread(int id);
void destroy_task_thread(rust_task_thread *thread);
public:
rust_scheduler(rust_kernel *kernel, rust_srv *srv, size_t num_threads);
~rust_scheduler();
void start_task_threads();
void kill_all_tasks();
rust_task_id create_task(rust_task *spawner,
const char *name,
size_t init_stack_sz);
rust_task_id create_task(rust_task *spawner, const char *name);
void exit();
size_t number_of_threads();
};
#endif /* RUST_SCHEDULER_H */

View file

@ -5,6 +5,7 @@
#include "rust_internal.h"
#include "rust_util.h"
#include "globals.h"
#include "rust_scheduler.h"
#ifndef _WIN32
pthread_key_t rust_task_thread::task_key;
@ -14,9 +15,9 @@ DWORD rust_task_thread::task_key;
bool rust_task_thread::tls_initialized = false;
rust_task_thread::rust_task_thread(rust_kernel *kernel,
rust_srv *srv,
int id) :
rust_task_thread::rust_task_thread(rust_scheduler *sched,
rust_srv *srv,
int id) :
ref_count(1),
_log(srv, this),
log_lvl(log_debug),
@ -28,7 +29,8 @@ rust_task_thread::rust_task_thread(rust_kernel *kernel,
blocked_tasks(this, "blocked"),
dead_tasks(this, "dead"),
cache(this),
kernel(kernel),
kernel(sched->kernel),
sched(sched),
id(id),
min_stack_size(kernel->env->min_stack_size),
env(kernel->env),
@ -217,8 +219,6 @@ rust_task_thread::start_main_loop() {
DLOG(this, dom, "started domain loop %d", id);
while (!should_exit) {
A(this, kernel->is_deadlocked() == false, "deadlock");
DLOG(this, dom, "worker %d, number_of_live_tasks = %d, total = %d",
id, number_of_live_tasks(), kernel->live_tasks);

View file

@ -69,6 +69,7 @@ struct rust_task_thread : public kernel_owned<rust_task_thread>,
randctx rctx;
rust_kernel *kernel;
rust_scheduler *sched;
int32_t list_index;
const int id;
@ -92,7 +93,7 @@ struct rust_task_thread : public kernel_owned<rust_task_thread>,
// Only a pointer to 'name' is kept, so it must live as long as this
// domain.
rust_task_thread(rust_kernel *kernel, rust_srv *srv, int id);
rust_task_thread(rust_scheduler *sched, rust_srv *srv, int id);
~rust_task_thread();
void activate(rust_task *task);
void log(rust_task *task, uint32_t level, char const *fmt, ...);