2010-06-23 21:03:09 -07:00
|
|
|
#include "rust_internal.h"
|
|
|
|
#include "rust_chan.h"
|
|
|
|
|
2010-07-28 16:46:13 -07:00
|
|
|
/**
|
|
|
|
* Create a new rust channel and associate it with the specified port.
|
|
|
|
*/
|
2010-09-07 18:39:07 -07:00
|
|
|
rust_chan::rust_chan(rust_task *task,
|
|
|
|
maybe_proxy<rust_port> *port,
|
|
|
|
size_t unit_sz) :
|
|
|
|
task(task),
|
|
|
|
port(port),
|
2011-06-27 19:15:03 -07:00
|
|
|
buffer(task, unit_sz) {
|
2011-06-22 15:44:47 -07:00
|
|
|
++task->ref_count;
|
2010-07-19 14:05:18 -07:00
|
|
|
if (port) {
|
2010-07-28 16:46:13 -07:00
|
|
|
associate(port);
|
2010-07-19 14:05:18 -07:00
|
|
|
}
|
2011-04-19 12:21:57 +02:00
|
|
|
LOG(task, comm, "new rust_chan(task=0x%" PRIxPTR
|
|
|
|
", port=0x%" PRIxPTR ") -> chan=0x%" PRIxPTR,
|
|
|
|
(uintptr_t) task, (uintptr_t) port, (uintptr_t) this);
|
2010-06-23 21:03:09 -07:00
|
|
|
}
|
|
|
|
|
2010-07-19 14:05:18 -07:00
|
|
|
rust_chan::~rust_chan() {
|
2011-04-19 12:21:57 +02:00
|
|
|
LOG(task, comm, "del rust_chan(task=0x%" PRIxPTR ")", (uintptr_t) this);
|
2010-08-09 08:15:34 -07:00
|
|
|
|
|
|
|
A(task->dom, is_associated() == false,
|
|
|
|
"Channel must be disassociated before being freed.");
|
2011-06-22 15:44:47 -07:00
|
|
|
--task->ref_count;
|
2010-06-23 21:03:09 -07:00
|
|
|
}
|
|
|
|
|
2010-07-28 16:46:13 -07:00
|
|
|
/**
|
|
|
|
* Link this channel with the specified port.
|
|
|
|
*/
|
|
|
|
void rust_chan::associate(maybe_proxy<rust_port> *port) {
|
|
|
|
this->port = port;
|
2010-08-09 08:15:34 -07:00
|
|
|
if (port->is_proxy() == false) {
|
2011-04-19 12:21:57 +02:00
|
|
|
LOG(task, task,
|
2010-08-09 08:15:34 -07:00
|
|
|
"associating chan: 0x%" PRIxPTR " with port: 0x%" PRIxPTR,
|
|
|
|
this, port);
|
2011-06-22 15:44:47 -07:00
|
|
|
++this->ref_count;
|
2010-09-07 18:39:07 -07:00
|
|
|
this->port->referent()->chans.push(this);
|
2010-07-28 16:46:13 -07:00
|
|
|
}
|
|
|
|
}
|
2010-06-23 21:03:09 -07:00
|
|
|
|
2010-07-28 16:46:13 -07:00
|
|
|
bool rust_chan::is_associated() {
|
|
|
|
return port != NULL;
|
|
|
|
}
|
2010-06-23 21:03:09 -07:00
|
|
|
|
2010-07-28 16:46:13 -07:00
|
|
|
/**
|
|
|
|
* Unlink this channel from its associated port.
|
|
|
|
*/
|
|
|
|
void rust_chan::disassociate() {
|
|
|
|
A(task->dom, is_associated(), "Channel must be associated with a port.");
|
2010-07-19 14:05:18 -07:00
|
|
|
|
2010-08-09 08:15:34 -07:00
|
|
|
if (port->is_proxy() == false) {
|
2011-04-19 12:21:57 +02:00
|
|
|
LOG(task, task,
|
2010-08-09 08:15:34 -07:00
|
|
|
"disassociating chan: 0x%" PRIxPTR " from port: 0x%" PRIxPTR,
|
2010-09-07 18:39:07 -07:00
|
|
|
this, port->referent());
|
2011-06-22 15:44:47 -07:00
|
|
|
--this->ref_count;
|
2010-09-07 18:39:07 -07:00
|
|
|
port->referent()->chans.swap_delete(this);
|
2010-08-09 08:15:34 -07:00
|
|
|
}
|
|
|
|
|
2010-07-28 16:46:13 -07:00
|
|
|
// Delete reference to the port.
|
|
|
|
port = NULL;
|
2010-07-19 14:05:18 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2010-08-09 08:15:34 -07:00
|
|
|
* Attempt to send data to the associated port.
|
2010-07-19 14:05:18 -07:00
|
|
|
*/
|
2010-08-09 08:15:34 -07:00
|
|
|
void rust_chan::send(void *sptr) {
|
|
|
|
buffer.enqueue(sptr);
|
|
|
|
|
2010-07-19 14:05:18 -07:00
|
|
|
rust_dom *dom = task->dom;
|
2010-07-28 16:46:13 -07:00
|
|
|
if (!is_associated()) {
|
|
|
|
W(dom, is_associated(),
|
|
|
|
"rust_chan::transmit with no associated port.");
|
|
|
|
return;
|
2010-07-19 14:05:18 -07:00
|
|
|
}
|
|
|
|
|
2010-07-28 16:46:13 -07:00
|
|
|
A(dom, !buffer.is_empty(),
|
|
|
|
"rust_chan::transmit with nothing to send.");
|
2010-07-19 14:05:18 -07:00
|
|
|
|
2010-07-28 16:46:13 -07:00
|
|
|
if (port->is_proxy()) {
|
2010-09-07 18:39:07 -07:00
|
|
|
data_message::send(buffer.peek(), buffer.unit_sz, "send data",
|
|
|
|
task->get_handle(), port->as_proxy()->handle());
|
2010-07-28 16:46:13 -07:00
|
|
|
buffer.dequeue(NULL);
|
|
|
|
} else {
|
2010-09-07 18:39:07 -07:00
|
|
|
rust_port *target_port = port->referent();
|
2010-07-28 16:46:13 -07:00
|
|
|
if (target_port->task->blocked_on(target_port)) {
|
2011-04-19 12:21:57 +02:00
|
|
|
DLOG(dom, comm, "dequeued in rendezvous_ptr");
|
2010-07-28 16:46:13 -07:00
|
|
|
buffer.dequeue(target_port->task->rendezvous_ptr);
|
|
|
|
target_port->task->rendezvous_ptr = 0;
|
|
|
|
target_port->task->wakeup(target_port);
|
|
|
|
return;
|
|
|
|
}
|
2010-07-19 14:05:18 -07:00
|
|
|
}
|
|
|
|
|
2010-07-28 16:46:13 -07:00
|
|
|
return;
|
2010-06-23 21:03:09 -07:00
|
|
|
}
|
2010-07-28 00:36:35 -07:00
|
|
|
//
|
|
|
|
// Local Variables:
|
|
|
|
// mode: C++
|
|
|
|
// fill-column: 78;
|
|
|
|
// indent-tabs-mode: nil
|
|
|
|
// c-basic-offset: 4
|
|
|
|
// buffer-file-coding-system: utf-8-unix
|
|
|
|
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
|
|
|
|
// End:
|
|
|
|
//
|