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.
This commit is contained in:
parent
ffdb5fc858
commit
f8ff013e3c
16 changed files with 250 additions and 111 deletions
|
@ -267,6 +267,7 @@ RUNTIME_CS := rt/sync/timer.cpp \
|
||||||
rt/circular_buffer.cpp \
|
rt/circular_buffer.cpp \
|
||||||
rt/isaac/randport.cpp \
|
rt/isaac/randport.cpp \
|
||||||
rt/rust_srv.cpp \
|
rt/rust_srv.cpp \
|
||||||
|
rt/rust_kernel.cpp \
|
||||||
rt/memory_region.cpp
|
rt/memory_region.cpp
|
||||||
|
|
||||||
RUNTIME_HDR := rt/globals.h \
|
RUNTIME_HDR := rt/globals.h \
|
||||||
|
@ -283,11 +284,14 @@ RUNTIME_HDR := rt/globals.h \
|
||||||
rt/rust_message.h \
|
rt/rust_message.h \
|
||||||
rt/circular_buffer.h \
|
rt/circular_buffer.h \
|
||||||
rt/util/array_list.h \
|
rt/util/array_list.h \
|
||||||
|
rt/util/indexed_list.h \
|
||||||
|
rt/util/synchronized_indexed_list.h \
|
||||||
rt/util/hash_map.h \
|
rt/util/hash_map.h \
|
||||||
rt/sync/sync.h \
|
rt/sync/sync.h \
|
||||||
rt/sync/timer.h \
|
rt/sync/timer.h \
|
||||||
rt/sync/lock_free_queue.h \
|
rt/sync/lock_free_queue.h \
|
||||||
rt/rust_srv.h \
|
rt/rust_srv.h \
|
||||||
|
rt/rust_kernel.h \
|
||||||
rt/memory_region.h \
|
rt/memory_region.h \
|
||||||
rt/memory.h
|
rt/memory.h
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#include "rust_internal.h"
|
#include "rust_internal.h"
|
||||||
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
command_line_args
|
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_srv srv;
|
||||||
rust_dom dom(&srv, crate, "main");
|
rust_dom dom(&srv, crate, "main");
|
||||||
|
srv.kernel->register_domain(&dom);
|
||||||
command_line_args args(dom, argc, argv);
|
command_line_args args(dom, argc, argv);
|
||||||
|
|
||||||
dom.log(rust_log::DOM, "startup: %d args", args.argc);
|
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));
|
sizeof(main_args));
|
||||||
|
|
||||||
ret = dom.start_main_loop();
|
ret = dom.start_main_loop();
|
||||||
|
srv.kernel->deregister_domain(&dom);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(__WIN32__)
|
#if !defined(__WIN32__)
|
||||||
|
|
|
@ -17,10 +17,6 @@
|
||||||
#define CDECL
|
#define CDECL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "util/array_list.h"
|
|
||||||
|
|
||||||
#include "rust_srv.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Local Variables:
|
* Local Variables:
|
||||||
* fill-column: 78;
|
* fill-column: 78;
|
||||||
|
|
|
@ -4,9 +4,6 @@
|
||||||
|
|
||||||
template class ptr_vec<rust_task>;
|
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,
|
rust_dom::rust_dom(rust_srv *srv, rust_crate const *root_crate,
|
||||||
const char *name) :
|
const char *name) :
|
||||||
interrupt_flag(0),
|
interrupt_flag(0),
|
||||||
|
@ -22,7 +19,8 @@ rust_dom::rust_dom(rust_srv *srv, rust_crate const *root_crate,
|
||||||
caches(this),
|
caches(this),
|
||||||
root_task(NULL),
|
root_task(NULL),
|
||||||
curr_task(NULL),
|
curr_task(NULL),
|
||||||
rval(0)
|
rval(0),
|
||||||
|
_kernel(srv->kernel)
|
||||||
{
|
{
|
||||||
logptr("new dom", (uintptr_t)this);
|
logptr("new dom", (uintptr_t)this);
|
||||||
isaac_init(this, &rctx);
|
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);
|
pthread_attr_setdetachstate(&attr, true);
|
||||||
#endif
|
#endif
|
||||||
root_task = new (this) rust_task(this, NULL, name);
|
root_task = new (this) rust_task(this, NULL, name);
|
||||||
|
|
||||||
if (_live_domains.replace(NULL, this) == false) {
|
|
||||||
_live_domains.append(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -86,8 +80,6 @@ rust_dom::~rust_dom() {
|
||||||
#endif
|
#endif
|
||||||
while (caches.length())
|
while (caches.length())
|
||||||
delete caches.pop();
|
delete caches.pop();
|
||||||
|
|
||||||
_live_domains.replace(this, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -375,7 +367,7 @@ rust_dom::schedule_task() {
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
rust_dom::is_deadlocked() {
|
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.
|
// We cannot tell if we are deadlocked if other domains exists.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -388,20 +380,13 @@ rust_dom::is_deadlocked() {
|
||||||
if (_incoming_message_queue.is_empty() && blocked_tasks.length() > 0) {
|
if (_incoming_message_queue.is_empty() && blocked_tasks.length() > 0) {
|
||||||
// We have no messages to process, no running tasks to schedule
|
// We have no messages to process, no running tasks to schedule
|
||||||
// and some blocked tasks therefore we are likely in a deadlock.
|
// and some blocked tasks therefore we are likely in a deadlock.
|
||||||
log_state();
|
_kernel->log_all_domain_state();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
rust_dom::log_all_state() {
|
|
||||||
for (uint32_t i = 0; i < _live_domains.size(); i++) {
|
|
||||||
_live_domains[i]->log_state();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
rust_dom::log_state() {
|
rust_dom::log_state() {
|
||||||
if (!running_tasks.is_empty()) {
|
if (!running_tasks.is_empty()) {
|
||||||
|
|
|
@ -1,16 +1,6 @@
|
||||||
/*
|
|
||||||
* rust_dom.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef RUST_DOM_H
|
#ifndef RUST_DOM_H
|
||||||
#define 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
|
struct rust_dom
|
||||||
{
|
{
|
||||||
// Fields known to the compiler:
|
// Fields known to the compiler:
|
||||||
|
@ -37,6 +27,9 @@ struct rust_dom
|
||||||
rust_task *curr_task;
|
rust_task *curr_task;
|
||||||
int rval;
|
int rval;
|
||||||
|
|
||||||
|
rust_kernel *_kernel;
|
||||||
|
int32_t list_index;
|
||||||
|
|
||||||
hash_map<rust_task *, rust_proxy<rust_task> *> _task_proxies;
|
hash_map<rust_task *, rust_proxy<rust_task> *> _task_proxies;
|
||||||
hash_map<rust_port *, rust_proxy<rust_port> *> _port_proxies;
|
hash_map<rust_port *, rust_proxy<rust_port> *> _port_proxies;
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,8 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "rust.h"
|
#include "rust.h"
|
||||||
|
|
||||||
#include "rand.h"
|
#include "rand.h"
|
||||||
#include "rust_log.h"
|
|
||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
|
|
||||||
#if defined(__WIN32__)
|
#if defined(__WIN32__)
|
||||||
|
@ -39,9 +36,28 @@ extern "C" {
|
||||||
#error "Platform not supported."
|
#error "Platform not supported."
|
||||||
#endif
|
#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/sync.h"
|
||||||
#include "sync/timer.h"
|
#include "sync/timer.h"
|
||||||
#include "sync/condition_variable.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__
|
#ifndef __i386__
|
||||||
#error "Target CPU not supported."
|
#error "Target CPU not supported."
|
||||||
|
@ -56,29 +72,13 @@ extern "C" {
|
||||||
#define A(dom, e, s, ...) ((e) ? (void)0 : \
|
#define A(dom, e, s, ...) ((e) ? (void)0 : \
|
||||||
(dom)->srv->fatal(#e, __FILE__, __LINE__, s, ## __VA_ARGS__))
|
(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.
|
// This drives our preemption scheme.
|
||||||
|
|
||||||
static size_t const TIME_SLICE_IN_MS = 10;
|
static size_t const TIME_SLICE_IN_MS = 10;
|
||||||
|
|
||||||
// Every reference counted object should derive from this base class.
|
// Every reference counted object should derive from this base class.
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> struct rc_base {
|
||||||
struct
|
|
||||||
rc_base
|
|
||||||
{
|
|
||||||
intptr_t ref_count;
|
intptr_t ref_count;
|
||||||
|
|
||||||
void ref() {
|
void ref() {
|
||||||
|
@ -91,29 +91,25 @@ rc_base
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_base();
|
rc_base();
|
||||||
~rc_base();
|
~rc_base();
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> struct dom_owned {
|
||||||
struct
|
|
||||||
dom_owned
|
|
||||||
{
|
|
||||||
rust_dom *get_dom() const {
|
rust_dom *get_dom() const {
|
||||||
return ((T*)this)->dom;
|
return ((T*)this)->dom;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void *ptr) {
|
void operator delete(void *ptr) {
|
||||||
((T *)ptr)->dom->free(ptr);
|
((T *)ptr)->dom->free(ptr);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> struct task_owned {
|
||||||
struct
|
|
||||||
task_owned
|
|
||||||
{
|
|
||||||
rust_dom *get_dom() const {
|
rust_dom *get_dom() const {
|
||||||
return ((T *)this)->task->dom;
|
return ((T *)this)->task->dom;
|
||||||
}
|
}
|
||||||
|
|
||||||
void operator delete(void *ptr) {
|
void operator delete(void *ptr) {
|
||||||
((T *)ptr)->task->dom->free(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
|
// A cond(ition) is something we can block on. This can be a channel
|
||||||
// (writing), a port (reading) or a task (waiting).
|
// (writing), a port (reading) or a task (waiting).
|
||||||
|
|
||||||
struct
|
struct rust_cond { };
|
||||||
rust_cond
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper class used regularly elsewhere.
|
// Helper class used regularly elsewhere.
|
||||||
|
|
||||||
template <typename T>
|
template <typename T> class ptr_vec : public dom_owned<ptr_vec<T> > {
|
||||||
class
|
|
||||||
ptr_vec : public dom_owned<ptr_vec<T> >
|
|
||||||
{
|
|
||||||
static const size_t INIT_SIZE = 8;
|
static const size_t INIT_SIZE = 8;
|
||||||
|
|
||||||
rust_dom *dom;
|
rust_dom *dom;
|
||||||
size_t alloc;
|
size_t alloc;
|
||||||
size_t fill;
|
size_t fill;
|
||||||
T **data;
|
T **data;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ptr_vec(rust_dom *dom);
|
ptr_vec(rust_dom *dom);
|
||||||
~ptr_vec();
|
~ptr_vec();
|
||||||
|
@ -160,24 +148,16 @@ public:
|
||||||
void swap_delete(T* p);
|
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"
|
#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"
|
#include "memory.h"
|
||||||
|
|
||||||
struct
|
struct rust_timer {
|
||||||
rust_timer
|
|
||||||
{
|
|
||||||
// FIXME: This will probably eventually need replacement
|
// FIXME: This will probably eventually need replacement
|
||||||
// with something more sophisticated and integrated with
|
// with something more sophisticated and integrated with
|
||||||
// an IO event-handling library, when we have such a thing.
|
// an IO event-handling library, when we have such a thing.
|
||||||
|
@ -568,7 +548,6 @@ struct gc_alloc {
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "circular_buffer.h"
|
#include "circular_buffer.h"
|
||||||
#include "rust_proxy.h"
|
|
||||||
#include "rust_task.h"
|
#include "rust_task.h"
|
||||||
#include "rust_chan.h"
|
#include "rust_chan.h"
|
||||||
#include "rust_port.h"
|
#include "rust_port.h"
|
||||||
|
|
43
src/rt/rust_kernel.cpp
Normal file
43
src/rt/rust_kernel.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
21
src/rt/rust_kernel.h
Normal file
21
src/rt/rust_kernel.h
Normal file
|
@ -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 */
|
|
@ -28,6 +28,7 @@ read_type_bit_mask() {
|
||||||
bits |= strstr(env_str, "gc") ? rust_log::GC : 0;
|
bits |= strstr(env_str, "gc") ? rust_log::GC : 0;
|
||||||
bits |= strstr(env_str, "stdlib") ? rust_log::STDLIB : 0;
|
bits |= strstr(env_str, "stdlib") ? rust_log::STDLIB : 0;
|
||||||
bits |= strstr(env_str, "special") ? rust_log::SPECIAL : 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, "all") ? rust_log::ALL : 0;
|
||||||
bits = strstr(env_str, "none") ? 0 : bits;
|
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());
|
uint32_t thread_id = hash((uint32_t) pthread_self());
|
||||||
#endif
|
#endif
|
||||||
char prefix[1024] = "";
|
char prefix[1024] = "";
|
||||||
if (_dom->name) {
|
if (_dom && _dom->name) {
|
||||||
append_string(prefix, "%04" PRIxPTR ":%.10s:",
|
append_string(prefix, "%04" PRIxPTR ":%.10s:",
|
||||||
thread_id, _dom->name);
|
thread_id, _dom->name);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
class rust_dom;
|
class rust_dom;
|
||||||
class rust_task;
|
class rust_task;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class rust_log {
|
class rust_log {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -43,6 +41,7 @@ public:
|
||||||
GC = 0x800,
|
GC = 0x800,
|
||||||
STDLIB = 0x1000,
|
STDLIB = 0x1000,
|
||||||
SPECIAL = 0x2000,
|
SPECIAL = 0x2000,
|
||||||
|
KERN = 0x4000,
|
||||||
ALL = 0xffffffff
|
ALL = 0xffffffff
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
|
|
||||||
rust_srv::rust_srv() :
|
rust_srv::rust_srv() :
|
||||||
local_region(this, false),
|
local_region(this, false),
|
||||||
synchronized_region(this, true) {
|
synchronized_region(this, true),
|
||||||
|
kernel(new rust_kernel(this)) {
|
||||||
// Nop.
|
// Nop.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,8 +74,3 @@ rust_srv::warning(char const *expression,
|
||||||
expression, file, (int)line, buf);
|
expression, file, (int)line, buf);
|
||||||
log(msg);
|
log(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
rust_srv *
|
|
||||||
rust_srv::clone() {
|
|
||||||
return new rust_srv();
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
/*
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef RUST_SRV_H
|
#ifndef RUST_SRV_H
|
||||||
#define RUST_SRV_H
|
#define RUST_SRV_H
|
||||||
|
|
||||||
#include "sync/spin_lock.h"
|
#include "rust_internal.h"
|
||||||
#include "memory_region.h"
|
|
||||||
|
|
||||||
class rust_srv {
|
class rust_srv {
|
||||||
public:
|
public:
|
||||||
memory_region local_region;
|
memory_region local_region;
|
||||||
memory_region synchronized_region;
|
memory_region synchronized_region;
|
||||||
|
rust_kernel *kernel;
|
||||||
virtual void log(char const *msg);
|
virtual void log(char const *msg);
|
||||||
virtual void fatal(char const *expression,
|
virtual void fatal(char const *expression,
|
||||||
char const *file,
|
char const *file,
|
||||||
|
@ -28,7 +24,6 @@ public:
|
||||||
virtual void *realloc(void *, size_t);
|
virtual void *realloc(void *, size_t);
|
||||||
rust_srv();
|
rust_srv();
|
||||||
virtual ~rust_srv();
|
virtual ~rust_srv();
|
||||||
virtual rust_srv *clone();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* RUST_SRV_H */
|
#endif /* RUST_SRV_H */
|
||||||
|
|
|
@ -567,11 +567,9 @@ static void *rust_thread_start(void *ptr)
|
||||||
|
|
||||||
// Start a new rust main loop for this thread.
|
// Start a new rust main loop for this thread.
|
||||||
dom->start_main_loop();
|
dom->start_main_loop();
|
||||||
|
|
||||||
rust_srv *srv = dom->srv;
|
rust_srv *srv = dom->srv;
|
||||||
|
srv->kernel->deregister_domain(dom);
|
||||||
delete dom;
|
delete dom;
|
||||||
delete srv;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -611,10 +609,10 @@ upcall_new_thread(rust_task *task, const char *name) {
|
||||||
LOG_UPCALL_ENTRY(task);
|
LOG_UPCALL_ENTRY(task);
|
||||||
|
|
||||||
rust_dom *old_dom = task->dom;
|
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,
|
old_dom->root_crate,
|
||||||
name);
|
name);
|
||||||
|
old_dom->srv->kernel->register_domain(new_dom);
|
||||||
task->log(rust_log::UPCALL | rust_log::MEM,
|
task->log(rust_log::UPCALL | rust_log::MEM,
|
||||||
"upcall new_thread(%s) = dom 0x%" PRIxPTR " task 0x%" PRIxPTR,
|
"upcall new_thread(%s) = dom 0x%" PRIxPTR " task 0x%" PRIxPTR,
|
||||||
name, new_dom, new_dom->root_task);
|
name, new_dom, new_dom->root_task);
|
||||||
|
|
|
@ -98,6 +98,8 @@ class lock_free_queue {
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
int32_t list_index;
|
||||||
|
|
||||||
lock_free_queue() {
|
lock_free_queue() {
|
||||||
// We can only handle 64bit CAS for counted pointers, so this will
|
// We can only handle 64bit CAS for counted pointers, so this will
|
||||||
// not work with 64bit pointers.
|
// not work with 64bit pointers.
|
||||||
|
|
70
src/rt/util/indexed_list.h
Normal file
70
src/rt/util/indexed_list.h
Normal file
|
@ -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 */
|
56
src/rt/util/synchronized_indexed_list.h
Normal file
56
src/rt/util/synchronized_indexed_list.h
Normal file
|
@ -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 */
|
Loading…
Add table
Add a link
Reference in a new issue