Cleanup, refactoring, and some runtime tests.
This commit is contained in:
parent
f985fded3e
commit
a493350eb5
22 changed files with 279 additions and 129 deletions
|
@ -257,6 +257,7 @@ RUNTIME_CS := rt/sync/timer.cpp \
|
|||
rt/rust_comm.cpp \
|
||||
rt/rust_dom.cpp \
|
||||
rt/rust_task.cpp \
|
||||
rt/rust_task_list.cpp \
|
||||
rt/rust_proxy.cpp \
|
||||
rt/rust_chan.cpp \
|
||||
rt/rust_port.cpp \
|
||||
|
@ -270,6 +271,7 @@ RUNTIME_CS := rt/sync/timer.cpp \
|
|||
rt/rust_kernel.cpp \
|
||||
rt/memory_region.cpp \
|
||||
rt/test/rust_test_harness.cpp \
|
||||
rt/test/rust_test_runtime.cpp \
|
||||
rt/test/rust_test_util.cpp
|
||||
|
||||
RUNTIME_HDR := rt/globals.h \
|
||||
|
@ -281,6 +283,7 @@ RUNTIME_HDR := rt/globals.h \
|
|||
rt/rust_port.h \
|
||||
rt/rust_dom.h \
|
||||
rt/rust_task.h \
|
||||
rt/rust_task_list.h \
|
||||
rt/rust_proxy.h \
|
||||
rt/rust_log.h \
|
||||
rt/rust_message.h \
|
||||
|
@ -297,6 +300,7 @@ RUNTIME_HDR := rt/globals.h \
|
|||
rt/memory_region.h \
|
||||
rt/memory.h \
|
||||
rt/test/rust_test_harness.h \
|
||||
rt/test/rust_test_runtime.h \
|
||||
rt/test/rust_test_util.h
|
||||
|
||||
RUNTIME_INCS := -Irt/isaac -Irt/uthash
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
#include <stdarg.h>
|
||||
#include "rust_internal.h"
|
||||
|
||||
template class ptr_vec<rust_task>;
|
||||
|
||||
rust_dom::rust_dom(rust_kernel *kernel,
|
||||
rust_message_queue *message_queue, rust_srv *srv,
|
||||
rust_crate const *root_crate, const char *name) :
|
||||
|
@ -14,9 +12,10 @@ rust_dom::rust_dom(rust_kernel *kernel,
|
|||
local_region(&srv->local_region),
|
||||
synchronized_region(&srv->synchronized_region),
|
||||
name(name),
|
||||
running_tasks(this),
|
||||
blocked_tasks(this),
|
||||
dead_tasks(this),
|
||||
newborn_tasks(this, "newborn"),
|
||||
running_tasks(this, "running"),
|
||||
blocked_tasks(this, "blocked"),
|
||||
dead_tasks(this, "dead"),
|
||||
caches(this),
|
||||
root_task(NULL),
|
||||
curr_task(NULL),
|
||||
|
@ -31,28 +30,16 @@ rust_dom::rust_dom(rust_kernel *kernel,
|
|||
pthread_attr_setstacksize(&attr, 1024 * 1024);
|
||||
pthread_attr_setdetachstate(&attr, true);
|
||||
#endif
|
||||
root_task = new (this) rust_task(this, NULL, name);
|
||||
}
|
||||
|
||||
static void
|
||||
del_all_tasks(rust_dom *dom, ptr_vec<rust_task> *v) {
|
||||
I(dom, v);
|
||||
while (v->length()) {
|
||||
dom->log(rust_log::TASK, "deleting task 0x%" PRIdPTR,
|
||||
v->length() - 1);
|
||||
delete v->pop();
|
||||
}
|
||||
root_task = create_task(NULL, name);
|
||||
}
|
||||
|
||||
rust_dom::~rust_dom() {
|
||||
log(rust_log::MEM | rust_log::DOM,
|
||||
"~rust_dom %s @0x%" PRIxPTR, name, (uintptr_t)this);
|
||||
log(rust_log::TASK, "deleting all running tasks");
|
||||
del_all_tasks(this, &running_tasks);
|
||||
log(rust_log::TASK, "deleting all blocked tasks");
|
||||
del_all_tasks(this, &blocked_tasks);
|
||||
log(rust_log::TASK, "deleting all dead tasks");
|
||||
del_all_tasks(this, &dead_tasks);
|
||||
newborn_tasks.delete_all();
|
||||
running_tasks.delete_all();
|
||||
blocked_tasks.delete_all();
|
||||
dead_tasks.delete_all();
|
||||
#ifndef __WIN32__
|
||||
pthread_attr_destroy(&attr);
|
||||
#endif
|
||||
|
@ -198,42 +185,10 @@ rust_dom::win32_require(LPCTSTR fn, BOOL ok) {
|
|||
#endif
|
||||
|
||||
size_t
|
||||
rust_dom::n_live_tasks()
|
||||
{
|
||||
rust_dom::number_of_live_tasks() {
|
||||
return running_tasks.length() + blocked_tasks.length();
|
||||
}
|
||||
|
||||
void
|
||||
rust_dom::add_task_to_state_vec(ptr_vec<rust_task> *v, rust_task *task)
|
||||
{
|
||||
log(rust_log::MEM|rust_log::TASK,
|
||||
"adding task %s @0x%" PRIxPTR " in state '%s' to vec 0x%" PRIxPTR,
|
||||
task->name, (uintptr_t)task, state_vec_name(v), (uintptr_t)v);
|
||||
v->push(task);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
rust_dom::remove_task_from_state_vec(ptr_vec<rust_task> *v, rust_task *task)
|
||||
{
|
||||
log(rust_log::MEM|rust_log::TASK,
|
||||
"removing task %s @0x%" PRIxPTR " in state '%s' from vec 0x%" PRIxPTR,
|
||||
task->name, (uintptr_t)task, state_vec_name(v), (uintptr_t)v);
|
||||
I(this, (*v)[task->idx] == task);
|
||||
v->swap_delete(task);
|
||||
}
|
||||
|
||||
const char *
|
||||
rust_dom::state_vec_name(ptr_vec<rust_task> *v)
|
||||
{
|
||||
if (v == &running_tasks)
|
||||
return "running";
|
||||
if (v == &blocked_tasks)
|
||||
return "blocked";
|
||||
I(this, v == &dead_tasks);
|
||||
return "dead";
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete any dead tasks.
|
||||
*/
|
||||
|
@ -243,7 +198,7 @@ rust_dom::reap_dead_tasks() {
|
|||
rust_task *task = dead_tasks[i];
|
||||
if (task->ref_count == 0) {
|
||||
I(this, task->tasks_waiting_to_join.is_empty());
|
||||
dead_tasks.swap_delete(task);
|
||||
dead_tasks.remove(task);
|
||||
log(rust_log::TASK,
|
||||
"deleting unreferenced dead task %s @0x%" PRIxPTR,
|
||||
task->name, task);
|
||||
|
@ -288,7 +243,6 @@ rust_dom::schedule_task() {
|
|||
return (rust_task *)running_tasks[i];
|
||||
}
|
||||
}
|
||||
// log(rust_log::DOM|rust_log::TASK, "no schedulable tasks");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -334,16 +288,16 @@ rust_dom::log_state() {
|
|||
* drop to zero.
|
||||
*/
|
||||
int
|
||||
rust_dom::start_main_loop()
|
||||
{
|
||||
rust_dom::start_main_loop() {
|
||||
// Make sure someone is watching, to pull us out of infinite loops.
|
||||
rust_timer timer(this);
|
||||
|
||||
log(rust_log::DOM, "running main-loop on domain %s @0x%" PRIxPTR,
|
||||
name, this);
|
||||
logptr("exit-task glue", root_crate->get_exit_task_glue());
|
||||
log(rust_log::DOM, "started domain loop");
|
||||
log(rust_log::DOM | rust_log::MEM,
|
||||
"activate glue: " PTR ", exit glue: " PTR,
|
||||
root_crate->get_activate_glue(), root_crate->get_exit_task_glue());
|
||||
|
||||
while (n_live_tasks() > 0) {
|
||||
while (number_of_live_tasks() > 0) {
|
||||
A(this, kernel->is_deadlocked() == false, "deadlock");
|
||||
|
||||
drain_incoming_message_queue(true);
|
||||
|
@ -377,7 +331,7 @@ rust_dom::start_main_loop()
|
|||
(uintptr_t)scheduled_task,
|
||||
scheduled_task->rust_sp,
|
||||
scheduled_task->ref_count,
|
||||
scheduled_task->state_str());
|
||||
scheduled_task->state->name);
|
||||
|
||||
interrupt_flag = 0;
|
||||
|
||||
|
@ -388,7 +342,7 @@ rust_dom::start_main_loop()
|
|||
" in state '%s', sp=0x%" PRIxPTR,
|
||||
scheduled_task->name,
|
||||
(uintptr_t)scheduled_task,
|
||||
state_vec_name(scheduled_task->state),
|
||||
scheduled_task->state->name,
|
||||
scheduled_task->rust_sp);
|
||||
|
||||
I(this, scheduled_task->rust_sp >=
|
||||
|
@ -443,6 +397,15 @@ rust_dom::get_cache(rust_crate const *crate) {
|
|||
return cache;
|
||||
}
|
||||
|
||||
rust_task *
|
||||
rust_dom::create_task(rust_task *spawner, const char *name) {
|
||||
rust_task *task =
|
||||
new (this) rust_task (this, &newborn_tasks, spawner, name);
|
||||
log(rust_log::TASK, "created task: " PTR ", spawner: %s, name: %s",
|
||||
task, spawner ? spawner->name : "null", name);
|
||||
newborn_tasks.append(task);
|
||||
return task;
|
||||
}
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
|
|
|
@ -18,10 +18,14 @@ struct rust_dom : public kernel_owned<rust_dom>, rc_base<rust_dom>
|
|||
memory_region local_region;
|
||||
memory_region synchronized_region;
|
||||
const char *const name;
|
||||
ptr_vec<rust_task> running_tasks;
|
||||
ptr_vec<rust_task> blocked_tasks;
|
||||
ptr_vec<rust_task> dead_tasks;
|
||||
|
||||
rust_task_list newborn_tasks;
|
||||
rust_task_list running_tasks;
|
||||
rust_task_list blocked_tasks;
|
||||
rust_task_list dead_tasks;
|
||||
|
||||
ptr_vec<rust_crate_cache> caches;
|
||||
|
||||
randctx rctx;
|
||||
rust_task *root_task;
|
||||
rust_task *curr_task;
|
||||
|
@ -71,10 +75,7 @@ struct rust_dom : public kernel_owned<rust_dom>, rc_base<rust_dom>
|
|||
#endif
|
||||
|
||||
rust_crate_cache *get_cache(rust_crate const *crate);
|
||||
size_t n_live_tasks();
|
||||
void add_task_to_state_vec(ptr_vec<rust_task> *v, rust_task *task);
|
||||
void remove_task_from_state_vec(ptr_vec<rust_task> *v, rust_task *task);
|
||||
const char *state_vec_name(ptr_vec<rust_task> *v);
|
||||
size_t number_of_live_tasks();
|
||||
|
||||
void reap_dead_tasks();
|
||||
rust_task *schedule_task();
|
||||
|
@ -83,6 +84,8 @@ struct rust_dom : public kernel_owned<rust_dom>, rc_base<rust_dom>
|
|||
|
||||
void log_state();
|
||||
static void log_all_state();
|
||||
|
||||
rust_task *create_task(rust_task *spawner, const char *name);
|
||||
};
|
||||
|
||||
//
|
||||
|
|
|
@ -124,6 +124,8 @@ template <typename T> struct region_owned {
|
|||
}
|
||||
};
|
||||
|
||||
#include "rust_task_list.h"
|
||||
|
||||
// A cond(ition) is something we can block on. This can be a channel
|
||||
// (writing), a port (reading) or a task (waiting).
|
||||
|
||||
|
@ -203,9 +205,7 @@ crate_rel(rust_crate const *crate, T const *t) {
|
|||
|
||||
typedef void CDECL (*activate_glue_ty)(rust_task *);
|
||||
|
||||
class
|
||||
rust_crate
|
||||
{
|
||||
class rust_crate {
|
||||
// The following fields are emitted by the compiler for the static
|
||||
// rust_crate object inside each compiled crate.
|
||||
|
||||
|
@ -563,6 +563,7 @@ struct gc_alloc {
|
|||
|
||||
#include "test/rust_test_harness.h"
|
||||
#include "test/rust_test_util.h"
|
||||
#include "test/rust_test_runtime.h"
|
||||
|
||||
//
|
||||
// Local Variables:
|
||||
|
|
|
@ -4,9 +4,7 @@ rust_kernel::rust_kernel(rust_srv *srv) :
|
|||
_region(&srv->local_region),
|
||||
_log(srv, NULL),
|
||||
_srv(srv),
|
||||
_interrupt_kernel_loop(FALSE),
|
||||
domains(&srv->local_region),
|
||||
message_queues(&srv->local_region) {
|
||||
_interrupt_kernel_loop(FALSE) {
|
||||
// Nop.
|
||||
}
|
||||
|
||||
|
@ -22,6 +20,9 @@ rust_kernel::create_domain(const rust_crate *crate, const char *name) {
|
|||
message_queue->associate(handle);
|
||||
domains.append(dom);
|
||||
message_queues.append(message_queue);
|
||||
log(rust_log::KERN | rust_log::TASK,
|
||||
"created domain: " PTR ", name: %s, index: %d, domains %d",
|
||||
dom, name, dom->list_index, domains.length());
|
||||
_kernel_lock.signal_all();
|
||||
_kernel_lock.unlock();
|
||||
return handle;
|
||||
|
@ -30,8 +31,9 @@ rust_kernel::create_domain(const rust_crate *crate, const char *name) {
|
|||
void
|
||||
rust_kernel::destroy_domain(rust_dom *dom) {
|
||||
_kernel_lock.lock();
|
||||
log(rust_log::KERN, "deleting domain: " PTR ", index: %d, domains %d",
|
||||
dom, dom->list_index, domains.length());
|
||||
log(rust_log::KERN,
|
||||
"deleting domain: " PTR ", name: %s, index: %d, domains %d",
|
||||
dom, dom->name, dom->list_index, domains.length());
|
||||
domains.remove(dom);
|
||||
dom->message_queue->disassociate();
|
||||
rust_srv *srv = dom->srv;
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
// FIXME (issue #151): This should be 0x300; the change here is for
|
||||
// practicality's sake until stack growth is working.
|
||||
static size_t const min_stk_bytes = 0x300000;
|
||||
// static size_t const min_stk_bytes = 0x10000;
|
||||
|
||||
// Task stack segments. Heap allocated and chained together.
|
||||
|
||||
|
@ -54,7 +55,8 @@ align_down(uintptr_t sp)
|
|||
}
|
||||
|
||||
|
||||
rust_task::rust_task(rust_dom *dom, rust_task *spawner, const char *name) :
|
||||
rust_task::rust_task(rust_dom *dom, rust_task_list *state,
|
||||
rust_task *spawner, const char *name) :
|
||||
maybe_proxy<rust_task>(this),
|
||||
stk(new_stk(dom, 0)),
|
||||
runtime_sp(0),
|
||||
|
@ -63,11 +65,11 @@ rust_task::rust_task(rust_dom *dom, rust_task *spawner, const char *name) :
|
|||
dom(dom),
|
||||
cache(NULL),
|
||||
name(name),
|
||||
state(&dom->running_tasks),
|
||||
state(state),
|
||||
cond(NULL),
|
||||
cond_name("none"),
|
||||
supervisor(spawner),
|
||||
idx(0),
|
||||
list_index(-1),
|
||||
rendezvous_ptr(0),
|
||||
alarm(this),
|
||||
handle(NULL)
|
||||
|
@ -197,7 +199,7 @@ rust_task::start(uintptr_t exit_task_glue,
|
|||
// Back up one, we overshot where sp should be.
|
||||
rust_sp = (uintptr_t) (spp+1);
|
||||
|
||||
dom->add_task_to_state_vec(&dom->running_tasks, this);
|
||||
transition(&dom->newborn_tasks, &dom->running_tasks);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -544,23 +546,14 @@ rust_task::free(void *p, bool is_gc)
|
|||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
rust_task::state_str() {
|
||||
return dom->state_vec_name(state);
|
||||
}
|
||||
|
||||
void
|
||||
rust_task::transition(ptr_vec<rust_task> *src, ptr_vec<rust_task> *dst)
|
||||
{
|
||||
rust_task::transition(rust_task_list *src, rust_task_list *dst) {
|
||||
I(dom, state == src);
|
||||
dom->log(rust_log::TASK,
|
||||
"task %s @0x%" PRIxPTR " state change '%s' -> '%s'",
|
||||
name,
|
||||
(uintptr_t)this,
|
||||
dom->state_vec_name(src),
|
||||
dom->state_vec_name(dst));
|
||||
dom->remove_task_from_state_vec(src, this);
|
||||
dom->add_task_to_state_vec(dst, this);
|
||||
"task %s " PTR " state change '%s' -> '%s'",
|
||||
name, (uintptr_t)this, src->name, dst->name);
|
||||
src->remove(this);
|
||||
dst->append(this);
|
||||
state = dst;
|
||||
}
|
||||
|
||||
|
@ -577,8 +570,7 @@ rust_task::block(rust_cond *on, const char* name) {
|
|||
}
|
||||
|
||||
void
|
||||
rust_task::wakeup(rust_cond *from)
|
||||
{
|
||||
rust_task::wakeup(rust_cond *from) {
|
||||
A(dom, cond != NULL, "Cannot wake up unblocked task.");
|
||||
log(rust_log::TASK, "Blocked on 0x%" PRIxPTR " woken up on 0x%" PRIxPTR,
|
||||
(uintptr_t) cond, (uintptr_t) from);
|
||||
|
@ -591,14 +583,12 @@ rust_task::wakeup(rust_cond *from)
|
|||
}
|
||||
|
||||
void
|
||||
rust_task::die()
|
||||
{
|
||||
rust_task::die() {
|
||||
transition(&dom->running_tasks, &dom->dead_tasks);
|
||||
}
|
||||
|
||||
void
|
||||
rust_task::unblock()
|
||||
{
|
||||
rust_task::unblock() {
|
||||
if (blocked())
|
||||
wakeup(cond);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
#include "util/array_list.h"
|
||||
|
||||
|
||||
struct
|
||||
rust_task : public maybe_proxy<rust_task>,
|
||||
public dom_owned<rust_task>
|
||||
|
@ -22,11 +21,11 @@ rust_task : public maybe_proxy<rust_task>,
|
|||
|
||||
// Fields known only to the runtime.
|
||||
const char *const name;
|
||||
ptr_vec<rust_task> *state;
|
||||
rust_task_list *state;
|
||||
rust_cond *cond;
|
||||
const char *cond_name;
|
||||
rust_task *supervisor; // Parent-link for failure propagation.
|
||||
size_t idx;
|
||||
int32_t list_index;
|
||||
size_t gc_alloc_thresh;
|
||||
size_t gc_alloc_accum;
|
||||
|
||||
|
@ -50,6 +49,7 @@ rust_task : public maybe_proxy<rust_task>,
|
|||
|
||||
// Only a pointer to 'name' is kept, so it must live as long as this task.
|
||||
rust_task(rust_dom *dom,
|
||||
rust_task_list *state,
|
||||
rust_task *spawner,
|
||||
const char *name);
|
||||
|
||||
|
@ -71,8 +71,7 @@ rust_task : public maybe_proxy<rust_task>,
|
|||
void *realloc(void *data, size_t sz, bool gc_mem=false);
|
||||
void free(void *p, bool gc_mem=false);
|
||||
|
||||
const char *state_str();
|
||||
void transition(ptr_vec<rust_task> *svec, ptr_vec<rust_task> *dvec);
|
||||
void transition(rust_task_list *src, rust_task_list *dst);
|
||||
|
||||
void block(rust_cond *on, const char* name);
|
||||
void wakeup(rust_cond *from);
|
||||
|
|
16
src/rt/rust_task_list.cpp
Normal file
16
src/rt/rust_task_list.cpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include "rust_internal.h"
|
||||
|
||||
rust_task_list::rust_task_list (rust_dom *dom, const char* name) :
|
||||
dom(dom), name(name) {
|
||||
// Nop;
|
||||
}
|
||||
|
||||
void
|
||||
rust_task_list::delete_all() {
|
||||
dom->log(rust_log::TASK, "deleting all %s tasks", name);
|
||||
while (is_empty() == false) {
|
||||
rust_task *task = pop_value();
|
||||
dom->log(rust_log::TASK, "deleting task " PTR, task);
|
||||
delete task;
|
||||
}
|
||||
}
|
16
src/rt/rust_task_list.h
Normal file
16
src/rt/rust_task_list.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef RUST_TASK_LIST_H
|
||||
#define RUST_TASK_LIST_H
|
||||
|
||||
/**
|
||||
* Used to indicate the state of a rust task.
|
||||
*/
|
||||
class rust_task_list : public indexed_list<rust_task>,
|
||||
public dom_owned<rust_task_list> {
|
||||
public:
|
||||
rust_dom *dom;
|
||||
const char* name;
|
||||
rust_task_list (rust_dom *dom, const char* name);
|
||||
void delete_all();
|
||||
};
|
||||
|
||||
#endif /* RUST_TASK_LIST_H */
|
|
@ -542,12 +542,8 @@ upcall_get_type_desc(rust_task *task,
|
|||
extern "C" CDECL rust_task *
|
||||
upcall_new_task(rust_task *spawner, const char *name) {
|
||||
LOG_UPCALL_ENTRY(spawner);
|
||||
|
||||
rust_dom *dom = spawner->dom;
|
||||
rust_task *task = new (dom) rust_task(dom, spawner, name);
|
||||
dom->log(rust_log::UPCALL | rust_log::MEM | rust_log::TASK,
|
||||
"upcall new_task(spawner %s @0x%" PRIxPTR ", %s) = 0x%" PRIxPTR,
|
||||
spawner->name, spawner, name, task);
|
||||
rust_task *task = dom->create_task(spawner, name);
|
||||
return task;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,18 @@ void sync::yield() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void sync::sleep(size_t timeout_in_ms) {
|
||||
#ifdef __WIN32__
|
||||
Sleep(timeout_in_ms);
|
||||
#else
|
||||
usleep(timeout_in_ms * 1000);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sync::random_sleep(size_t max_timeout_in_ms) {
|
||||
sleep(rand() % max_timeout_in_ms);
|
||||
}
|
||||
|
||||
rust_thread::rust_thread() : _is_running(false), thread(0) {
|
||||
// Nop.
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
class sync {
|
||||
public:
|
||||
static void yield();
|
||||
static void sleep(size_t timeout_in_ms);
|
||||
static void random_sleep(size_t max_timeout_in_ms);
|
||||
template <class T>
|
||||
static bool compare_and_swap(T *address,
|
||||
T oldValue, T newValue) {
|
||||
|
|
|
@ -25,6 +25,11 @@ timer::get_elapsed_time() {
|
|||
return get_time() - _start;
|
||||
}
|
||||
|
||||
double
|
||||
timer::get_elapsed_time_in_ms() {
|
||||
return (double) get_elapsed_time() / 1000.0;
|
||||
}
|
||||
|
||||
int64_t
|
||||
timer::get_timeout() {
|
||||
return _timeout - get_elapsed_time();
|
||||
|
|
|
@ -17,6 +17,7 @@ public:
|
|||
timer();
|
||||
void reset(uint64_t timeout);
|
||||
uint64_t get_elapsed_time();
|
||||
double get_elapsed_time_in_ms();
|
||||
int64_t get_timeout();
|
||||
bool has_timed_out();
|
||||
virtual ~timer();
|
||||
|
|
|
@ -10,7 +10,9 @@ rust_test::name() {
|
|||
return "untitled";
|
||||
}
|
||||
|
||||
rust_test_suite::rust_test_suite() {
|
||||
rust_test_suite::rust_test_suite(rust_crate *crate) : crate(crate) {
|
||||
tests.append(new rust_domain_test());
|
||||
tests.append(new rust_task_test(this));
|
||||
tests.append(new rust_array_list_test());
|
||||
tests.append(new rust_synchronized_indexed_list_test());
|
||||
}
|
||||
|
@ -25,11 +27,12 @@ rust_test_suite::run() {
|
|||
for (size_t i = 0; i < tests.size(); i++) {
|
||||
rust_test *test = tests[i];
|
||||
printf("test: %s running ... \n", test->name());
|
||||
if (tests[i]->run() == false) {
|
||||
printf("test: %s FAILED\n", test->name());
|
||||
timer timer;
|
||||
bool result = tests[i]->run();
|
||||
printf("test: %s %s %.2f ms\n", test->name(),
|
||||
result ? "PASSED" : "FAILE", timer.get_elapsed_time_in_ms());
|
||||
if (result == false) {
|
||||
pass = false;
|
||||
} else {
|
||||
printf("test: %s PASSED\n", test->name());
|
||||
}
|
||||
}
|
||||
return pass;
|
||||
|
|
|
@ -13,8 +13,9 @@ public:
|
|||
|
||||
class rust_test_suite : public rust_test {
|
||||
public:
|
||||
rust_crate *crate;
|
||||
array_list<rust_test*> tests;
|
||||
rust_test_suite();
|
||||
rust_test_suite(rust_crate *crate);
|
||||
virtual ~rust_test_suite();
|
||||
bool run();
|
||||
};
|
||||
|
|
77
src/rt/test/rust_test_runtime.cpp
Normal file
77
src/rt/test/rust_test_runtime.cpp
Normal file
|
@ -0,0 +1,77 @@
|
|||
#include "rust_test_runtime.h"
|
||||
|
||||
rust_test_runtime::rust_test_runtime() {
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
rust_test_runtime::~rust_test_runtime() {
|
||||
// TODO Auto-generated destructor stub
|
||||
}
|
||||
|
||||
#define DOMAINS 32
|
||||
#define TASKS 32
|
||||
|
||||
void
|
||||
rust_domain_test::worker::run() {
|
||||
rust_handle<rust_dom> *handle = kernel->create_domain(NULL, "test");
|
||||
for (int i = 0; i < TASKS; i++) {
|
||||
handle->referent()->create_task(NULL, "child");
|
||||
}
|
||||
sync::random_sleep(1000);
|
||||
kernel->destroy_domain(handle->_referent);
|
||||
}
|
||||
|
||||
bool
|
||||
rust_domain_test::run() {
|
||||
rust_srv srv;
|
||||
rust_kernel kernel(&srv);
|
||||
|
||||
array_list<worker *> workers;
|
||||
for (int i = 0; i < DOMAINS; i++) {
|
||||
worker *worker = new rust_domain_test::worker (&kernel);
|
||||
workers.append(worker);
|
||||
worker->start();
|
||||
}
|
||||
|
||||
// We don't join the worker threads here in order to simulate ad-hoc
|
||||
// termination of domains. If we join_all_domains before all domains
|
||||
// are actually spawned, this could crash, thus the reason for the
|
||||
// sleep below.
|
||||
|
||||
sync::sleep(100);
|
||||
kernel.join_all_domains();
|
||||
return true;
|
||||
}
|
||||
|
||||
void task_entry() {
|
||||
printf("task entry\n");
|
||||
}
|
||||
|
||||
void
|
||||
rust_task_test::worker::run() {
|
||||
rust_crate *crate = parent->suite->crate;
|
||||
rust_handle<rust_dom> *handle =
|
||||
kernel->create_domain(crate, "test");
|
||||
rust_dom *domain = handle->referent();
|
||||
domain->root_task->start(crate->get_exit_task_glue(),
|
||||
(uintptr_t)&task_entry, NULL, 0);
|
||||
domain->start_main_loop();
|
||||
kernel->destroy_domain(domain);
|
||||
}
|
||||
|
||||
bool
|
||||
rust_task_test::run() {
|
||||
rust_srv srv;
|
||||
rust_kernel kernel(&srv);
|
||||
|
||||
array_list<worker *> workers;
|
||||
for (int i = 0; i < DOMAINS; i++) {
|
||||
worker *worker = new rust_task_test::worker (&kernel, this);
|
||||
workers.append(worker);
|
||||
worker->start();
|
||||
}
|
||||
|
||||
sync::random_sleep(1000);
|
||||
kernel.join_all_domains();
|
||||
return true;
|
||||
}
|
51
src/rt/test/rust_test_runtime.h
Normal file
51
src/rt/test/rust_test_runtime.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
#include "../rust_internal.h"
|
||||
|
||||
#ifndef RUST_TEST_RUNTIME_H
|
||||
#define RUST_TEST_RUNTIME_H
|
||||
|
||||
class rust_test_runtime {
|
||||
public:
|
||||
rust_test_runtime();
|
||||
virtual ~rust_test_runtime();
|
||||
};
|
||||
|
||||
|
||||
class rust_domain_test : public rust_test {
|
||||
public:
|
||||
class worker : public rust_thread {
|
||||
public:
|
||||
rust_kernel *kernel;
|
||||
worker(rust_kernel *kernel) : kernel(kernel) {
|
||||
// Nop.
|
||||
}
|
||||
void run();
|
||||
};
|
||||
bool run();
|
||||
const char *name() {
|
||||
return "rust_domain_test";
|
||||
}
|
||||
};
|
||||
|
||||
class rust_task_test : public rust_test {
|
||||
public:
|
||||
rust_test_suite *suite;
|
||||
rust_task_test(rust_test_suite *suite) : suite(suite) {
|
||||
// Nop.
|
||||
}
|
||||
class worker : public rust_thread {
|
||||
public:
|
||||
rust_kernel *kernel;
|
||||
rust_task_test *parent;
|
||||
worker(rust_kernel *kernel, rust_task_test *parent) :
|
||||
kernel(kernel), parent(parent) {
|
||||
// Nop.
|
||||
}
|
||||
void run();
|
||||
};
|
||||
bool run();
|
||||
const char *name() {
|
||||
return "rust_task_test";
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* RUST_TEST_RUNTIME_H */
|
|
@ -1,7 +1,7 @@
|
|||
#include "../rust_internal.h"
|
||||
|
||||
#define COUNT 1000
|
||||
#define LARGE_COUNT 100000
|
||||
#define LARGE_COUNT 10000
|
||||
#define THREADS 10
|
||||
|
||||
bool
|
||||
|
|
|
@ -18,11 +18,9 @@ public:
|
|||
class rust_synchronized_indexed_list_test : public rust_test {
|
||||
public:
|
||||
rust_srv srv;
|
||||
memory_region region;
|
||||
synchronized_indexed_list<indexed_list_element<int> > list;
|
||||
|
||||
rust_synchronized_indexed_list_test() :
|
||||
region(&srv, false), list(®ion) {
|
||||
rust_synchronized_indexed_list_test() {
|
||||
// Nop.
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include "array_list.h"
|
||||
#include "../memory_region.h"
|
||||
|
||||
class indexed_list_object {
|
||||
public:
|
||||
|
@ -28,12 +27,14 @@ public:
|
|||
* object inserted in this list must define a "int32_t list_index" member.
|
||||
*/
|
||||
template<typename T> class indexed_list {
|
||||
memory_region *region;
|
||||
array_list<T*> list;
|
||||
public:
|
||||
indexed_list(memory_region *region) : region(region) {}
|
||||
virtual int32_t append(T *value);
|
||||
virtual bool pop(T **value);
|
||||
/**
|
||||
* Same as pop(), except that it returns NULL if the list is empty.
|
||||
*/
|
||||
virtual T* pop_value();
|
||||
virtual size_t length() {
|
||||
return list.size();
|
||||
}
|
||||
|
@ -76,6 +77,15 @@ indexed_list<T>::pop(T **value) {
|
|||
return list.pop(value);
|
||||
}
|
||||
|
||||
template<typename T> T*
|
||||
indexed_list<T>::pop_value() {
|
||||
T *value = NULL;
|
||||
if (list.pop(&value)) {
|
||||
return value;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename T> T *
|
||||
indexed_list<T>::operator[](int32_t index) {
|
||||
T *value = list[index];
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
#define SYNCHRONIZED_INDEXED_LIST_H
|
||||
|
||||
#include "indexed_list.h"
|
||||
#include "../sync/lock_and_signal.h"
|
||||
|
||||
template<typename T> class synchronized_indexed_list :
|
||||
public indexed_list<T> {
|
||||
lock_and_signal _lock;
|
||||
|
||||
public:
|
||||
synchronized_indexed_list(memory_region *region) :
|
||||
indexed_list<T>(region) {
|
||||
synchronized_indexed_list() {
|
||||
// Nop.
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue