rt: Extract rust_scheduler from rust_task_thread
This commit is contained in:
parent
f94339cc1c
commit
8d881967a2
9 changed files with 182 additions and 112 deletions
2
mk/rt.mk
2
mk/rt.mk
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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*
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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
110
src/rt/rust_scheduler.cpp
Normal 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
39
src/rt/rust_scheduler.h
Normal 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 */
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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, ...);
|
||||
|
|
Loading…
Add table
Reference in a new issue