From 00d1465d13980fc3acf650f182ee0723fbda0e06 Mon Sep 17 00:00:00 2001 From: Michael Bebenita Date: Mon, 19 Jul 2010 14:05:18 -0700 Subject: 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. --- src/rt/rust_upcall.cpp | 600 ++++++++++++++++++++++--------------------------- 1 file changed, 270 insertions(+), 330 deletions(-) (limited to 'src/rt/rust_upcall.cpp') 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 *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 *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 *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 * +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 *proxy = + new (old_dom) rust_proxy(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 * 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 *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; } // -- cgit v1.2.3