Added some locking to ports to prevent the case where two threads simultaneously wake up a task blocked on a certain port.
This commit is contained in:
parent
cb00befff0
commit
4d99bf9af2
@ -31,6 +31,7 @@ rust_chan::~rust_chan() {
|
||||
void rust_chan::associate(maybe_proxy<rust_port> *port) {
|
||||
this->port = port;
|
||||
if (port->is_proxy() == false) {
|
||||
scoped_lock sync(port->referent()->lock);
|
||||
LOG(task, task,
|
||||
"associating chan: 0x%" PRIxPTR " with port: 0x%" PRIxPTR,
|
||||
this, port);
|
||||
@ -49,6 +50,7 @@ void rust_chan::disassociate() {
|
||||
A(task->dom, is_associated(), "Channel must be associated with a port.");
|
||||
|
||||
if (port->is_proxy() == false) {
|
||||
scoped_lock sync(port->referent()->lock);
|
||||
LOG(task, task,
|
||||
"disassociating chan: 0x%" PRIxPTR " from port: 0x%" PRIxPTR,
|
||||
this, port->referent());
|
||||
@ -81,6 +83,7 @@ void rust_chan::send(void *sptr) {
|
||||
buffer.dequeue(NULL);
|
||||
} else {
|
||||
rust_port *target_port = port->referent();
|
||||
scoped_lock sync(target_port->lock);
|
||||
if (target_port->task->blocked_on(target_port)) {
|
||||
DLOG(dom, comm, "dequeued in rendezvous_ptr");
|
||||
buffer.dequeue(target_port->task->rendezvous_ptr);
|
||||
|
@ -13,6 +13,8 @@ public:
|
||||
// Data sent to this port from remote tasks is buffered in this channel.
|
||||
rust_chan *remote_channel;
|
||||
|
||||
lock_and_signal lock;
|
||||
|
||||
rust_port(rust_task *task, size_t unit_sz);
|
||||
~rust_port();
|
||||
void log_state();
|
||||
|
@ -170,10 +170,7 @@ rust_task::start(uintptr_t spawnee_fn,
|
||||
ctx.call((void *)task_start_wrapper, a, sp);
|
||||
|
||||
yield_timer.reset(0);
|
||||
{
|
||||
scoped_lock sync(dom->scheduler_lock);
|
||||
transition(&dom->newborn_tasks, &dom->running_tasks);
|
||||
}
|
||||
transition(&dom->newborn_tasks, &dom->running_tasks);
|
||||
}
|
||||
|
||||
void
|
||||
@ -408,6 +405,7 @@ rust_task::free(void *p, bool is_gc)
|
||||
|
||||
void
|
||||
rust_task::transition(rust_task_list *src, rust_task_list *dst) {
|
||||
scoped_lock sync(dom->scheduler_lock);
|
||||
DLOG(dom, task,
|
||||
"task %s " PTR " state change '%s' -> '%s' while in '%s'",
|
||||
name, (uintptr_t)this, src->name, dst->name, state->name);
|
||||
@ -424,10 +422,7 @@ rust_task::block(rust_cond *on, const char* name) {
|
||||
A(dom, cond == NULL, "Cannot block an already blocked task.");
|
||||
A(dom, on != NULL, "Cannot block on a NULL object.");
|
||||
|
||||
{
|
||||
scoped_lock sync(dom->scheduler_lock);
|
||||
transition(&dom->running_tasks, &dom->blocked_tasks);
|
||||
}
|
||||
transition(&dom->running_tasks, &dom->blocked_tasks);
|
||||
cond = on;
|
||||
cond_name = name;
|
||||
}
|
||||
@ -439,10 +434,7 @@ rust_task::wakeup(rust_cond *from) {
|
||||
(uintptr_t) cond, (uintptr_t) from);
|
||||
A(dom, cond == from, "Cannot wake up blocked task on wrong condition.");
|
||||
|
||||
{
|
||||
scoped_lock sync(dom->scheduler_lock);
|
||||
transition(&dom->blocked_tasks, &dom->running_tasks);
|
||||
}
|
||||
transition(&dom->blocked_tasks, &dom->running_tasks);
|
||||
I(dom, cond == from);
|
||||
cond = NULL;
|
||||
cond_name = "none";
|
||||
@ -450,7 +442,6 @@ rust_task::wakeup(rust_cond *from) {
|
||||
|
||||
void
|
||||
rust_task::die() {
|
||||
scoped_lock sync(dom->scheduler_lock);
|
||||
transition(&dom->running_tasks, &dom->dead_tasks);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user