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_crate_cache.cpp \
rt/rust_env.cpp \ rt/rust_env.cpp \
rt/rust_task_thread.cpp \ rt/rust_task_thread.cpp \
rt/rust_scheduler.cpp \
rt/rust_task.cpp \ rt/rust_task.cpp \
rt/rust_task_list.cpp \ rt/rust_task_list.cpp \
rt/rust_port.cpp \ rt/rust_port.cpp \
@@ -80,6 +81,7 @@ RUNTIME_HDR_$(1) := rt/globals.h \
rt/rust_upcall.h \ rt/rust_upcall.h \
rt/rust_port.h \ rt/rust_port.h \
rt/rust_task_thread.h \ rt/rust_task_thread.h \
rt/rust_scheduler.h \
rt/rust_shape.h \ rt/rust_shape.h \
rt/rust_task.h \ rt/rust_task.h \
rt/rust_task_list.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->deref();
root_task = NULL; root_task = NULL;
int ret = kernel->start_task_threads(); int ret = kernel->start_schedulers();
delete args; delete args;
delete kernel; delete kernel;
delete srv; delete srv;

View File

@@ -4,6 +4,7 @@
#include "rust_task_thread.h" #include "rust_task_thread.h"
#include "rust_task.h" #include "rust_task.h"
#include "rust_util.h" #include "rust_util.h"
#include "rust_scheduler.h"
#include "sync/timer.h" #include "sync/timer.h"
#if !defined(__WIN32__) #if !defined(__WIN32__)
@@ -416,7 +417,7 @@ start_task(rust_task_id id, fn_env_pair *f) {
extern "C" CDECL int extern "C" CDECL int
sched_threads() { sched_threads() {
rust_task *task = rust_task_thread::get_task(); 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* extern "C" CDECL rust_port*

View File

@@ -1,5 +1,6 @@
#include "rust_internal.h" #include "rust_internal.h"
#include "rust_util.h" #include "rust_util.h"
#include "rust_scheduler.h"
#define KLOG_(...) \ #define KLOG_(...) \
KLOG(this, kern, __VA_ARGS__) KLOG(this, kern, __VA_ARGS__)
@@ -12,64 +13,11 @@ rust_kernel::rust_kernel(rust_srv *srv, size_t num_threads) :
srv(srv), srv(srv),
max_id(0), max_id(0),
rval(0), rval(0),
num_threads(num_threads),
live_tasks(0), live_tasks(0),
env(srv->env) env(srv->env)
{ {
isaac_init(this, &rctx); sched = new (this, "rust_scheduler")
create_schedulers(); rust_scheduler(this, srv, num_threads);
}
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;
} }
void void
@@ -94,7 +42,7 @@ rust_kernel::fatal(char const *fmt, ...) {
} }
rust_kernel::~rust_kernel() { rust_kernel::~rust_kernel() {
destroy_schedulers(); delete sched;
} }
void * void *
@@ -111,24 +59,9 @@ void rust_kernel::free(void *mem) {
_region.free(mem); _region.free(mem);
} }
void int rust_kernel::start_schedulers()
rust_kernel::signal_kernel_lock() {
_kernel_lock.lock();
_kernel_lock.unlock();
}
int rust_kernel::start_task_threads()
{ {
for(size_t i = 0; i < num_threads; ++i) { sched->start_task_threads();
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();
}
return rval; return rval;
} }
@@ -141,21 +74,13 @@ rust_kernel::fail() {
#if defined(__WIN32__) #if defined(__WIN32__)
exit(rval); exit(rval);
#endif #endif
for(size_t i = 0; i < num_threads; ++i) { sched->kill_all_tasks();
rust_task_thread *thread = threads[i];
thread->kill_all_tasks();
}
} }
rust_task_id rust_task_id
rust_kernel::create_task(rust_task *spawner, const char *name, rust_kernel::create_task(rust_task *spawner, const char *name,
size_t init_stack_sz) { size_t init_stack_sz) {
scoped_lock with(_kernel_lock); return sched->create_task(spawner, name, init_stack_sz);
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;
} }
rust_task_id 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); 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_task *
rust_kernel::get_task_by_id(rust_task_id id) { rust_kernel::get_task_by_id(rust_task_id id) {
scoped_lock with(_kernel_lock); scoped_lock with(_kernel_lock);
@@ -190,9 +122,7 @@ rust_kernel::release_task_id(rust_task_id id) {
} }
void rust_kernel::exit_schedulers() { void rust_kernel::exit_schedulers() {
for(size_t i = 0; i < num_threads; ++i) { sched->exit();
threads[i]->exit();
}
} }
#ifdef __WIN32__ #ifdef __WIN32__

View File

@@ -6,6 +6,7 @@
#include "rust_log.h" #include "rust_log.h"
struct rust_task_thread; struct rust_task_thread;
struct rust_scheduler;
/** /**
* 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
@@ -20,36 +21,21 @@ public:
rust_srv *srv; rust_srv *srv;
private: private:
lock_and_signal _kernel_lock; lock_and_signal _kernel_lock;
rust_scheduler *sched;
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_task_id max_id; rust_task_id max_id;
hash_map<rust_task_id, rust_task *> task_table; hash_map<rust_task_id, rust_task *> task_table;
int rval; int rval;
public: public:
const size_t num_threads;
volatile int live_tasks; volatile int live_tasks;
struct rust_env *env; struct rust_env *env;
rust_kernel(rust_srv *srv, size_t num_threads); rust_kernel(rust_srv *srv, size_t num_threads);
bool is_deadlocked();
void signal_kernel_lock();
void exit_schedulers(); void exit_schedulers();
void log_all_scheduler_state();
void log(uint32_t level, char const *fmt, ...); void log(uint32_t level, char const *fmt, ...);
void fatal(char const *fmt, ...); void fatal(char const *fmt, ...);
virtual ~rust_kernel(); virtual ~rust_kernel();
@@ -60,7 +46,7 @@ public:
void fail(); void fail();
int start_task_threads(); int start_schedulers();
#ifdef __WIN32__ #ifdef __WIN32__
void win32_require(LPCTSTR fn, BOOL ok); void win32_require(LPCTSTR fn, BOOL ok);
@@ -69,6 +55,7 @@ public:
rust_task_id create_task(rust_task *spawner, const char *name, rust_task_id create_task(rust_task *spawner, const char *name,
size_t init_stack_size); size_t init_stack_size);
rust_task_id create_task(rust_task * spawner, const char *name); 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); rust_task *get_task_by_id(rust_task_id id);
void release_task_id(rust_task_id tid); void release_task_id(rust_task_id tid);
void set_exit_status(int code); 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_internal.h"
#include "rust_util.h" #include "rust_util.h"
#include "globals.h" #include "globals.h"
#include "rust_scheduler.h"
#ifndef _WIN32 #ifndef _WIN32
pthread_key_t rust_task_thread::task_key; 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; bool rust_task_thread::tls_initialized = false;
rust_task_thread::rust_task_thread(rust_kernel *kernel, rust_task_thread::rust_task_thread(rust_scheduler *sched,
rust_srv *srv, rust_srv *srv,
int id) : int id) :
ref_count(1), ref_count(1),
_log(srv, this), _log(srv, this),
log_lvl(log_debug), log_lvl(log_debug),
@@ -28,7 +29,8 @@ rust_task_thread::rust_task_thread(rust_kernel *kernel,
blocked_tasks(this, "blocked"), blocked_tasks(this, "blocked"),
dead_tasks(this, "dead"), dead_tasks(this, "dead"),
cache(this), cache(this),
kernel(kernel), kernel(sched->kernel),
sched(sched),
id(id), id(id),
min_stack_size(kernel->env->min_stack_size), min_stack_size(kernel->env->min_stack_size),
env(kernel->env), env(kernel->env),
@@ -217,8 +219,6 @@ rust_task_thread::start_main_loop() {
DLOG(this, dom, "started domain loop %d", id); DLOG(this, dom, "started domain loop %d", id);
while (!should_exit) { while (!should_exit) {
A(this, kernel->is_deadlocked() == false, "deadlock");
DLOG(this, dom, "worker %d, number_of_live_tasks = %d, total = %d", DLOG(this, dom, "worker %d, number_of_live_tasks = %d, total = %d",
id, number_of_live_tasks(), kernel->live_tasks); 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; randctx rctx;
rust_kernel *kernel; rust_kernel *kernel;
rust_scheduler *sched;
int32_t list_index; int32_t list_index;
const int id; 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 // Only a pointer to 'name' is kept, so it must live as long as this
// domain. // 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(); ~rust_task_thread();
void activate(rust_task *task); void activate(rust_task *task);
void log(rust_task *task, uint32_t level, char const *fmt, ...); void log(rust_task *task, uint32_t level, char const *fmt, ...);