summary refs log tree commit diff
path: root/src/rt
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-03-04 15:36:32 -0800
committerBrian Anderson <banderson@mozilla.com>2012-03-05 19:39:56 -0800
commit4c4a2320eb9620dbc68a264ce64ee1f233dd977d (patch)
tree906d11b31ca849c4d4a6ef0ca176dd46118e84be /src/rt
parent0a5603cb58bdc66ad6b6a030e4e98ebeb3c13721 (diff)
downloadrust-4c4a2320eb9620dbc68a264ce64ee1f233dd977d.tar.gz
rust-4c4a2320eb9620dbc68a264ce64ee1f233dd977d.zip
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.
Diffstat (limited to 'src/rt')
-rw-r--r--src/rt/rust_builtin.cpp3
-rw-r--r--src/rt/rust_internal.h23
-rw-r--r--src/rt/rust_port.cpp3
-rw-r--r--src/rt/rust_port.h4
-rw-r--r--src/rt/rust_port_selector.cpp1
-rw-r--r--src/rt/rust_task.cpp1
-rw-r--r--src/rt/rust_task.h8
7 files changed, 23 insertions, 20 deletions
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index b6ad9397e9c..c37944c3760 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -492,7 +492,7 @@ extern "C" CDECL void
 del_port(rust_port *port) {
     rust_task *task = rust_task_thread::get_task();
     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();
 }
 
@@ -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);
         if(port) {
             port->send(sptr);
-            scoped_lock with(target_task->port_lock);
             port->deref();
             sent = true;
         } else {
diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h
index 85b12b3e546..5996c6391ad 100644
--- a/src/rt/rust_internal.h
+++ b/src/rt/rust_internal.h
@@ -104,15 +104,20 @@ static size_t const BUF_BYTES = 2048;
   void ref() { ++ref_count; } \
   void deref() { if (--ref_count == 0) { dtor; } }
 
-#define RUST_ATOMIC_REFCOUNT()                                            \
-private:                                                                  \
-   intptr_t ref_count;                                                    \
-public:                                                                   \
-   void ref() {                                                           \
-       intptr_t old = sync::increment(ref_count);                         \
-       assert(old > 0);                                                   \
-   }                                                                      \
-   void deref() { if(0 == sync::decrement(ref_count)) { delete_this(); } }
+#define RUST_ATOMIC_REFCOUNT()                                             \
+private:                                                                   \
+   intptr_t ref_count;                                                     \
+public:                                                                    \
+   void ref() {                                                            \
+       intptr_t old = sync::increment(ref_count);                          \
+       assert(old > 0);                                                    \
+   }                                                                       \
+   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 {
     inline void *operator new(size_t size, rust_task *task, const char *tag);
diff --git a/src/rt/rust_port.cpp b/src/rt/rust_port.cpp
index bbfa737adec..628d3d70d18 100644
--- a/src/rt/rust_port.cpp
+++ b/src/rt/rust_port.cpp
@@ -25,8 +25,7 @@ void rust_port::detach() {
     // FIXME: Busy waiting until we're the only ref
     bool done = false;
     while (!done) {
-        scoped_lock with(task->port_lock);
-        done = ref_count == 1;
+        done = get_ref_count() == 1;
     }
 }
 
diff --git a/src/rt/rust_port.h b/src/rt/rust_port.h
index 0fbfeeac2ec..e1eb8a7871b 100644
--- a/src/rt/rust_port.h
+++ b/src/rt/rust_port.h
@@ -5,7 +5,7 @@
 
 class rust_port : public kernel_owned<rust_port>, public rust_cond {
 public:
-    RUST_REFCOUNTED(rust_port)
+    RUST_ATOMIC_REFCOUNT();
 
     rust_port_id id;
 
@@ -18,6 +18,8 @@ public:
 
     rust_port(rust_task *task, size_t unit_sz);
     ~rust_port();
+    void delete_this() { delete this; }
+
     void log_state();
     void send(void *sptr);
     void receive(void *dptr, uintptr_t *yield);
diff --git a/src/rt/rust_port_selector.cpp b/src/rt/rust_port_selector.cpp
index 319b6fb579d..a06da53f02e 100644
--- a/src/rt/rust_port_selector.cpp
+++ b/src/rt/rust_port_selector.cpp
@@ -69,7 +69,6 @@ void
 rust_port_selector::msg_sent_on(rust_port *port) {
     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, !rendezvous_lock.lock_held_by_current_thread());
 
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp
index 878bf099689..bb56b4dcb0a 100644
--- a/src/rt/rust_task.cpp
+++ b/src/rt/rust_task.cpp
@@ -516,7 +516,6 @@ rust_task::notify(bool success) {
                 msg.result = !success ? tr_failure : tr_success;
 
                 target_port->send(&msg);
-                scoped_lock with(target_task->port_lock);
                 target_port->deref();
             }
             target_task->deref();
diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h
index f822c109510..ebc90d48024 100644
--- a/src/rt/rust_task.h
+++ b/src/rt/rust_task.h
@@ -89,10 +89,6 @@ rust_task : public kernel_owned<rust_task>, rust_cond
 
     bool propagate_failure;
 
-    // Protects port_table
-    lock_and_signal port_lock;
-    hash_map<rust_port_id, rust_port *> port_table;
-
     rust_obstack dynastack;
 
     uint32_t cc_counter;
@@ -104,6 +100,10 @@ rust_task : public kernel_owned<rust_task>, rust_cond
 
 private:
 
+    // Protects port_table
+    lock_and_signal port_lock;
+    hash_map<rust_port_id, rust_port *> port_table;
+
     // Protects state, cond, cond_name
     lock_and_signal state_lock;
     rust_task_list *state;