about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-02-07 22:24:56 -0800
committerBrian Anderson <banderson@mozilla.com>2012-02-08 15:42:51 -0800
commit149d1d4a6e3bb8a439eff78cc6edb25f16aa47c5 (patch)
tree8cf83c0d9cc29e4d7a71aadcb7d209aef6d23179
parent35ba9715fafe14c96081049327c808fd0c5a2792 (diff)
downloadrust-149d1d4a6e3bb8a439eff78cc6edb25f16aa47c5.tar.gz
rust-149d1d4a6e3bb8a439eff78cc6edb25f16aa47c5.zip
core: Add a test for blocking in native code
-rw-r--r--src/libcore/task.rs68
-rw-r--r--src/rt/rust_builtin.cpp40
-rw-r--r--src/rt/rustrt.def.in6
3 files changed, 114 insertions, 0 deletions
diff --git a/src/libcore/task.rs b/src/libcore/task.rs
index a62dafbadaf..637a684b8d8 100644
--- a/src/libcore/task.rs
+++ b/src/libcore/task.rs
@@ -504,6 +504,74 @@ mod tests {
         comm::recv(po);
     }
 
+    #[nolink]
+    native mod rt {
+        fn rust_dbg_lock_create() -> *ctypes::void;
+        fn rust_dbg_lock_destroy(lock: *ctypes::void);
+        fn rust_dbg_lock_lock(lock: *ctypes::void);
+        fn rust_dbg_lock_unlock(lock: *ctypes::void);
+        fn rust_dbg_lock_wait(lock: *ctypes::void);
+        fn rust_dbg_lock_signal(lock: *ctypes::void);
+    }
+
+    #[test]
+    fn spawn_sched_blocking() {
+
+        // Testing that a task in one scheduler can block natively
+        // without affecting other schedulers
+        iter::repeat(20u) {||
+
+            let start_po = comm::port();
+            let start_ch = comm::chan(start_po);
+            let fin_po = comm::port();
+            let fin_ch = comm::chan(fin_po);
+
+            let lock = rt::rust_dbg_lock_create();
+
+            spawn_sched(1u) {||
+                rt::rust_dbg_lock_lock(lock);
+
+                comm::send(start_ch, ());
+
+                // Block the scheduler thread
+                rt::rust_dbg_lock_wait(lock);
+                rt::rust_dbg_lock_unlock(lock);
+
+                comm::send(fin_ch, ());
+            };
+
+            // Wait until the other task has its lock
+            comm::recv(start_po);
+
+            fn pingpong(po: comm::port<int>, ch: comm::chan<int>) {
+                let val = 20;
+                while val > 0 {
+                    val = comm::recv(po);
+                    comm::send(ch, val - 1);
+                }
+            }
+
+            let setup_po = comm::port();
+            let setup_ch = comm::chan(setup_po);
+            let parent_po = comm::port();
+            let parent_ch = comm::chan(parent_po);
+            spawn {||
+                let child_po = comm::port();
+                comm::send(setup_ch, comm::chan(child_po));
+                pingpong(child_po, parent_ch);
+            };
+
+            let child_ch = comm::recv(setup_po);
+            comm::send(child_ch, 20);
+            pingpong(parent_po, child_ch);
+            rt::rust_dbg_lock_lock(lock);
+            rt::rust_dbg_lock_signal(lock);
+            rt::rust_dbg_lock_unlock(lock);
+            comm::recv(fin_po);
+            rt::rust_dbg_lock_destroy(lock);
+        }
+    }
+
 }
 
 
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index c228aa9159f..19295167518 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -626,6 +626,46 @@ rust_log_console_off() {
     log_console_off(task->kernel->env);
 }
 
+extern "C" CDECL lock_and_signal *
+rust_dbg_lock_create() {
+    return new lock_and_signal();
+}
+
+extern "C" CDECL void
+rust_dbg_lock_destroy(lock_and_signal *lock) {
+    rust_task *task = rust_task_thread::get_task();
+    I(task->thread, lock);
+    delete lock;
+}
+
+extern "C" CDECL void
+rust_dbg_lock_lock(lock_and_signal *lock) {
+    rust_task *task = rust_task_thread::get_task();
+    I(task->thread, lock);
+    lock->lock();
+}
+
+extern "C" CDECL void
+rust_dbg_lock_unlock(lock_and_signal *lock) {
+    rust_task *task = rust_task_thread::get_task();
+    I(task->thread, lock);
+    lock->unlock();
+}
+
+extern "C" CDECL void
+rust_dbg_lock_wait(lock_and_signal *lock) {
+    rust_task *task = rust_task_thread::get_task();
+    I(task->thread, lock);
+    lock->wait();
+}
+
+extern "C" CDECL void
+rust_dbg_lock_signal(lock_and_signal *lock) {
+    rust_task *task = rust_task_thread::get_task();
+    I(task->thread, lock);
+    lock->signal();
+}
+
 //
 // Local Variables:
 // mode: C++
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index e51d47065f6..b0acbacf4e3 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -100,3 +100,9 @@ rust_uvtmp_read_start
 rust_uvtmp_timer
 rust_uvtmp_delete_buf
 rust_uvtmp_get_req_id
+rust_dbg_lock_create
+rust_dbg_lock_destroy
+rust_dbg_lock_lock
+rust_dbg_lock_unlock
+rust_dbg_lock_wait
+rust_dbg_lock_signal