diff --git a/src/rt/memory_region.cpp b/src/rt/memory_region.cpp index 6e651590197..44924218e57 100644 --- a/src/rt/memory_region.cpp +++ b/src/rt/memory_region.cpp @@ -4,7 +4,7 @@ // NB: please do not commit code with this uncommented. It's // hugely expensive and should only be used as a last resort. // -// #define TRACK_ALLOCATIONS +#define TRACK_ALLOCATIONS #define MAGIC 0xbadc0ffe diff --git a/src/rt/rust_chan.cpp b/src/rt/rust_chan.cpp index 9253d7d0361..dc6ea0fefdf 100644 --- a/src/rt/rust_chan.cpp +++ b/src/rt/rust_chan.cpp @@ -60,7 +60,7 @@ void rust_chan::disassociate() { // "disassociating chan: 0x%" PRIxPTR " from port: 0x%" PRIxPTR, // this, port->referent()); --this->ref_count; - --this->task->ref_count; + task->deref(); this->task = NULL; port->referent()->chans.swap_delete(this); } @@ -109,22 +109,10 @@ void rust_chan::send(void *sptr) { return; } -rust_chan *rust_chan::clone(maybe_proxy *target) { +rust_chan *rust_chan::clone(rust_task *target) { size_t unit_sz = buffer.unit_sz; maybe_proxy *port = this->port; - rust_task *target_task = NULL; - if (target->is_proxy() == false) { - port = this->port; - target_task = target->referent(); - } else { - rust_handle *handle = - task->sched->kernel->get_port_handle(port->as_referent()); - maybe_proxy *proxy = new rust_proxy (handle); - DLOG(task->sched, mem, "new proxy: " PTR, proxy); - port = proxy; - target_task = target->as_proxy()->handle()->referent(); - } - return new (target_task->kernel, "cloned chan") + return new (target->kernel, "cloned chan") rust_chan(kernel, port, unit_sz); } diff --git a/src/rt/rust_chan.h b/src/rt/rust_chan.h index 056d70cebe4..68cdd31b3cc 100644 --- a/src/rt/rust_chan.h +++ b/src/rt/rust_chan.h @@ -22,7 +22,7 @@ public: void send(void *sptr); - rust_chan *clone(maybe_proxy *target); + rust_chan *clone(rust_task *target); // Called whenever the channel's ref count drops to zero. void destroy(); diff --git a/src/rt/rust_message.cpp b/src/rt/rust_message.cpp index 59645d6d5bd..f8001a17193 100644 --- a/src/rt/rust_message.cpp +++ b/src/rt/rust_message.cpp @@ -61,8 +61,8 @@ void notify_message::process() { break; case JOIN: { if (task->dead() == false) { - rust_proxy *proxy = new rust_proxy(_source); - task->tasks_waiting_to_join.append(proxy); + // FIXME: this should be dead code. + assert(false); } else { send(WAKEUP, "wakeup", _target, _source); } diff --git a/src/rt/rust_scheduler.cpp b/src/rt/rust_scheduler.cpp index 4f19b0c681b..245ee3d5fce 100644 --- a/src/rt/rust_scheduler.cpp +++ b/src/rt/rust_scheduler.cpp @@ -89,14 +89,14 @@ rust_scheduler::reap_dead_tasks(int id) { rust_task *task = dead_tasks[i]; task->lock.lock(); // Make sure this task isn't still running somewhere else... - if (task->ref_count == 0 && task->can_schedule(id)) { + if (task->can_schedule(id)) { I(this, task->tasks_waiting_to_join.is_empty()); dead_tasks.remove(task); DLOG(this, task, "deleting unreferenced dead task %s @0x%" PRIxPTR, task->name, task); task->lock.unlock(); - delete task; + task->deref(); sync::decrement(kernel->live_tasks); kernel->wakeup_schedulers(); continue; @@ -174,9 +174,8 @@ rust_scheduler::log_state() { if (!dead_tasks.is_empty()) { log(NULL, log_note, "dead tasks:"); for (size_t i = 0; i < dead_tasks.length(); i++) { - log(NULL, log_note, "\t task: %s 0x%" PRIxPTR ", ref_count: %d", - dead_tasks[i]->name, dead_tasks[i], - dead_tasks[i]->ref_count); + log(NULL, log_note, "\t task: %s 0x%" PRIxPTR, + dead_tasks[i]->name, dead_tasks[i]); } } } @@ -225,15 +224,13 @@ rust_scheduler::start_main_loop() { I(this, scheduled_task->running()); DLOG(this, task, - "activating task %s 0x%" PRIxPTR - ", sp=0x%" PRIxPTR - ", ref_count=%d" - ", state: %s", - scheduled_task->name, - (uintptr_t)scheduled_task, - scheduled_task->rust_sp, - scheduled_task->ref_count, - scheduled_task->state->name); + "activating task %s 0x%" PRIxPTR + ", sp=0x%" PRIxPTR + ", state: %s", + scheduled_task->name, + (uintptr_t)scheduled_task, + scheduled_task->rust_sp, + scheduled_task->state->name); interrupt_flag = 0; diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 05efc12e4d4..a144879cc04 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -64,7 +64,7 @@ size_t const callee_save_fp = 0; rust_task::rust_task(rust_scheduler *sched, rust_task_list *state, rust_task *spawner, const char *name) : - maybe_proxy(this), + ref_count(1), stk(NULL), runtime_sp(0), rust_sp(0), @@ -92,10 +92,6 @@ rust_task::rust_task(rust_scheduler *sched, rust_task_list *state, stk = new_stk(this, 0); rust_sp = stk->limit; - - if (spawner == NULL) { - ref_count = 0; - } } rust_task::~rust_task() @@ -131,10 +127,6 @@ void task_start_wrapper(spawn_args *a) LOG(task, task, "task exited with value %d", rval); - - LOG(task, task, "task ref_count: %d", task->ref_count); - A(task->sched, task->ref_count >= 0, - "Task ref_count should not be negative on exit!"); task->die(); task->lock.lock(); task->notify_tasks_waiting_to_join(); @@ -263,17 +255,10 @@ rust_task::notify_tasks_waiting_to_join() { while (tasks_waiting_to_join.is_empty() == false) { LOG(this, task, "notify_tasks_waiting_to_join: %d", tasks_waiting_to_join.size()); - maybe_proxy *waiting_task = 0; + rust_task *waiting_task = 0; tasks_waiting_to_join.pop(&waiting_task); - if (waiting_task->is_proxy()) { - notify_message::send(notify_message::WAKEUP, "wakeup", - get_handle(), waiting_task->as_proxy()->handle()); - delete waiting_task; - } else { - rust_task *task = waiting_task->referent(); - if (task->blocked() == true) { - task->wakeup(this); - } + if (waiting_task->blocked() == true) { + waiting_task->wakeup(this); } } } diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 9b1a3a39582..8b55c0028a9 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -34,10 +34,19 @@ struct gc_alloc { } }; + struct -rust_task : public maybe_proxy, - public kernel_owned +rust_task : public kernel_owned, rust_cond { + // This block could be pulled out into something like a + // RUST_ATOMIC_REFCOUNTED macro. +private: + intptr_t ref_count; +public: + void ref() { sync::increment(ref_count); } + void deref() { if(0 == sync::decrement(ref_count)) { delete this; } } + + // Fields known to the compiler. stk_seg *stk; uintptr_t runtime_sp; // Runtime sp while task running. @@ -69,7 +78,7 @@ rust_task : public maybe_proxy, uintptr_t* rendezvous_ptr; // List of tasks waiting for this task to finish. - array_list *> tasks_waiting_to_join; + array_list tasks_waiting_to_join; rust_handle *handle; diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 103aa49a6e9..794bbc9c244 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -6,12 +6,10 @@ #define LOG_UPCALL_ENTRY(task) \ LOG(task, upcall, \ "> UPCALL %s - task: %s 0x%" PRIxPTR \ - " retpc: x%" PRIxPTR \ - " ref_count: %d", \ + " retpc: x%" PRIxPTR, \ __FUNCTION__, \ (task)->name, (task), \ - __builtin_return_address(0), \ - (task->ref_count)); + __builtin_return_address(0)); #else #define LOG_UPCALL_ENTRY(task) \ LOG(task, upcall, "> UPCALL task: %s @x%" PRIxPTR, \ @@ -114,8 +112,8 @@ upcall_del_port(rust_task *task, rust_port *port) { I(task->sched, !port->ref_count); delete port; - // FIXME: We shouldn't ever directly manipulate the ref count. - --task->ref_count; + // FIXME: this should happen in the port. + task->deref(); } /** @@ -162,7 +160,7 @@ void upcall_del_chan(rust_task *task, rust_chan *chan) { * has its own copy of the channel. */ extern "C" CDECL rust_chan * -upcall_clone_chan(rust_task *task, maybe_proxy *target, +upcall_clone_chan(rust_task *task, rust_task *target, rust_chan *chan) { LOG_UPCALL_ENTRY(task); return chan->clone(target); @@ -247,18 +245,10 @@ upcall_fail(rust_task *task, * Called whenever a task's ref count drops to zero. */ extern "C" CDECL void -upcall_kill(rust_task *task, maybe_proxy *target) { +upcall_kill(rust_task *task, rust_task *target) { LOG_UPCALL_ENTRY(task); - if (target->is_proxy()) { - notify_message:: - send(notify_message::KILL, "kill", task->get_handle(), - target->as_proxy()->handle()); - // The proxy ref_count dropped to zero, delete it here. - delete target->as_proxy(); - } else { - target->referent()->kill(); - } + target->kill(); } /** @@ -267,9 +257,6 @@ upcall_kill(rust_task *task, maybe_proxy *target) { extern "C" CDECL void upcall_exit(rust_task *task) { LOG_UPCALL_ENTRY(task); - LOG(task, task, "task ref_count: %d", task->ref_count); - A(task->sched, task->ref_count >= 0, - "Task ref_count should not be negative on exit!"); task->die(); task->notify_tasks_waiting_to_join(); task->yield(1); @@ -544,6 +531,7 @@ upcall_new_task(rust_task *spawner, rust_vec *name) { scoped_lock with(spawner->sched->lock); rust_task *task = spawner->kernel->create_task(spawner, (const char *)name->data); + task->ref(); return task; } @@ -559,8 +547,7 @@ extern "C" CDECL void upcall_drop_task(rust_task *task, rust_task *target) { LOG_UPCALL_ENTRY(task); if(target) { - //target->deref(); - --target->ref_count; + target->deref(); } }