aboutsummaryrefslogtreecommitdiff
path: root/src/rt/rust_upcall.cpp
diff options
context:
space:
mode:
authorMichael Bebenita <[email protected]>2010-07-19 14:05:18 -0700
committerMichael Bebenita <[email protected]>2010-07-19 14:05:18 -0700
commit00d1465d13980fc3acf650f182ee0723fbda0e06 (patch)
treea73cf5f0f20c0bee6722b33d975eb930919fefdf /src/rt/rust_upcall.cpp
parentAdd a test for an obvious-seeming (but not actually legal) kind of cast attem... (diff)
downloadrust-00d1465d13980fc3acf650f182ee0723fbda0e06.tar.xz
rust-00d1465d13980fc3acf650f182ee0723fbda0e06.zip
Added a message passing system based on lock free queues for inter-thread communication. Channels now buffer on the sending side, and no longer require blocking when sending. Lots of other refactoring and bug fixes.
Diffstat (limited to 'src/rt/rust_upcall.cpp')
-rw-r--r--src/rt/rust_upcall.cpp600
1 files changed, 270 insertions, 330 deletions
diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp
index 99df91a6..1aaf89fb 100644
--- a/src/rt/rust_upcall.cpp
+++ b/src/rt/rust_upcall.cpp
@@ -1,127 +1,120 @@
-
#include "rust_internal.h"
-
// Upcalls.
#ifdef __GNUC__
#define LOG_UPCALL_ENTRY(task) \
(task)->dom->get_log().reset_indent(0); \
- (task)->dom->log(rust_log::UPCALL, \
- "upcall task: 0x%" PRIxPTR \
- " retpc: 0x%" PRIxPTR, \
- (task), __builtin_return_address(0)); \
+ (task)->log(rust_log::UPCALL, \
+ "> UPCALL %s - task: 0x%" PRIxPTR \
+ " retpc: x%" PRIxPTR, \
+ __FUNCTION__, \
+ (task), __builtin_return_address(0)); \
(task)->dom->get_log().indent();
#else
#define LOG_UPCALL_ENTRY(task) \
(task)->dom->get_log().reset_indent(0); \
- (task)->dom->log(rust_log::UPCALL, \
- "upcall task: 0x%" PRIxPTR (task)); \
+ (task)->log(rust_log::UPCALL, \
+ "> UPCALL task: x%" PRIxPTR (task)); \
(task)->dom->get_log().indent();
#endif
extern "C" CDECL char const *str_buf(rust_task *task, rust_str *s);
-extern "C" void
-upcall_grow_task(rust_task *task, size_t n_frame_bytes)
-{
+inline bool
+requires_message_passing(rust_task *sender, rust_task *receiver) {
+ return sender->dom != receiver->dom;
+}
+
+extern "C" void upcall_grow_task(rust_task *task, size_t n_frame_bytes) {
LOG_UPCALL_ENTRY(task);
task->grow(n_frame_bytes);
}
-extern "C" CDECL void
-upcall_log_int(rust_task *task, int32_t i)
-{
+extern "C" CDECL void upcall_log_int(rust_task *task, int32_t i) {
LOG_UPCALL_ENTRY(task);
- task->dom->log(rust_log::UPCALL|rust_log::ULOG,
- "upcall log_int(0x%" PRIx32 " = %" PRId32 " = '%c')",
- i, i, (char)i);
+ task->log(rust_log::UPCALL | rust_log::ULOG,
+ "upcall log_int(0x%" PRIx32 " = %" PRId32 " = '%c')", i, i,
+ (char) i);
}
-extern "C" CDECL void
-upcall_log_str(rust_task *task, rust_str *str)
-{
+extern "C" CDECL void upcall_log_str(rust_task *task, rust_str *str) {
LOG_UPCALL_ENTRY(task);
const char *c = str_buf(task, str);
- task->dom->log(rust_log::UPCALL|rust_log::ULOG,
- "upcall log_str(\"%s\")",
- c);
+ task->log(rust_log::UPCALL | rust_log::ULOG, "upcall log_str(\"%s\")", c);
}
-extern "C" CDECL void
-upcall_trace_word(rust_task *task, uintptr_t i)
-{
+extern "C" CDECL void upcall_trace_word(rust_task *task, uintptr_t i) {
LOG_UPCALL_ENTRY(task);
- task->dom->log(rust_log::UPCALL|rust_log::TRACE,
- "trace: 0x%" PRIxPTR "",
- i, i, (char)i);
+ task->log(rust_log::UPCALL | rust_log::TRACE, "trace: 0x%" PRIxPTR "", i,
+ i, (char) i);
}
-extern "C" CDECL void
-upcall_trace_str(rust_task *task, char const *c)
-{
+extern "C" CDECL void upcall_trace_str(rust_task *task, char const *c) {
LOG_UPCALL_ENTRY(task);
- task->dom->log(rust_log::UPCALL|rust_log::TRACE,
- "trace: %s",
- c);
+ task->log(rust_log::UPCALL | rust_log::TRACE, "trace: %s", c);
}
extern "C" CDECL rust_port*
-upcall_new_port(rust_task *task, size_t unit_sz)
-{
+upcall_new_port(rust_task *task, size_t unit_sz) {
LOG_UPCALL_ENTRY(task);
rust_dom *dom = task->dom;
- dom->log(rust_log::UPCALL|rust_log::MEM|rust_log::COMM,
- "upcall_new_port(task=0x%" PRIxPTR ", unit_sz=%d)",
- (uintptr_t)task, unit_sz);
+ task->log(rust_log::UPCALL | rust_log::MEM | rust_log::COMM,
+ "upcall_new_port(task=0x%" PRIxPTR ", unit_sz=%d)",
+ (uintptr_t) task, unit_sz);
return new (dom) rust_port(task, unit_sz);
}
-extern "C" CDECL void
-upcall_del_port(rust_task *task, rust_port *port)
-{
+extern "C" CDECL void upcall_del_port(rust_task *task, rust_port *port) {
LOG_UPCALL_ENTRY(task);
- task->dom->log(rust_log::UPCALL|rust_log::MEM|rust_log::COMM,
- "upcall del_port(0x%" PRIxPTR ")", (uintptr_t)port);
- I(task->dom, !port->refcnt);
+ task->log(rust_log::UPCALL | rust_log::MEM | rust_log::COMM,
+ "upcall del_port(0x%" PRIxPTR ")", (uintptr_t) port);
+ I(task->dom, !port->ref_count);
delete port;
}
+/**
+ * Creates a new channel, pointed to a specified port.
+ */
extern "C" CDECL rust_chan*
-upcall_new_chan(rust_task *task, rust_port *port)
-{
+upcall_new_chan(rust_task *task, rust_port *port) {
LOG_UPCALL_ENTRY(task);
rust_dom *dom = task->dom;
- dom->log(rust_log::UPCALL|rust_log::MEM|rust_log::COMM,
- "upcall_new_chan(task=0x%" PRIxPTR ", port=0x%" PRIxPTR ")",
- (uintptr_t)task, port);
+ task->log(rust_log::UPCALL | rust_log::MEM | rust_log::COMM,
+ "upcall_new_chan(task=0x%" PRIxPTR ", port=0x%" PRIxPTR ")",
+ (uintptr_t) task, port);
I(dom, port);
return new (dom) rust_chan(task, port);
}
-extern "C" CDECL void
-upcall_del_chan(rust_task *task, rust_chan *chan)
-{
+/**
+ * Called whenever the channel's ref count drops to zero.
+ */
+extern "C" CDECL void upcall_del_chan(rust_task *task, rust_chan *chan) {
LOG_UPCALL_ENTRY(task);
rust_dom *dom = task->dom;
- dom->log(rust_log::UPCALL|rust_log::MEM|rust_log::COMM,
- "upcall del_chan(0x%" PRIxPTR ")", (uintptr_t)chan);
- I(dom, !chan->refcnt);
+ task->log(rust_log::UPCALL | rust_log::MEM | rust_log::COMM,
+ "upcall del_chan(0x%" PRIxPTR ")", (uintptr_t) chan);
+ I(dom, !chan->ref_count);
delete chan;
}
+/**
+ * Clones a channel and stores it in the spawnee's domain. Each spawned task
+ * has it's own copy of the channel.
+ */
extern "C" CDECL rust_chan *
-upcall_clone_chan(rust_task *task, rust_task *owner, rust_chan *chan)
-{
+upcall_clone_chan(rust_task *task,
+ rust_proxy_delegate<rust_task> *spawnee_proxy,
+ rust_chan *chan) {
LOG_UPCALL_ENTRY(task);
- rust_dom *dom = task->dom;
- dom->log(rust_log::UPCALL|rust_log::MEM|rust_log::COMM,
- "upcall clone_chan(owner 0x%" PRIxPTR ", chan 0x%" PRIxPTR ")",
- (uintptr_t)owner, (uintptr_t)chan);
- return new (owner->dom) rust_chan(owner, chan->port);
+ rust_task *spawnee = spawnee_proxy->delegate();
+ task->log(rust_log::UPCALL | rust_log::MEM | rust_log::COMM,
+ "spawnee: 0x%" PRIxPTR ", chan: 0x%" PRIxPTR,
+ (uintptr_t) spawnee, (uintptr_t) chan);
+ return new (spawnee->dom) rust_chan(spawnee, chan->port);
}
-
/*
* Buffering protocol:
*
@@ -143,74 +136,64 @@ upcall_clone_chan(rust_task *task, rust_task *owner, rust_chan *chan)
* - Set blocked writer to running
*
*/
+//
+//static int
+//attempt_transmission(rust_dom *dom, rust_chan *src, rust_task *dst) {
+// I(dom, src);
+// I(dom, dst);
+//
+// rust_port *port = src->port;
+// if (!port) {
+// dom->log(rust_log::COMM, "src died, transmission incomplete");
+// return 0;
+// }
+//
+// circular_buffer *buf = &src->buffer;
+// if (buf->is_empty()) {
+// dom->log(rust_log::COMM, "buffer empty, transmission incomplete");
+// return 0;
+// }
+//
+// if (!dst->blocked_on(port)) {
+// dom->log(rust_log::COMM,
+// "dst in non-reading state, transmission incomplete");
+// return 0;
+// }
+//
+// uintptr_t *dptr = dst->dptr;
+// dom->log(rust_log::COMM, "receiving %d bytes into dst_task=0x%" PRIxPTR
+// ", dptr=0x%" PRIxPTR, port->unit_sz, dst, dptr);
+// buf->dequeue(dptr);
+//
+// // Wake up the sender if its waiting for the send operation.
+// rust_task *sender = src->task;
+// rust_token *token = &src->token;
+// if (sender->blocked_on(token))
+// sender->wakeup(token);
+//
+// // Wake up the receiver, there is new data.
+// dst->wakeup(port);
+//
+// dom->log(rust_log::COMM, "transmission complete");
+// return 1;
+//}
-static int
-attempt_transmission(rust_dom *dom,
- rust_chan *src,
- rust_task *dst)
-{
- I(dom, src);
- I(dom, dst);
-
- rust_port *port = src->port;
- if (!port) {
- dom->log(rust_log::COMM,
- "src died, transmission incomplete");
- return 0;
- }
-
- circ_buf *buf = &src->buffer;
- if (buf->unread == 0) {
- dom->log(rust_log::COMM,
- "buffer empty, transmission incomplete");
- return 0;
- }
-
- if (!dst->blocked_on(port)) {
- dom->log(rust_log::COMM,
- "dst in non-reading state, transmission incomplete");
- return 0;
- }
-
- uintptr_t *dptr = dst->dptr;
- dom->log(rust_log::COMM,
- "receiving %d bytes into dst_task=0x%" PRIxPTR
- ", dptr=0x%" PRIxPTR,
- port->unit_sz, dst, dptr);
- buf->shift(dptr);
-
- // Wake up the sender if its waiting for the send operation.
- rust_task *sender = src->task;
- rust_token *token = &src->token;
- if (sender->blocked_on(token))
- sender->wakeup(token);
-
- // Wake up the receiver, there is new data.
- dst->wakeup(port);
-
- dom->log(rust_log::COMM, "transmission complete");
- return 1;
-}
-
-extern "C" CDECL void
-upcall_yield(rust_task *task)
-{
+extern "C" CDECL void upcall_yield(rust_task *task) {
LOG_UPCALL_ENTRY(task);
- rust_dom *dom = task->dom;
- dom->log(rust_log::UPCALL|rust_log::COMM, "upcall yield()");
+ task->log(rust_log::UPCALL | rust_log::COMM, "upcall yield()");
task->yield(1);
}
-extern "C" CDECL void
-upcall_join(rust_task *task, rust_task *other)
-{
+extern "C" CDECL void upcall_join(rust_task *task,
+ rust_proxy_delegate<rust_task> *proxy) {
LOG_UPCALL_ENTRY(task);
- rust_dom *dom = task->dom;
- dom->log(rust_log::UPCALL|rust_log::COMM,
- "upcall join(other=0x%" PRIxPTR ")",
- (uintptr_t)other);
+ task->log(rust_log::UPCALL | rust_log::COMM,
+ "join proxy 0x%" PRIxPTR " -> task = 0x%" PRIxPTR,
+ proxy, proxy->delegate());
- // If the other task is already dying, we dont have to wait for it.
+ rust_task *other = proxy->delegate();
+
+ // If the other task is already dying, we don't have to wait for it.
if (!other->dead()) {
other->waiting_tasks.push(&task->alarm);
task->block(other);
@@ -218,106 +201,91 @@ upcall_join(rust_task *task, rust_task *other)
}
}
+/**
+ * Sends an chunk of data along the specified channel.
+ *
+ * sptr: pointer to a chunk of data to send
+ */
extern "C" CDECL void
-upcall_send(rust_task *task, rust_chan *chan, void *sptr)
-{
+upcall_send(rust_task *task, rust_chan *chan, void *sptr) {
LOG_UPCALL_ENTRY(task);
- rust_dom *dom = task->dom;
- dom->log(rust_log::UPCALL|rust_log::COMM,
- "upcall send(chan=0x%" PRIxPTR ", sptr=0x%" PRIxPTR ")",
- (uintptr_t)chan,
- (uintptr_t)sptr);
+ task->log(rust_log::UPCALL | rust_log::COMM,
+ "chan: 0x%" PRIxPTR ", sptr: 0x%" PRIxPTR ", size: %d",
+ (uintptr_t) chan, (uintptr_t) sptr, chan->port->unit_sz);
- I(dom, chan);
- I(dom, sptr);
-
- rust_port *port = chan->port;
- dom->log(rust_log::MEM|rust_log::COMM,
- "send to port", (uintptr_t)port);
- I(dom, port);
-
- rust_token *token = &chan->token;
- dom->log(rust_log::MEM|rust_log::COMM,
- "sending via token 0x%" PRIxPTR,
- (uintptr_t)token);
-
- if (port->task) {
- chan->buffer.push(sptr);
- task->block(token);
- attempt_transmission(dom, chan, port->task);
- if (chan->buffer.unread && !token->pending())
- token->submit();
- } else {
- dom->log(rust_log::COMM|rust_log::ERR,
- "port has no task (possibly throw?)");
- }
-
- if (!task->running())
- task->yield(3);
+ chan->buffer.enqueue(sptr);
+ chan->transmit();
+ task->log(rust_log::COMM, "=== WROTE DATA ===>");
}
extern "C" CDECL void
-upcall_recv(rust_task *task, uintptr_t *dptr, rust_port *port)
-{
+upcall_recv(rust_task *task, uintptr_t *dptr, rust_port *port) {
LOG_UPCALL_ENTRY(task);
- rust_dom *dom = task->dom;
- dom->log(rust_log::UPCALL|rust_log::COMM,
- "upcall recv(dptr=0x%" PRIxPTR ", port=0x%" PRIxPTR ")",
- (uintptr_t)dptr,
- (uintptr_t)port);
+ task->log(rust_log::UPCALL | rust_log::COMM,
+ "port: 0x%" PRIxPTR ", dptr: 0x%" PRIxPTR
+ ", size: 0x%" PRIxPTR ", chan_no: %d",
+ (uintptr_t) port, (uintptr_t) dptr, port->unit_sz,
+ port->chans.length());
+
+ for (uint32_t i = 0; i < port->chans.length(); i++) {
+ rust_chan *chan = port->chans[i];
+ if (chan->buffer.is_empty() == false) {
+ chan->buffer.dequeue(dptr);
+ task->log(rust_log::COMM, "<=== READ DATA ===");
+ return;
+ }
+ }
- I(dom, port);
- I(dom, port->task);
- I(dom, task);
- I(dom, port->task == task);
+ // No data was buffered on any incoming channel, so block this task
+ // on the port. Remember the rendezvous location so that any sender
+ // task can write to it before waking up this task.
+ task->rendezvous_ptr = dptr;
task->block(port);
-
- if (port->writers.length() > 0) {
- I(dom, task->dom);
- size_t i = rand(&dom->rctx);
- i %= port->writers.length();
- rust_token *token = port->writers[i];
- rust_chan *chan = token->chan;
- if (attempt_transmission(dom, chan, task))
- token->withdraw();
- } else {
- dom->log(rust_log::COMM,
- "no writers sending to port", (uintptr_t)port);
- }
-
- if (!task->running()) {
- task->dptr = dptr;
- task->yield(3);
- }
+ task->yield(3);
}
-extern "C" CDECL void
-upcall_fail(rust_task *task, char const *expr, char const *file, size_t line)
-{
+extern "C" CDECL void upcall_fail(rust_task *task, char const *expr,
+ char const *file, size_t line) {
LOG_UPCALL_ENTRY(task);
- task->dom->log(rust_log::UPCALL|rust_log::ERR,
- "upcall fail '%s', %s:%" PRIdPTR,
- expr, file, line);
+ task->log(rust_log::UPCALL | rust_log::ERR,
+ "upcall fail '%s', %s:%" PRIdPTR, expr, file, line);
task->fail(4);
}
+/**
+ * Called whenever a task's ref count drops to zero.
+ */
extern "C" CDECL void
-upcall_kill(rust_task *task, rust_task *target)
-{
+upcall_kill(rust_task *task, rust_proxy_delegate<rust_task> *target_proxy) {
LOG_UPCALL_ENTRY(task);
- task->dom->log(rust_log::UPCALL|rust_log::TASK,
- "upcall kill target=0x%" PRIxPTR, target);
- target->kill();
+ rust_task *target_task = target_proxy->delegate();
+ if (target_proxy != target_task) {
+ task->dom->free(target_proxy);
+ }
+ task->log(rust_log::UPCALL | rust_log::TASK,
+ "kill task 0x%" PRIxPTR ", ref count %d",
+ target_task,
+ target_task->ref_count);
+
+ if (requires_message_passing(task, target_task)) {
+ rust_dom *target_domain = target_task->dom;
+ target_domain->send_message(
+ new (target_domain)
+ kill_task_message(target_domain, target_task));
+ } else {
+ target_task->kill();
+ }
}
+/**
+ * Called by the exit glue when the task terminates.
+ */
extern "C" CDECL void
-upcall_exit(rust_task *task)
-{
+upcall_exit(rust_task *task) {
LOG_UPCALL_ENTRY(task);
-
- rust_dom *dom = task->dom;
- dom->log(rust_log::UPCALL|rust_log::TASK, "upcall exit");
+ task->log(rust_log::UPCALL | rust_log::TASK,
+ "task ref_count: %d", task->ref_count);
task->die();
task->notify_waiting_tasks();
task->yield(1);
@@ -341,11 +309,13 @@ upcall_malloc(rust_task *task, size_t nbytes, type_desc *td)
return (uintptr_t) p;
}
+/**
+ * Called whenever an object's ref count drops to zero.
+ */
extern "C" CDECL void
upcall_free(rust_task *task, void* ptr, uintptr_t is_gc)
{
LOG_UPCALL_ENTRY(task);
-
rust_dom *dom = task->dom;
dom->log(rust_log::UPCALL|rust_log::MEM,
"upcall free(0x%" PRIxPTR ")",
@@ -371,22 +341,19 @@ upcall_mark(rust_task *task, void* ptr)
}
extern "C" CDECL rust_str *
-upcall_new_str(rust_task *task, char const *s, size_t fill)
-{
+upcall_new_str(rust_task *task, char const *s, size_t fill) {
LOG_UPCALL_ENTRY(task);
rust_dom *dom = task->dom;
- dom->log(rust_log::UPCALL|rust_log::MEM,
- "upcall new_str('%s', %" PRIdPTR ")", s, fill);
size_t alloc = next_power_of_two(sizeof(rust_str) + fill);
void *mem = dom->malloc(alloc);
if (!mem) {
task->fail(3);
return NULL;
}
- rust_str *st = new (mem) rust_str(dom, alloc, fill, (uint8_t const *)s);
- dom->log(rust_log::UPCALL|rust_log::MEM,
- "upcall new_str('%s', %" PRIdPTR ") = 0x%" PRIxPTR,
- s, fill, st);
+ rust_str *st = new (mem) rust_str(dom, alloc, fill, (uint8_t const *) s);
+ task->log(rust_log::UPCALL | rust_log::MEM,
+ "upcall new_str('%s', %" PRIdPTR ") = 0x%" PRIxPTR,
+ s, fill, st);
return st;
}
@@ -405,34 +372,32 @@ upcall_new_vec(rust_task *task, size_t fill, type_desc *td)
return NULL;
}
rust_vec *v = new (mem) rust_vec(dom, alloc, 0, NULL);
- dom->log(rust_log::UPCALL|rust_log::MEM,
- "upcall new_vec(%" PRIdPTR ") = 0x%" PRIxPTR,
- fill, v);
+ task->log(rust_log::UPCALL | rust_log::MEM,
+ "upcall new_vec(%" PRIdPTR ") = 0x%" PRIxPTR, fill, v);
return v;
}
-
extern "C" CDECL rust_str *
upcall_vec_grow(rust_task *task, rust_vec *v, size_t n_bytes, uintptr_t is_gc)
{
LOG_UPCALL_ENTRY(task);
rust_dom *dom = task->dom;
- dom->log(rust_log::UPCALL|rust_log::MEM,
+ task->log(rust_log::UPCALL|rust_log::MEM,
"upcall vec_grow(%" PRIxPTR ", %" PRIdPTR
"), alloc=%" PRIdPTR ", fill=%" PRIdPTR,
v, n_bytes, v->alloc, v->fill);
size_t alloc = next_power_of_two(sizeof(rust_vec) + v->fill + n_bytes);
- if (v->refcnt == 1) {
+ if (v->ref_count == 1) {
// Fastest path: already large enough.
if (v->alloc >= alloc) {
- dom->log(rust_log::UPCALL|rust_log::MEM, "no-growth path");
+ task->log(rust_log::UPCALL | rust_log::MEM, "no-growth path");
return v;
}
// Second-fastest path: can at least realloc.
- dom->log(rust_log::UPCALL|rust_log::MEM, "realloc path");
- v = (rust_vec*)dom->realloc(v, alloc);
+ task->log(rust_log::UPCALL | rust_log::MEM, "realloc path");
+ v = (rust_vec*) dom->realloc(v, alloc);
if (!v) {
task->fail(4);
return NULL;
@@ -441,7 +406,7 @@ upcall_vec_grow(rust_task *task, rust_vec *v, size_t n_bytes, uintptr_t is_gc)
} else {
// Slowest path: make a new vec.
- dom->log(rust_log::UPCALL|rust_log::MEM, "new vec path");
+ task->log(rust_log::UPCALL | rust_log::MEM, "new vec path");
void *mem = dom->malloc(alloc);
if (!mem) {
task->fail(4);
@@ -454,121 +419,100 @@ upcall_vec_grow(rust_task *task, rust_vec *v, size_t n_bytes, uintptr_t is_gc)
return v;
}
-
static rust_crate_cache::c_sym *
-fetch_c_sym(rust_task *task,
- rust_crate const *curr_crate,
- size_t lib_num,
- size_t c_sym_num,
- char const *library,
- char const *symbol)
-{
+fetch_c_sym(rust_task *task, rust_crate const *curr_crate, size_t lib_num,
+ size_t c_sym_num, char const *library, char const *symbol) {
rust_crate_cache *cache = task->get_crate_cache(curr_crate);
rust_crate_cache::lib *l = cache->get_lib(lib_num, library);
return cache->get_c_sym(c_sym_num, l, symbol);
}
-extern "C" CDECL uintptr_t
-upcall_require_rust_sym(rust_task *task,
- rust_crate const *curr_crate,
- size_t lib_num, // # of lib
- size_t c_sym_num, // # of C sym "rust_crate" in lib
- size_t rust_sym_num, // # of rust sym
- char const *library,
- char const **path)
-{
+extern "C" CDECL uintptr_t upcall_require_rust_sym(rust_task *task,
+ rust_crate const *curr_crate, size_t lib_num, // # of lib
+ size_t c_sym_num, // # of C sym "rust_crate" in lib
+ size_t rust_sym_num, // # of rust sym
+ char const *library, char const **path) {
LOG_UPCALL_ENTRY(task);
rust_dom *dom = task->dom;
- dom->log(rust_log::UPCALL|rust_log::CACHE,
- "upcall require rust sym: lib #%" PRIdPTR
- " = %s, c_sym #%" PRIdPTR
- ", rust_sym #%" PRIdPTR
- ", curr_crate = 0x%" PRIxPTR,
- lib_num, library, c_sym_num, rust_sym_num,
- curr_crate);
+ task->log(rust_log::UPCALL | rust_log::CACHE,
+ "upcall require rust sym: lib #%" PRIdPTR
+ " = %s, c_sym #%" PRIdPTR
+ ", rust_sym #%" PRIdPTR
+ ", curr_crate = 0x%" PRIxPTR, lib_num, library, c_sym_num,
+ rust_sym_num, curr_crate);
for (char const **c = crate_rel(curr_crate, path); *c; ++c) {
- dom->log(rust_log::UPCALL, " + %s", crate_rel(curr_crate, *c));
+ task->log(rust_log::UPCALL, " + %s", crate_rel(curr_crate, *c));
}
- dom->log(rust_log::UPCALL|rust_log::CACHE,
- "require C symbol 'rust_crate' from lib #%" PRIdPTR,lib_num);
+ task->log(rust_log::UPCALL | rust_log::CACHE,
+ "require C symbol 'rust_crate' from lib #%" PRIdPTR, lib_num);
rust_crate_cache::c_sym *c =
- fetch_c_sym(task, curr_crate, lib_num, c_sym_num,
- library, "rust_crate");
+ fetch_c_sym(task, curr_crate, lib_num, c_sym_num, library,
+ "rust_crate");
- dom->log(rust_log::UPCALL|rust_log::CACHE,
- "require rust symbol inside crate");
- rust_crate_cache::rust_sym *s =
- task->cache->get_rust_sym(rust_sym_num, dom, curr_crate, c, path);
+ task->log(rust_log::UPCALL | rust_log::CACHE,
+ "require rust symbol inside crate");
+ rust_crate_cache::rust_sym *s = task->cache->get_rust_sym(rust_sym_num,
+ dom,
+ curr_crate, c,
+ path);
uintptr_t addr = s->get_val();
if (addr) {
- dom->log(rust_log::UPCALL|rust_log::CACHE,
- "found-or-cached addr: 0x%" PRIxPTR, addr);
+ task->log(rust_log::UPCALL | rust_log::CACHE,
+ "found-or-cached addr: 0x%" PRIxPTR, addr);
} else {
- dom->log(rust_log::UPCALL|rust_log::CACHE,
- "failed to resolve symbol");
+ task->log(rust_log::UPCALL | rust_log::CACHE,
+ "failed to resolve symbol");
task->fail(7);
}
return addr;
}
-extern "C" CDECL uintptr_t
-upcall_require_c_sym(rust_task *task,
- rust_crate const *curr_crate,
- size_t lib_num, // # of lib
- size_t c_sym_num, // # of C sym
- char const *library,
- char const *symbol)
-{
+extern "C" CDECL uintptr_t upcall_require_c_sym(rust_task *task,
+ rust_crate const *curr_crate, size_t lib_num, // # of lib
+ size_t c_sym_num, // # of C sym
+ char const *library, char const *symbol) {
LOG_UPCALL_ENTRY(task);
- rust_dom *dom = task->dom;
- dom->log(rust_log::UPCALL|rust_log::CACHE,
- "upcall require c sym: lib #%" PRIdPTR
- " = %s, c_sym #%" PRIdPTR
- " = %s"
- ", curr_crate = 0x%" PRIxPTR,
- lib_num, library, c_sym_num, symbol, curr_crate);
+ task->log(rust_log::UPCALL | rust_log::CACHE,
+ "upcall require c sym: lib #%" PRIdPTR
+ " = %s, c_sym #%" PRIdPTR
+ " = %s"
+ ", curr_crate = 0x%" PRIxPTR, lib_num, library, c_sym_num,
+ symbol, curr_crate);
- rust_crate_cache::c_sym *c =
- fetch_c_sym(task, curr_crate, lib_num, c_sym_num, library, symbol);
+ rust_crate_cache::c_sym *c = fetch_c_sym(task, curr_crate, lib_num,
+ c_sym_num, library, symbol);
uintptr_t addr = c->get_val();
if (addr) {
- dom->log(rust_log::UPCALL|rust_log::CACHE,
- "found-or-cached addr: 0x%" PRIxPTR, addr);
+ task->log(rust_log::UPCALL | rust_log::CACHE,
+ "found-or-cached addr: 0x%" PRIxPTR, addr);
} else {
- dom->log(rust_log::UPCALL|rust_log::CACHE,
- "failed to resolve symbol");
+ task->log(rust_log::UPCALL | rust_log::CACHE,
+ "failed to resolve symbol");
task->fail(6);
}
return addr;
}
extern "C" CDECL type_desc *
-upcall_get_type_desc(rust_task *task,
- rust_crate const *curr_crate,
- size_t size,
- size_t align,
- size_t n_descs,
- type_desc const **descs)
-{
+upcall_get_type_desc(rust_task *task, rust_crate const *curr_crate,
+ size_t size, size_t align, size_t n_descs, type_desc const **descs) {
LOG_UPCALL_ENTRY(task);
- rust_dom *dom = task->dom;
- dom->log(rust_log::UPCALL|rust_log::CACHE,
- "upcall get_type_desc with size=%" PRIdPTR
- ", align=%" PRIdPTR ", %" PRIdPTR " descs",
- size, align, n_descs);
+ task->log(rust_log::UPCALL | rust_log::CACHE,
+ "upcall get_type_desc with size=%" PRIdPTR
+ ", align=%" PRIdPTR ", %" PRIdPTR " descs", size, align,
+ n_descs);
rust_crate_cache *cache = task->get_crate_cache(curr_crate);
type_desc *td = cache->get_type_desc(size, align, n_descs, descs);
- dom->log(rust_log::UPCALL|rust_log::CACHE,
- "returning tydesc 0x%" PRIxPTR, td);
+ task->log(rust_log::UPCALL | rust_log::CACHE,
+ "returning tydesc 0x%" PRIxPTR, td);
return td;
}
-
#if defined(__WIN32__)
static DWORD WINAPI rust_thread_start(void *ptr)
#elif defined(__GNUC__)
@@ -578,10 +522,10 @@ static void *rust_thread_start(void *ptr)
#endif
{
// We were handed the domain we are supposed to run.
- rust_dom *dom = (rust_dom *)ptr;
+ rust_dom *dom = (rust_dom *) ptr;
// Start a new rust main loop for this thread.
- rust_main_loop(dom);
+ dom->start_main_loop();
rust_srv *srv = dom->srv;
delete dom;
@@ -591,81 +535,77 @@ static void *rust_thread_start(void *ptr)
}
extern "C" CDECL rust_task *
-upcall_new_task(rust_task *spawner)
-{
+upcall_new_task(rust_task *spawner) {
LOG_UPCALL_ENTRY(spawner);
rust_dom *dom = spawner->dom;
rust_task *task = new (dom) rust_task(dom, spawner);
- dom->log(rust_log::UPCALL|rust_log::MEM|rust_log::TASK,
+ dom->log(rust_log::UPCALL | rust_log::MEM | rust_log::TASK,
"upcall new_task(spawner 0x%" PRIxPTR ") = 0x%" PRIxPTR,
spawner, task);
return task;
}
extern "C" CDECL rust_task *
-upcall_start_task(rust_task *spawner,
- rust_task *task,
- uintptr_t exit_task_glue,
- uintptr_t spawnee_fn,
- size_t callsz)
-{
+upcall_start_task(rust_task *spawner, rust_task *task,
+ uintptr_t exit_task_glue, uintptr_t spawnee_fn, size_t callsz) {
LOG_UPCALL_ENTRY(spawner);
rust_dom *dom = spawner->dom;
- dom->log(rust_log::UPCALL|rust_log::MEM|rust_log::TASK,
+ dom->log(rust_log::UPCALL | rust_log::MEM | rust_log::TASK,
"upcall start_task(task 0x%" PRIxPTR
" exit_task_glue 0x%" PRIxPTR
", spawnee 0x%" PRIxPTR
- ", callsz %" PRIdPTR ")",
- task, exit_task_glue, spawnee_fn, callsz);
+ ", callsz %" PRIdPTR ")", task, exit_task_glue, spawnee_fn,
+ callsz);
task->start(exit_task_glue, spawnee_fn, spawner->rust_sp, callsz);
return task;
}
-extern "C" CDECL rust_task *
-upcall_new_thread(rust_task *task)
-{
+extern "C" CDECL rust_proxy_delegate<rust_task> *
+upcall_new_thread(rust_task *task) {
LOG_UPCALL_ENTRY(task);
rust_dom *old_dom = task->dom;
rust_dom *new_dom = new rust_dom(old_dom->srv->clone(),
old_dom->root_crate);
- new_dom->log(rust_log::UPCALL|rust_log::MEM,
- "upcall new_thread() = 0x%" PRIxPTR,
- new_dom->root_task);
- return new_dom->root_task;
+
+ task->log(rust_log::UPCALL | rust_log::MEM,
+ "upcall new_thread() = dom 0x%" PRIxPTR " task 0x%" PRIxPTR,
+ new_dom, new_dom->root_task);
+ rust_proxy<rust_task> *proxy =
+ new (old_dom) rust_proxy<rust_task>(old_dom, new_dom->root_task);
+ task->log(rust_log::UPCALL | rust_log::MEM,
+ "new proxy = 0x%" PRIxPTR " -> task = 0x%" PRIxPTR,
+ proxy, proxy->delegate());
+ return proxy;
}
-extern "C" CDECL rust_task *
+extern "C" CDECL rust_proxy_delegate<rust_task> *
upcall_start_thread(rust_task *spawner,
- rust_task *root_task,
- uintptr_t exit_task_glue,
- uintptr_t spawnee_fn,
- size_t callsz)
-{
+ rust_proxy_delegate<rust_task> *root_task_proxy,
+ uintptr_t exit_task_glue, uintptr_t spawnee_fn, size_t callsz) {
LOG_UPCALL_ENTRY(spawner);
rust_dom *dom = spawner->dom;
- dom->log(rust_log::UPCALL|rust_log::MEM|rust_log::TASK,
+ rust_task *root_task = root_task_proxy->delegate();
+ dom->log(rust_log::UPCALL | rust_log::MEM | rust_log::TASK,
"upcall start_thread(exit_task_glue 0x%" PRIxPTR
", spawnee 0x%" PRIxPTR
- ", callsz %" PRIdPTR ")",
- exit_task_glue, spawnee_fn, callsz);
+ ", callsz %" PRIdPTR ")", exit_task_glue, spawnee_fn, callsz);
root_task->start(exit_task_glue, spawnee_fn, spawner->rust_sp, callsz);
#if defined(__WIN32__)
HANDLE thread;
thread = CreateThread(NULL, 0, rust_thread_start, root_task->dom,
- 0, NULL);
+ 0, NULL);
dom->win32_require("CreateThread", thread != NULL);
#else
pthread_t thread;
pthread_create(&thread, &dom->attr, rust_thread_start,
- (void *)root_task->dom);
+ (void *) root_task->dom);
#endif
-
- return 0;
+ return root_task_proxy;
}
//