aboutsummaryrefslogtreecommitdiff
path: root/src/rt
diff options
context:
space:
mode:
authorMichael Bebenita <[email protected]>2010-09-10 01:21:29 -0700
committerMichael Bebenita <[email protected]>2010-09-10 14:38:31 -0700
commita493350eb5ab38ba8a6563f3eb4a090d257b0d3a (patch)
treedc984eaa28a55de9f05db0b961a0e67f80ca35ef /src/rt
parentAdded lock_and_signal::signal_all(), and made the rust_kernel::join() use wai... (diff)
downloadrust-a493350eb5ab38ba8a6563f3eb4a090d257b0d3a.tar.xz
rust-a493350eb5ab38ba8a6563f3eb4a090d257b0d3a.zip
Cleanup, refactoring, and some runtime tests.
Diffstat (limited to 'src/rt')
-rw-r--r--src/rt/rust_dom.cpp93
-rw-r--r--src/rt/rust_dom.h17
-rw-r--r--src/rt/rust_internal.h7
-rw-r--r--src/rt/rust_kernel.cpp12
-rw-r--r--src/rt/rust_task.cpp38
-rw-r--r--src/rt/rust_task.h9
-rw-r--r--src/rt/rust_task_list.cpp16
-rw-r--r--src/rt/rust_task_list.h16
-rw-r--r--src/rt/rust_upcall.cpp6
-rw-r--r--src/rt/sync/sync.cpp12
-rw-r--r--src/rt/sync/sync.h2
-rw-r--r--src/rt/sync/timer.cpp5
-rw-r--r--src/rt/sync/timer.h1
-rw-r--r--src/rt/test/rust_test_harness.cpp13
-rw-r--r--src/rt/test/rust_test_harness.h3
-rw-r--r--src/rt/test/rust_test_runtime.cpp77
-rw-r--r--src/rt/test/rust_test_runtime.h51
-rw-r--r--src/rt/test/rust_test_util.cpp2
-rw-r--r--src/rt/test/rust_test_util.h4
-rw-r--r--src/rt/util/indexed_list.h16
-rw-r--r--src/rt/util/synchronized_indexed_list.h4
21 files changed, 275 insertions, 129 deletions
diff --git a/src/rt/rust_dom.cpp b/src/rt/rust_dom.cpp
index 323e9c39..d3b5d2ce 100644
--- a/src/rt/rust_dom.cpp
+++ b/src/rt/rust_dom.cpp
@@ -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:
diff --git a/src/rt/rust_dom.h b/src/rt/rust_dom.h
index 3f90bb67..8aa24192 100644
--- a/src/rt/rust_dom.h
+++ b/src/rt/rust_dom.h
@@ -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);
};
//
diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h
index 0913f967..d1eec48b 100644
--- a/src/rt/rust_internal.h
+++ b/src/rt/rust_internal.h
@@ -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:
diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp
index 549b85d3..ef4220f9 100644
--- a/src/rt/rust_kernel.cpp
+++ b/src/rt/rust_kernel.cpp
@@ -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;
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
index 97502588..3bc41b93 100644
--- a/src/rt/rust_task.cpp
+++ b/src/rt/rust_task.cpp
@@ -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);
}
diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h
index 7b0cfef7..26ba872d 100644
--- a/src/rt/rust_task.h
+++ b/src/rt/rust_task.h
@@ -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);
diff --git a/src/rt/rust_task_list.cpp b/src/rt/rust_task_list.cpp
new file mode 100644
index 00000000..635ee136
--- /dev/null
+++ b/src/rt/rust_task_list.cpp
@@ -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;
+ }
+}
diff --git a/src/rt/rust_task_list.h b/src/rt/rust_task_list.h
new file mode 100644
index 00000000..b1fba750
--- /dev/null
+++ b/src/rt/rust_task_list.h
@@ -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 */
diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp
index 4b5fa1d6..9a5e73f8 100644
--- a/src/rt/rust_upcall.cpp
+++ b/src/rt/rust_upcall.cpp
@@ -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;
}
diff --git a/src/rt/sync/sync.cpp b/src/rt/sync/sync.cpp
index c754392a..be874a11 100644
--- a/src/rt/sync/sync.cpp
+++ b/src/rt/sync/sync.cpp
@@ -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.
}
diff --git a/src/rt/sync/sync.h b/src/rt/sync/sync.h
index 3829dafe..bd755e1f 100644
--- a/src/rt/sync/sync.h
+++ b/src/rt/sync/sync.h
@@ -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) {
diff --git a/src/rt/sync/timer.cpp b/src/rt/sync/timer.cpp
index 0487b397..e6fe3688 100644
--- a/src/rt/sync/timer.cpp
+++ b/src/rt/sync/timer.cpp
@@ -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();
diff --git a/src/rt/sync/timer.h b/src/rt/sync/timer.h
index 509fd22c..aae098a1 100644
--- a/src/rt/sync/timer.h
+++ b/src/rt/sync/timer.h
@@ -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();
diff --git a/src/rt/test/rust_test_harness.cpp b/src/rt/test/rust_test_harness.cpp
index c33e170e..41000a6d 100644
--- a/src/rt/test/rust_test_harness.cpp
+++ b/src/rt/test/rust_test_harness.cpp
@@ -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;
diff --git a/src/rt/test/rust_test_harness.h b/src/rt/test/rust_test_harness.h
index 401015e4..8dd8baaa 100644
--- a/src/rt/test/rust_test_harness.h
+++ b/src/rt/test/rust_test_harness.h
@@ -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();
};
diff --git a/src/rt/test/rust_test_runtime.cpp b/src/rt/test/rust_test_runtime.cpp
new file mode 100644
index 00000000..b10be5ed
--- /dev/null
+++ b/src/rt/test/rust_test_runtime.cpp
@@ -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;
+}
diff --git a/src/rt/test/rust_test_runtime.h b/src/rt/test/rust_test_runtime.h
new file mode 100644
index 00000000..8d4f38ec
--- /dev/null
+++ b/src/rt/test/rust_test_runtime.h
@@ -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 */
diff --git a/src/rt/test/rust_test_util.cpp b/src/rt/test/rust_test_util.cpp
index 76bd7990..2e9d764f 100644
--- a/src/rt/test/rust_test_util.cpp
+++ b/src/rt/test/rust_test_util.cpp
@@ -1,7 +1,7 @@
#include "../rust_internal.h"
#define COUNT 1000
-#define LARGE_COUNT 100000
+#define LARGE_COUNT 10000
#define THREADS 10
bool
diff --git a/src/rt/test/rust_test_util.h b/src/rt/test/rust_test_util.h
index fb8490cb..41c35790 100644
--- a/src/rt/test/rust_test_util.h
+++ b/src/rt/test/rust_test_util.h
@@ -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(&region) {
+ rust_synchronized_indexed_list_test() {
// Nop.
}
diff --git a/src/rt/util/indexed_list.h b/src/rt/util/indexed_list.h
index d643a050..df887122 100644
--- a/src/rt/util/indexed_list.h
+++ b/src/rt/util/indexed_list.h
@@ -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];
diff --git a/src/rt/util/synchronized_indexed_list.h b/src/rt/util/synchronized_indexed_list.h
index 6b561171..52fabe05 100644
--- a/src/rt/util/synchronized_indexed_list.h
+++ b/src/rt/util/synchronized_indexed_list.h
@@ -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.
}