summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authortoddaaro <github@opprobrio.us>2013-06-12 14:55:32 -0700
committertoddaaro <github@opprobrio.us>2013-06-12 14:55:32 -0700
commit4224fc7aad3cfbd7093e55812e5a566d7aad3325 (patch)
tree9c04690212581ccaac9359e7eda0377e4dc6e963 /src/libstd
parent84280819585fb65bf18903aef9364579f3552522 (diff)
downloadrust-4224fc7aad3cfbd7093e55812e5a566d7aad3325.tar.gz
rust-4224fc7aad3cfbd7093e55812e5a566d7aad3325.zip
added functionality to tell schedulers to refuse to run tasks that are not pinned to them
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/rt/sched.rs48
-rw-r--r--src/libstd/rt/test.rs30
2 files changed, 60 insertions, 18 deletions
diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs
index 698cafdf8c6..4bc61d63824 100644
--- a/src/libstd/rt/sched.rs
+++ b/src/libstd/rt/sched.rs
@@ -70,7 +70,9 @@ pub struct Scheduler {
     /// An action performed after a context switch on behalf of the
     /// code running before the context switch
     priv cleanup_job: Option<CleanupJob>,
-    metrics: SchedMetrics
+    metrics: SchedMetrics,
+    /// Should this scheduler run any task, or only pinned tasks?
+    run_anything: bool
 }
 
 pub struct SchedHandle {
@@ -136,6 +138,16 @@ pub impl Scheduler {
            sleeper_list: SleeperList)
         -> Scheduler {
 
+        Scheduler::new_special(event_loop, work_queue, sleeper_list, true)
+
+    }
+
+    fn new_special(event_loop: ~EventLoopObject,
+           work_queue: WorkQueue<~Coroutine>,
+           sleeper_list: SleeperList,
+           run_anything: bool)
+        -> Scheduler {
+
         // Lazily initialize the runtime TLS key
         local_ptr::init_tls_key();
 
@@ -150,7 +162,8 @@ pub impl Scheduler {
             saved_context: Context::empty(),
             current_task: None,
             cleanup_job: None,
-            metrics: SchedMetrics::new()
+            metrics: SchedMetrics::new(),
+            run_anything: run_anything
         }
     }
 
@@ -429,19 +442,28 @@ pub impl Scheduler {
         assert!(!self.in_task_context());
 
         rtdebug!("looking in work queue for task to schedule");
-
         let mut this = self;
-        match this.work_queue.pop() {
-            Some(task) => {
-                rtdebug!("resuming task from work queue");
-                this.resume_task_immediately(task);
-                return true;
-            }
-            None => {
-                rtdebug!("no tasks in queue");
-                Local::put(this);
-                return false;
+
+        if this.run_anything {
+            match this.work_queue.pop() {
+                Some(task) => {
+                    rtdebug!("resuming task from work queue");
+                    this.resume_task_immediately(task);
+                    return true;
+                }
+                None => {
+                    rtdebug!("no tasks in queue");
+                    Local::put(this);
+                    return false;
+                }
             }
+        } else {
+            // In this branch we have a scheduler that is not allowed
+            // to run unpinned tasks. As such it will only get tasks
+            // to run from the message queue.
+            rtdebug!("skipping resume_task_from_queue");
+            Local::put(this);
+            return false;
         }
     }
 
diff --git a/src/libstd/rt/test.rs b/src/libstd/rt/test.rs
index 97aa76d7db6..ecef505ce57 100644
--- a/src/libstd/rt/test.rs
+++ b/src/libstd/rt/test.rs
@@ -157,23 +157,43 @@ pub fn run_in_mt_newsched_task_random_homed() {
         let mut handles = ~[];
         let mut scheds = ~[];
 
-        for uint::range(0, nthreads) |_| {
+        // create a few special schedulers, those with even indicies
+        // will be pinned-only
+        for uint::range(0, nthreads) |i| {
+            let special = (i % 2) == 0;
             let loop_ = ~UvEventLoop::new();
-            let mut sched = ~Scheduler::new(loop_, work_queue.clone(), sleepers.clone());
+            let mut sched = ~Scheduler::new_special(loop_, work_queue.clone(), sleepers.clone(), special);
             let handle = sched.make_handle();
             handles.push(handle);
             scheds.push(sched);
-        }
+        }           
 
         // Schedule a pile o tasks
-        let n = 120*stress_factor();        
+        let n = 5*stress_factor();        
         for uint::range(0,n) |_i| {
                 rtdebug!("creating task: %u", _i);
                 let hf: ~fn() = || { assert!(true) };
                 spawntask_homed(&mut scheds, hf);            
             }
 
-        let f: ~fn() = || { assert!(true); };
+        // Now we want another pile o tasks that do not ever run on a
+        // special scheduler, because they are normal tasks. Because
+        // we can we put these in the "main" task.
+
+        let n = 5*stress_factor();
+
+        let f: ~fn() = || {        
+            for uint::range(0,n) |_| {
+                let f: ~fn()  = || {                                 
+                    // Borrow the scheduler we run on and check if it is
+                    // privliged.
+                    do Local::borrow::<Scheduler,()> |sched| {
+                        assert!(sched.run_anything);
+                    };
+                };
+                spawntask_random(f);
+            };
+        };
         
         let f_cell = Cell(f);
         let handles = Cell(handles);