diff options
| author | Michael Bebenita <mbebenita@mozilla.com> | 2010-08-27 18:26:36 -0700 |
|---|---|---|
| committer | Michael Bebenita <mbebenita@mozilla.com> | 2010-09-07 18:41:07 -0700 |
| commit | f8ff013e3cc737b92b5a140dfd0ddcc5ab6773d9 (patch) | |
| tree | 84daaf59d1eb899021e681927e1103cf08b91dd5 /src/rt | |
| parent | ffdb5fc8582c77eef7b3a30859eaa216872525a4 (diff) | |
| download | rust-f8ff013e3cc737b92b5a140dfd0ddcc5ab6773d9.tar.gz rust-f8ff013e3cc737b92b5a140dfd0ddcc5ab6773d9.zip | |
Added a few utility classes, cleaned up the include order of .h files, and started to make the Rust kernel own domain message queues rather than the Rust domains themselves.
Diffstat (limited to 'src/rt')
| -rw-r--r-- | src/rt/rust.cpp | 3 | ||||
| -rw-r--r-- | src/rt/rust.h | 4 | ||||
| -rw-r--r-- | src/rt/rust_dom.cpp | 23 | ||||
| -rw-r--r-- | src/rt/rust_dom.h | 13 | ||||
| -rw-r--r-- | src/rt/rust_internal.h | 91 | ||||
| -rw-r--r-- | src/rt/rust_kernel.cpp | 43 | ||||
| -rw-r--r-- | src/rt/rust_kernel.h | 21 | ||||
| -rw-r--r-- | src/rt/rust_log.cpp | 3 | ||||
| -rw-r--r-- | src/rt/rust_log.h | 3 | ||||
| -rw-r--r-- | src/rt/rust_srv.cpp | 8 | ||||
| -rw-r--r-- | src/rt/rust_srv.h | 9 | ||||
| -rw-r--r-- | src/rt/rust_upcall.cpp | 8 | ||||
| -rw-r--r-- | src/rt/sync/lock_free_queue.h | 2 | ||||
| -rw-r--r-- | src/rt/util/indexed_list.h | 70 | ||||
| -rw-r--r-- | src/rt/util/synchronized_indexed_list.h | 56 |
15 files changed, 246 insertions, 111 deletions
diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp index 905b0c8a359..43818de5514 100644 --- a/src/rt/rust.cpp +++ b/src/rt/rust.cpp @@ -1,6 +1,5 @@ #include "rust_internal.h" - struct command_line_args { @@ -80,6 +79,7 @@ rust_start(uintptr_t main_fn, rust_crate const *crate, int argc, char **argv) { rust_srv srv; rust_dom dom(&srv, crate, "main"); + srv.kernel->register_domain(&dom); command_line_args args(dom, argc, argv); dom.log(rust_log::DOM, "startup: %d args", args.argc); @@ -99,6 +99,7 @@ rust_start(uintptr_t main_fn, rust_crate const *crate, int argc, char **argv) sizeof(main_args)); ret = dom.start_main_loop(); + srv.kernel->deregister_domain(&dom); } #if !defined(__WIN32__) diff --git a/src/rt/rust.h b/src/rt/rust.h index 3c534c9444b..66185727cff 100644 --- a/src/rt/rust.h +++ b/src/rt/rust.h @@ -17,10 +17,6 @@ #define CDECL #endif -#include "util/array_list.h" - -#include "rust_srv.h" - /* * Local Variables: * fill-column: 78; diff --git a/src/rt/rust_dom.cpp b/src/rt/rust_dom.cpp index dc42286da8a..a1207ec738a 100644 --- a/src/rt/rust_dom.cpp +++ b/src/rt/rust_dom.cpp @@ -4,9 +4,6 @@ template class ptr_vec<rust_task>; -// Keeps track of all live domains, for debugging purposes. -array_list<rust_dom*> _live_domains; - rust_dom::rust_dom(rust_srv *srv, rust_crate const *root_crate, const char *name) : interrupt_flag(0), @@ -22,7 +19,8 @@ rust_dom::rust_dom(rust_srv *srv, rust_crate const *root_crate, caches(this), root_task(NULL), curr_task(NULL), - rval(0) + rval(0), + _kernel(srv->kernel) { logptr("new dom", (uintptr_t)this); isaac_init(this, &rctx); @@ -32,10 +30,6 @@ rust_dom::rust_dom(rust_srv *srv, rust_crate const *root_crate, pthread_attr_setdetachstate(&attr, true); #endif root_task = new (this) rust_task(this, NULL, name); - - if (_live_domains.replace(NULL, this) == false) { - _live_domains.append(this); - } } static void @@ -86,8 +80,6 @@ rust_dom::~rust_dom() { #endif while (caches.length()) delete caches.pop(); - - _live_domains.replace(this, NULL); } void @@ -375,7 +367,7 @@ rust_dom::schedule_task() { */ bool rust_dom::is_deadlocked() { - if (_live_domains.size() != 1) { + if (_kernel->domains.length() != 1) { // We cannot tell if we are deadlocked if other domains exists. return false; } @@ -388,7 +380,7 @@ rust_dom::is_deadlocked() { if (_incoming_message_queue.is_empty() && blocked_tasks.length() > 0) { // We have no messages to process, no running tasks to schedule // and some blocked tasks therefore we are likely in a deadlock. - log_state(); + _kernel->log_all_domain_state(); return true; } @@ -396,13 +388,6 @@ rust_dom::is_deadlocked() { } void -rust_dom::log_all_state() { - for (uint32_t i = 0; i < _live_domains.size(); i++) { - _live_domains[i]->log_state(); - } -} - -void rust_dom::log_state() { if (!running_tasks.is_empty()) { log(rust_log::TASK, "running tasks:"); diff --git a/src/rt/rust_dom.h b/src/rt/rust_dom.h index 44f56cc41bb..5c9c29533c4 100644 --- a/src/rt/rust_dom.h +++ b/src/rt/rust_dom.h @@ -1,16 +1,6 @@ -/* - * rust_dom.h - */ - #ifndef RUST_DOM_H #define RUST_DOM_H -#include "sync/lock_free_queue.h" -#include "util/hash_map.h" - -#include "rust_proxy.h" -#include "rust_message.h" - struct rust_dom { // Fields known to the compiler: @@ -37,6 +27,9 @@ struct rust_dom rust_task *curr_task; int rval; + rust_kernel *_kernel; + int32_t list_index; + hash_map<rust_task *, rust_proxy<rust_task> *> _task_proxies; hash_map<rust_port *, rust_proxy<rust_port> *> _port_proxies; diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h index d6618873dff..60d86f6116c 100644 --- a/src/rt/rust_internal.h +++ b/src/rt/rust_internal.h @@ -14,11 +14,8 @@ #include <stdio.h> #include <string.h> - #include "rust.h" - #include "rand.h" -#include "rust_log.h" #include "uthash.h" #if defined(__WIN32__) @@ -39,9 +36,28 @@ extern "C" { #error "Platform not supported." #endif +#include "util/array_list.h" +#include "util/indexed_list.h" +#include "util/synchronized_indexed_list.h" +#include "util/hash_map.h" #include "sync/sync.h" #include "sync/timer.h" #include "sync/condition_variable.h" +#include "sync/lock_free_queue.h" + +class rust_dom; +class rust_log; +class rust_task; +class rust_port; +class rust_chan; +struct rust_token; +class rust_kernel; +class rust_crate; +class rust_crate_cache; + +struct stk_seg; +struct type_desc; +struct frame_glue_fns; #ifndef __i386__ #error "Target CPU not supported." @@ -56,29 +72,13 @@ extern "C" { #define A(dom, e, s, ...) ((e) ? (void)0 : \ (dom)->srv->fatal(#e, __FILE__, __LINE__, s, ## __VA_ARGS__)) -struct rust_task; -struct rust_port; -class rust_chan; -struct rust_token; -struct rust_dom; -class rust_crate; -class rust_crate_cache; -// class lockfree_queue; - -struct stk_seg; -struct type_desc; -struct frame_glue_fns; - // This drives our preemption scheme. static size_t const TIME_SLICE_IN_MS = 10; // Every reference counted object should derive from this base class. -template <typename T> -struct -rc_base -{ +template <typename T> struct rc_base { intptr_t ref_count; void ref() { @@ -91,29 +91,25 @@ rc_base } } - rc_base(); - ~rc_base(); + rc_base(); + ~rc_base(); }; -template <typename T> -struct -dom_owned -{ +template <typename T> struct dom_owned { rust_dom *get_dom() const { return ((T*)this)->dom; } + void operator delete(void *ptr) { ((T *)ptr)->dom->free(ptr); } }; -template <typename T> -struct -task_owned -{ +template <typename T> struct task_owned { rust_dom *get_dom() const { return ((T *)this)->task->dom; } + void operator delete(void *ptr) { ((T *)ptr)->task->dom->free(ptr); } @@ -122,24 +118,16 @@ task_owned // A cond(ition) is something we can block on. This can be a channel // (writing), a port (reading) or a task (waiting). -struct -rust_cond -{ -}; +struct rust_cond { }; // Helper class used regularly elsewhere. -template <typename T> -class -ptr_vec : public dom_owned<ptr_vec<T> > -{ +template <typename T> class ptr_vec : public dom_owned<ptr_vec<T> > { static const size_t INIT_SIZE = 8; - rust_dom *dom; size_t alloc; size_t fill; T **data; - public: ptr_vec(rust_dom *dom); ~ptr_vec(); @@ -160,24 +148,16 @@ public: void swap_delete(T* p); }; +#include "memory_region.h" +#include "rust_srv.h" +#include "rust_log.h" +#include "rust_proxy.h" +#include "rust_message.h" +#include "rust_kernel.h" #include "rust_dom.h" - -template <typename T> inline T -check_null(rust_dom *dom, T value, char const *expr, - char const *file, size_t line) { - if (value == NULL) { - dom->srv->fatal(expr, file, line, "is null"); - } - return value; -} - -#define CHECK_NULL(dom, e) (check_null(dom, e, #e, __FILE__, __LINE__)) - #include "memory.h" -struct -rust_timer -{ +struct rust_timer { // FIXME: This will probably eventually need replacement // with something more sophisticated and integrated with // an IO event-handling library, when we have such a thing. @@ -568,7 +548,6 @@ struct gc_alloc { }; #include "circular_buffer.h" -#include "rust_proxy.h" #include "rust_task.h" #include "rust_chan.h" #include "rust_port.h" diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp new file mode 100644 index 00000000000..b82e46152fa --- /dev/null +++ b/src/rt/rust_kernel.cpp @@ -0,0 +1,43 @@ +#include "rust_internal.h" + +rust_kernel::rust_kernel(rust_srv *srv) : + _region(srv->local_region), + _log(srv, NULL), + domains(srv->local_region), + message_queues(srv->local_region) { + // Nop. +} + +rust_kernel::~rust_kernel() { + // Nop. +} + +void +rust_kernel::register_domain(rust_dom *dom) { + domains.append(dom); +} + +void +rust_kernel::deregister_domain(rust_dom *dom) { + domains.remove(dom); +} + +void +rust_kernel::log_all_domain_state() { + log(rust_log::KERN, "log_all_domain_state: %d domains", domains.length()); + for (uint32_t i = 0; i < domains.length(); i++) { + domains[i]->log_state(); + } +} + +void +rust_kernel::log(uint32_t type_bits, char const *fmt, ...) { + char buf[256]; + if (_log.is_tracing(type_bits)) { + va_list args; + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + _log.trace_ln(NULL, type_bits, buf); + va_end(args); + } +} diff --git a/src/rt/rust_kernel.h b/src/rt/rust_kernel.h new file mode 100644 index 00000000000..478d030c177 --- /dev/null +++ b/src/rt/rust_kernel.h @@ -0,0 +1,21 @@ +#ifndef RUST_KERNEL_H +#define RUST_KERNEL_H + +/** + * A global object shared by all domains. + */ +class rust_kernel { + memory_region &_region; + rust_log _log; +public: + synchronized_indexed_list<rust_dom> domains; + synchronized_indexed_list<lock_free_queue<rust_message*> > message_queues; + rust_kernel(rust_srv *srv); + void register_domain(rust_dom *dom); + void deregister_domain(rust_dom *dom); + void log_all_domain_state(); + void log(uint32_t type_bits, char const *fmt, ...); + virtual ~rust_kernel(); +}; + +#endif /* RUST_KERNEL_H */ diff --git a/src/rt/rust_log.cpp b/src/rt/rust_log.cpp index e72a62faa30..fab5098d85a 100644 --- a/src/rt/rust_log.cpp +++ b/src/rt/rust_log.cpp @@ -28,6 +28,7 @@ read_type_bit_mask() { bits |= strstr(env_str, "gc") ? rust_log::GC : 0; bits |= strstr(env_str, "stdlib") ? rust_log::STDLIB : 0; bits |= strstr(env_str, "special") ? rust_log::SPECIAL : 0; + bits |= strstr(env_str, "kern") ? rust_log::KERN : 0; bits |= strstr(env_str, "all") ? rust_log::ALL : 0; bits = strstr(env_str, "none") ? 0 : bits; } @@ -150,7 +151,7 @@ rust_log::trace_ln(rust_task *task, char *message) { uint32_t thread_id = hash((uint32_t) pthread_self()); #endif char prefix[1024] = ""; - if (_dom->name) { + if (_dom && _dom->name) { append_string(prefix, "%04" PRIxPTR ":%.10s:", thread_id, _dom->name); } else { diff --git a/src/rt/rust_log.h b/src/rt/rust_log.h index 5155cb48bc3..66246eb60e4 100644 --- a/src/rt/rust_log.h +++ b/src/rt/rust_log.h @@ -4,8 +4,6 @@ class rust_dom; class rust_task; - - class rust_log { public: @@ -43,6 +41,7 @@ public: GC = 0x800, STDLIB = 0x1000, SPECIAL = 0x2000, + KERN = 0x4000, ALL = 0xffffffff }; diff --git a/src/rt/rust_srv.cpp b/src/rt/rust_srv.cpp index f2dfef63ab6..d92235623de 100644 --- a/src/rt/rust_srv.cpp +++ b/src/rt/rust_srv.cpp @@ -7,7 +7,8 @@ rust_srv::rust_srv() : local_region(this, false), - synchronized_region(this, true) { + synchronized_region(this, true), + kernel(new rust_kernel(this)) { // Nop. } @@ -73,8 +74,3 @@ rust_srv::warning(char const *expression, expression, file, (int)line, buf); log(msg); } - -rust_srv * -rust_srv::clone() { - return new rust_srv(); -} diff --git a/src/rt/rust_srv.h b/src/rt/rust_srv.h index e617c002576..ab646ae6a8f 100644 --- a/src/rt/rust_srv.h +++ b/src/rt/rust_srv.h @@ -1,17 +1,13 @@ -/* - * - */ - #ifndef RUST_SRV_H #define RUST_SRV_H -#include "sync/spin_lock.h" -#include "memory_region.h" +#include "rust_internal.h" class rust_srv { public: memory_region local_region; memory_region synchronized_region; + rust_kernel *kernel; virtual void log(char const *msg); virtual void fatal(char const *expression, char const *file, @@ -28,7 +24,6 @@ public: virtual void *realloc(void *, size_t); rust_srv(); virtual ~rust_srv(); - virtual rust_srv *clone(); }; #endif /* RUST_SRV_H */ diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 954e7a13ded..0e3961bc24c 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -567,11 +567,9 @@ static void *rust_thread_start(void *ptr) // Start a new rust main loop for this thread. dom->start_main_loop(); - rust_srv *srv = dom->srv; + srv->kernel->deregister_domain(dom); delete dom; - delete srv; - return 0; } @@ -611,10 +609,10 @@ upcall_new_thread(rust_task *task, const char *name) { LOG_UPCALL_ENTRY(task); rust_dom *old_dom = task->dom; - rust_dom *new_dom = new rust_dom(old_dom->srv->clone(), + rust_dom *new_dom = new rust_dom(old_dom->srv, old_dom->root_crate, name); - + old_dom->srv->kernel->register_domain(new_dom); task->log(rust_log::UPCALL | rust_log::MEM, "upcall new_thread(%s) = dom 0x%" PRIxPTR " task 0x%" PRIxPTR, name, new_dom, new_dom->root_task); diff --git a/src/rt/sync/lock_free_queue.h b/src/rt/sync/lock_free_queue.h index ac0c5b046a0..5ebc70f12fe 100644 --- a/src/rt/sync/lock_free_queue.h +++ b/src/rt/sync/lock_free_queue.h @@ -98,6 +98,8 @@ class lock_free_queue { } public: + int32_t list_index; + lock_free_queue() { // We can only handle 64bit CAS for counted pointers, so this will // not work with 64bit pointers. diff --git a/src/rt/util/indexed_list.h b/src/rt/util/indexed_list.h new file mode 100644 index 00000000000..d869d43e3e2 --- /dev/null +++ b/src/rt/util/indexed_list.h @@ -0,0 +1,70 @@ +#ifndef INDEXED_LIST_H +#define INDEXED_LIST_H + +#include <assert.h> +#include "array_list.h" +#include "../memory_region.h" + +class indexed_list_object { +public: + int32_t list_index; +}; + +/** + * An array list of objects that are aware of their position in the list. + * Normally, objects in this list should derive from the base class + * "indexed_list_object" however because of nasty Rust compiler dependencies + * on the layout of runtime objects we cannot always derive from this + * base class, so instead we just enforce the informal protocol that any + * object inserted in this list must define a "int32_t list_index" member. + */ +template<typename T> class indexed_list { + memory_region ®ion; + array_list<T*> list; +public: + indexed_list(memory_region ®ion) : region(region) {} + virtual int32_t append(T *value); + virtual size_t length() { + return list.size(); + } + virtual bool is_empty() { + return list.is_empty(); + } + virtual int32_t remove(T* value); + virtual T * operator[](int32_t index); +}; + +template<typename T> int32_t +indexed_list<T>::append(T *value) { + value->list_index = list.push(value); + return value->list_index; +} + +/** + * Swap delete the last object in the list with the specified object. + */ +template<typename T> int32_t +indexed_list<T>::remove(T *value) { + assert (value->list_index >= 0); + assert (value->list_index < (int32_t)list.size()); + int32_t removeIndex = value->list_index; + T *last = list.pop(); + if (last->list_index == removeIndex) { + last->list_index = -1; + return removeIndex; + } else { + value->list_index = -1; + list[removeIndex] = last; + last->list_index = removeIndex; + return removeIndex; + } +} + +template <typename T> T * +indexed_list<T>::operator[](int32_t index) { + T *value = list[index]; + assert(value->list_index == index); + return value; +} + +#endif /* INDEXED_LIST_H */ diff --git a/src/rt/util/synchronized_indexed_list.h b/src/rt/util/synchronized_indexed_list.h new file mode 100644 index 00000000000..ca02f6efdd2 --- /dev/null +++ b/src/rt/util/synchronized_indexed_list.h @@ -0,0 +1,56 @@ +#ifndef SYNCHRONIZED_INDEXED_LIST_H +#define SYNCHRONIZED_INDEXED_LIST_H + +#include "indexed_list.h" + +template<typename T> class synchronized_indexed_list : + public indexed_list<T> { + spin_lock _lock; +public: + synchronized_indexed_list(memory_region ®ion) : + indexed_list<T>(region) { + // Nop. + } + + int32_t append(T *value) { + int32_t index = 0; + _lock.lock(); + index = indexed_list<T>::append(value); + _lock.unlock(); + return index; + } + + size_t length() { + size_t length = 0; + _lock.lock(); + length = indexed_list<T>::length(); + _lock.unlock(); + return length; + } + + bool is_empty() { + bool empty = false; + _lock.lock(); + empty = indexed_list<T>::is_empty(); + _lock.unlock(); + return empty; + } + + int32_t remove(T* value) { + size_t index = 0; + _lock.lock(); + index = indexed_list<T>::remove(value); + _lock.unlock(); + return index; + } + + T *operator[](size_t index) { + T *value = NULL; + _lock.lock(); + value = indexed_list<T>::operator[](index); + _lock.unlock(); + return value; + } +}; + +#endif /* SYNCHRONIZED_INDEXED_LIST_H */ |
