aboutsummaryrefslogtreecommitdiff
path: root/src/rt
diff options
context:
space:
mode:
Diffstat (limited to 'src/rt')
-rw-r--r--src/rt/rust.cpp3
-rw-r--r--src/rt/rust.h4
-rw-r--r--src/rt/rust_dom.cpp23
-rw-r--r--src/rt/rust_dom.h13
-rw-r--r--src/rt/rust_internal.h91
-rw-r--r--src/rt/rust_kernel.cpp43
-rw-r--r--src/rt/rust_kernel.h21
-rw-r--r--src/rt/rust_log.cpp3
-rw-r--r--src/rt/rust_log.h3
-rw-r--r--src/rt/rust_srv.cpp8
-rw-r--r--src/rt/rust_srv.h9
-rw-r--r--src/rt/rust_upcall.cpp8
-rw-r--r--src/rt/sync/lock_free_queue.h2
-rw-r--r--src/rt/util/indexed_list.h70
-rw-r--r--src/rt/util/synchronized_indexed_list.h56
15 files changed, 246 insertions, 111 deletions
diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp
index 905b0c8a..43818de5 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 3c534c94..66185727 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 dc42286d..a1207ec7 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 44f56cc4..5c9c2953 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 d6618873..60d86f61 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 00000000..b82e4615
--- /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 00000000..478d030c
--- /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 e72a62fa..fab5098d 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 5155cb48..66246eb6 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 f2dfef63..d9223562 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 e617c002..ab646ae6 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 954e7a13..0e3961bc 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 ac0c5b04..5ebc70f1 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 00000000..d869d43e
--- /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 &region;
+ array_list<T*> list;
+public:
+ indexed_list(memory_region &region) : 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 00000000..ca02f6ef
--- /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 &region) :
+ 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 */