Skip to content

Commit ef255ee

Browse files
committed
---
yaml --- r: 519 b: refs/heads/master c: 7ff39ea h: refs/heads/master i: 517: bca0d4f 515: 4aa89c7 511: 4630b74 v: v3
1 parent cd86595 commit ef255ee

File tree

3 files changed

+21
-33
lines changed

3 files changed

+21
-33
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 6e9f0f952d758bae2b530c2c9b780f2addf10207
2+
refs/heads/master: 7ff39ea448c60e5ab993bb4a32649e60de13184d

trunk/src/rt/rust_port.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ rust_port::~rust_port() {
2323
while (chans.is_empty() == false) {
2424
rust_chan *chan = chans.peek();
2525
chan->disassociate();
26+
27+
if (chan->ref_count == 0) {
28+
task->log(rust_log::COMM,
29+
"chan: 0x%" PRIxPTR " is dormant, freeing", chan);
30+
delete chan;
31+
}
2632
}
2733

2834
delete remote_channel;
@@ -33,13 +39,6 @@ bool rust_port::receive(void *dptr) {
3339
rust_chan *chan = chans[i];
3440
if (chan->buffer.is_empty() == false) {
3541
chan->buffer.dequeue(dptr);
36-
if (chan->buffer.is_empty() && chan->task->blocked()) {
37-
task->log(rust_log::COMM,
38-
"chan: 0x%" PRIxPTR
39-
" is flushing, wakeup task: 0x%" PRIxPTR,
40-
chan, chan->task);
41-
chan->task->wakeup(this);
42-
}
4342
task->log(rust_log::COMM, "<=== read data ===");
4443
return true;
4544
}

trunk/src/rt/rust_upcall.cpp

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -108,29 +108,7 @@ upcall_new_chan(rust_task *task, rust_port *port) {
108108
extern "C" CDECL void
109109
upcall_flush_chan(rust_task *task, rust_chan *chan) {
110110
LOG_UPCALL_ENTRY(task);
111-
rust_dom *dom = task->dom;
112-
task->log(rust_log::UPCALL | rust_log::COMM,
113-
"flush chan: 0x%" PRIxPTR, chan);
114-
115-
if (chan->buffer.is_empty()) {
116-
return;
117-
}
118-
119-
// We cannot flush if the target port was dropped.
120-
if (chan->is_associated() == false) {
121-
return;
122-
}
123-
124-
A(dom, chan->is_associated(),
125-
"Channel should be associated to a port.");
126-
127-
A(dom, chan->port->is_proxy() == false,
128-
"Channels to remote ports should be flushed automatically.");
129-
130-
// Block on the port until this channel has been completely drained
131-
// by the port.
132-
task->block(chan->port);
133-
task->yield(2);
111+
// Nop.
134112
}
135113

136114
/**
@@ -149,8 +127,19 @@ extern "C" CDECL void upcall_del_chan(rust_task *task, rust_chan *chan) {
149127
"Channel's ref count should be zero.");
150128

151129
if (chan->is_associated()) {
152-
A(task->dom, chan->buffer.is_empty(),
153-
"Channel's buffer should be empty.");
130+
// We're trying to delete a channel that another task may be reading
131+
// from. We have two options:
132+
//
133+
// 1. We can flush the channel by blocking in upcall_flush_chan()
134+
// and resuming only when the channel is flushed. The problem
135+
// here is that we can get ourselves in a deadlock if the parent
136+
// task tries to join us.
137+
//
138+
// 2. We can leave the channel in a "dormnat" state by not freeing
139+
// it and letting the receiver task delete it for us instead.
140+
if (chan->buffer.is_empty() == false) {
141+
return;
142+
}
154143
chan->disassociate();
155144
}
156145
delete chan;

0 commit comments

Comments
 (0)