rt: Make rust_port_detach less contentious
It still utterly dominates some benchmarks with busy waiting, but at least it doesn't create lock contention while doing so.
This commit is contained in:
parent
0a5603cb58
commit
4c4a2320eb
7 changed files with 23 additions and 20 deletions
|
@ -492,7 +492,7 @@ extern "C" CDECL void
|
||||||
del_port(rust_port *port) {
|
del_port(rust_port *port) {
|
||||||
rust_task *task = rust_task_thread::get_task();
|
rust_task *task = rust_task_thread::get_task();
|
||||||
LOG(task, comm, "del_port(0x%" PRIxPTR ")", (uintptr_t) port);
|
LOG(task, comm, "del_port(0x%" PRIxPTR ")", (uintptr_t) port);
|
||||||
A(task->thread, port->ref_count == 1, "Expected port ref_count == 1");
|
A(task->thread, port->get_ref_count() == 1, "Expected port ref_count == 1");
|
||||||
port->deref();
|
port->deref();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -522,7 +522,6 @@ chan_id_send(type_desc *t, rust_task_id target_task_id,
|
||||||
rust_port *port = target_task->get_port_by_id(target_port_id);
|
rust_port *port = target_task->get_port_by_id(target_port_id);
|
||||||
if(port) {
|
if(port) {
|
||||||
port->send(sptr);
|
port->send(sptr);
|
||||||
scoped_lock with(target_task->port_lock);
|
|
||||||
port->deref();
|
port->deref();
|
||||||
sent = true;
|
sent = true;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -104,15 +104,20 @@ static size_t const BUF_BYTES = 2048;
|
||||||
void ref() { ++ref_count; } \
|
void ref() { ++ref_count; } \
|
||||||
void deref() { if (--ref_count == 0) { dtor; } }
|
void deref() { if (--ref_count == 0) { dtor; } }
|
||||||
|
|
||||||
#define RUST_ATOMIC_REFCOUNT() \
|
#define RUST_ATOMIC_REFCOUNT() \
|
||||||
private: \
|
private: \
|
||||||
intptr_t ref_count; \
|
intptr_t ref_count; \
|
||||||
public: \
|
public: \
|
||||||
void ref() { \
|
void ref() { \
|
||||||
intptr_t old = sync::increment(ref_count); \
|
intptr_t old = sync::increment(ref_count); \
|
||||||
assert(old > 0); \
|
assert(old > 0); \
|
||||||
} \
|
} \
|
||||||
void deref() { if(0 == sync::decrement(ref_count)) { delete_this(); } }
|
void deref() { if(0 == sync::decrement(ref_count)) { delete_this(); } } \
|
||||||
|
intptr_t get_ref_count() { \
|
||||||
|
sync::increment(ref_count); \
|
||||||
|
intptr_t current = sync::decrement(ref_count); \
|
||||||
|
return current; \
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T> struct task_owned {
|
template <typename T> struct task_owned {
|
||||||
inline void *operator new(size_t size, rust_task *task, const char *tag);
|
inline void *operator new(size_t size, rust_task *task, const char *tag);
|
||||||
|
|
|
@ -25,8 +25,7 @@ void rust_port::detach() {
|
||||||
// FIXME: Busy waiting until we're the only ref
|
// FIXME: Busy waiting until we're the only ref
|
||||||
bool done = false;
|
bool done = false;
|
||||||
while (!done) {
|
while (!done) {
|
||||||
scoped_lock with(task->port_lock);
|
done = get_ref_count() == 1;
|
||||||
done = ref_count == 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
class rust_port : public kernel_owned<rust_port>, public rust_cond {
|
class rust_port : public kernel_owned<rust_port>, public rust_cond {
|
||||||
public:
|
public:
|
||||||
RUST_REFCOUNTED(rust_port)
|
RUST_ATOMIC_REFCOUNT();
|
||||||
|
|
||||||
rust_port_id id;
|
rust_port_id id;
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@ public:
|
||||||
|
|
||||||
rust_port(rust_task *task, size_t unit_sz);
|
rust_port(rust_task *task, size_t unit_sz);
|
||||||
~rust_port();
|
~rust_port();
|
||||||
|
void delete_this() { delete this; }
|
||||||
|
|
||||||
void log_state();
|
void log_state();
|
||||||
void send(void *sptr);
|
void send(void *sptr);
|
||||||
void receive(void *dptr, uintptr_t *yield);
|
void receive(void *dptr, uintptr_t *yield);
|
||||||
|
|
|
@ -69,7 +69,6 @@ void
|
||||||
rust_port_selector::msg_sent_on(rust_port *port) {
|
rust_port_selector::msg_sent_on(rust_port *port) {
|
||||||
rust_task *task = port->task;
|
rust_task *task = port->task;
|
||||||
|
|
||||||
I(task->thread, !task->port_lock.lock_held_by_current_thread());
|
|
||||||
I(task->thread, !port->lock.lock_held_by_current_thread());
|
I(task->thread, !port->lock.lock_held_by_current_thread());
|
||||||
I(task->thread, !rendezvous_lock.lock_held_by_current_thread());
|
I(task->thread, !rendezvous_lock.lock_held_by_current_thread());
|
||||||
|
|
||||||
|
|
|
@ -516,7 +516,6 @@ rust_task::notify(bool success) {
|
||||||
msg.result = !success ? tr_failure : tr_success;
|
msg.result = !success ? tr_failure : tr_success;
|
||||||
|
|
||||||
target_port->send(&msg);
|
target_port->send(&msg);
|
||||||
scoped_lock with(target_task->port_lock);
|
|
||||||
target_port->deref();
|
target_port->deref();
|
||||||
}
|
}
|
||||||
target_task->deref();
|
target_task->deref();
|
||||||
|
|
|
@ -89,10 +89,6 @@ rust_task : public kernel_owned<rust_task>, rust_cond
|
||||||
|
|
||||||
bool propagate_failure;
|
bool propagate_failure;
|
||||||
|
|
||||||
// Protects port_table
|
|
||||||
lock_and_signal port_lock;
|
|
||||||
hash_map<rust_port_id, rust_port *> port_table;
|
|
||||||
|
|
||||||
rust_obstack dynastack;
|
rust_obstack dynastack;
|
||||||
|
|
||||||
uint32_t cc_counter;
|
uint32_t cc_counter;
|
||||||
|
@ -104,6 +100,10 @@ rust_task : public kernel_owned<rust_task>, rust_cond
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
// Protects port_table
|
||||||
|
lock_and_signal port_lock;
|
||||||
|
hash_map<rust_port_id, rust_port *> port_table;
|
||||||
|
|
||||||
// Protects state, cond, cond_name
|
// Protects state, cond, cond_name
|
||||||
lock_and_signal state_lock;
|
lock_and_signal state_lock;
|
||||||
rust_task_list *state;
|
rust_task_list *state;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue