diff options
| author | Michael Bebenita <[email protected]> | 2010-09-10 01:21:29 -0700 |
|---|---|---|
| committer | Michael Bebenita <[email protected]> | 2010-09-10 14:38:31 -0700 |
| commit | a493350eb5ab38ba8a6563f3eb4a090d257b0d3a (patch) | |
| tree | dc984eaa28a55de9f05db0b961a0e67f80ca35ef /src | |
| parent | Added lock_and_signal::signal_all(), and made the rust_kernel::join() use wai... (diff) | |
| download | rust-a493350eb5ab38ba8a6563f3eb4a090d257b0d3a.tar.xz rust-a493350eb5ab38ba8a6563f3eb4a090d257b0d3a.zip | |
Cleanup, refactoring, and some runtime tests.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 4 | ||||
| -rw-r--r-- | src/rt/rust_dom.cpp | 93 | ||||
| -rw-r--r-- | src/rt/rust_dom.h | 17 | ||||
| -rw-r--r-- | src/rt/rust_internal.h | 7 | ||||
| -rw-r--r-- | src/rt/rust_kernel.cpp | 12 | ||||
| -rw-r--r-- | src/rt/rust_task.cpp | 38 | ||||
| -rw-r--r-- | src/rt/rust_task.h | 9 | ||||
| -rw-r--r-- | src/rt/rust_task_list.cpp | 16 | ||||
| -rw-r--r-- | src/rt/rust_task_list.h | 16 | ||||
| -rw-r--r-- | src/rt/rust_upcall.cpp | 6 | ||||
| -rw-r--r-- | src/rt/sync/sync.cpp | 12 | ||||
| -rw-r--r-- | src/rt/sync/sync.h | 2 | ||||
| -rw-r--r-- | src/rt/sync/timer.cpp | 5 | ||||
| -rw-r--r-- | src/rt/sync/timer.h | 1 | ||||
| -rw-r--r-- | src/rt/test/rust_test_harness.cpp | 13 | ||||
| -rw-r--r-- | src/rt/test/rust_test_harness.h | 3 | ||||
| -rw-r--r-- | src/rt/test/rust_test_runtime.cpp | 77 | ||||
| -rw-r--r-- | src/rt/test/rust_test_runtime.h | 51 | ||||
| -rw-r--r-- | src/rt/test/rust_test_util.cpp | 2 | ||||
| -rw-r--r-- | src/rt/test/rust_test_util.h | 4 | ||||
| -rw-r--r-- | src/rt/util/indexed_list.h | 16 | ||||
| -rw-r--r-- | src/rt/util/synchronized_indexed_list.h | 4 |
22 files changed, 279 insertions, 129 deletions
diff --git a/src/Makefile b/src/Makefile index 3fbd7799..a524739a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -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 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(®ion) { + 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. } |