Skip to content

Commit 56a059f

Browse files
committed
---
yaml --- r: 81895 b: refs/heads/master c: 33fef99 h: refs/heads/master i: 81893: ba17f0d 81891: 393bb66 81887: 58d2b2e v: v3
1 parent bd1a472 commit 56a059f

File tree

6 files changed

+567
-602
lines changed

6 files changed

+567
-602
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: d209717ddd260a5b0afd0dd07cddde903281f353
2+
refs/heads/master: 33fef9934b82df305e6f495839de566b81a5160b
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 6c08cc2db4f98e9f07ae7d50338396c4123c2f0a
55
refs/heads/try: 70152ff55722878cde684ee6462c14c65f2c4729

trunk/RELEASES.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
Version 0.8 (October 2013)
1+
Version 0.8 (September 2013)
22
--------------------------
33

4-
* ~2100 changes, numerous bugfixes
4+
* ~2200 changes, numerous bugfixes
55

66
* Language
77
* The `for` loop syntax has changed to work with the `Iterator` trait.

trunk/src/libstd/rt/comm.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,6 @@ impl<T> ChanOne<T> {
118118
rtassert!(!rt::in_sched_context());
119119
}
120120

121-
// In order to prevent starvation of other tasks in situations
122-
// where a task sends repeatedly without ever receiving, we
123-
// occassionally yield instead of doing a send immediately.
124-
// Only doing this if we're doing a rescheduling send,
125-
// otherwise the caller is expecting not to context switch.
126-
if do_resched {
127-
// XXX: This TLS hit should be combined with other uses of the scheduler below
128-
let sched: ~Scheduler = Local::take();
129-
sched.maybe_yield();
130-
}
131-
132121
let mut this = self;
133122
let mut recvr_active = true;
134123
let packet = this.packet();

trunk/src/libstd/rt/sched.rs

Lines changed: 28 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use rt::local::Local;
2626
use rt::rtio::{RemoteCallback, PausibleIdleCallback};
2727
use borrow::{to_uint};
2828
use cell::Cell;
29-
use rand::{XorShiftRng, Rng, Rand};
29+
use rand::{XorShiftRng, Rng};
3030
use iter::range;
3131
use vec::{OwnedVector};
3232

@@ -78,14 +78,7 @@ pub struct Scheduler {
7878
/// A fast XorShift rng for scheduler use
7979
rng: XorShiftRng,
8080
/// A toggleable idle callback
81-
idle_callback: Option<~PausibleIdleCallback>,
82-
/// A countdown that starts at a random value and is decremented
83-
/// every time a yield check is performed. When it hits 0 a task
84-
/// will yield.
85-
yield_check_count: uint,
86-
/// A flag to tell the scheduler loop it needs to do some stealing
87-
/// in order to introduce randomness as part of a yield
88-
steal_for_yield: bool
81+
idle_callback: Option<~PausibleIdleCallback>
8982
}
9083

9184
/// An indication of how hard to work on a given operation, the difference
@@ -96,13 +89,6 @@ enum EffortLevel {
9689
GiveItYourBest
9790
}
9891

99-
static MAX_YIELD_CHECKS: uint = 200;
100-
101-
fn reset_yield_check(rng: &mut XorShiftRng) -> uint {
102-
let r: uint = Rand::rand(rng);
103-
r % MAX_YIELD_CHECKS + 1
104-
}
105-
10692
impl Scheduler {
10793

10894
// * Initialization Functions
@@ -127,7 +113,7 @@ impl Scheduler {
127113
friend: Option<SchedHandle>)
128114
-> Scheduler {
129115

130-
let mut sched = Scheduler {
116+
Scheduler {
131117
sleeper_list: sleeper_list,
132118
message_queue: MessageQueue::new(),
133119
sleepy: false,
@@ -141,14 +127,8 @@ impl Scheduler {
141127
run_anything: run_anything,
142128
friend_handle: friend,
143129
rng: XorShiftRng::new(),
144-
idle_callback: None,
145-
yield_check_count: 0,
146-
steal_for_yield: false
147-
};
148-
149-
sched.yield_check_count = reset_yield_check(&mut sched.rng);
150-
151-
return sched;
130+
idle_callback: None
131+
}
152132
}
153133

154134
// XXX: This may eventually need to be refactored so that
@@ -327,7 +307,8 @@ impl Scheduler {
327307
}
328308
Some(TaskFromFriend(task)) => {
329309
rtdebug!("got a task from a friend. lovely!");
330-
this.process_task(task, Scheduler::resume_task_immediately_cl);
310+
this.process_task(task,
311+
Scheduler::resume_task_immediately_cl).map_move(Local::put);
331312
return None;
332313
}
333314
Some(Wake) => {
@@ -371,8 +352,8 @@ impl Scheduler {
371352
match this.find_work() {
372353
Some(task) => {
373354
rtdebug!("found some work! processing the task");
374-
this.process_task(task, Scheduler::resume_task_immediately_cl);
375-
return None;
355+
return this.process_task(task,
356+
Scheduler::resume_task_immediately_cl);
376357
}
377358
None => {
378359
rtdebug!("no work was found, returning the scheduler struct");
@@ -392,35 +373,14 @@ impl Scheduler {
392373
// there, trying to steal from the remote work queues.
393374
fn find_work(&mut self) -> Option<~Task> {
394375
rtdebug!("scheduler looking for work");
395-
if !self.steal_for_yield {
396-
match self.work_queue.pop() {
397-
Some(task) => {
398-
rtdebug!("found a task locally");
399-
return Some(task)
400-
}
401-
None => {
402-
rtdebug!("scheduler trying to steal");
403-
return self.try_steals();
404-
}
376+
match self.work_queue.pop() {
377+
Some(task) => {
378+
rtdebug!("found a task locally");
379+
return Some(task)
405380
}
406-
} else {
407-
// During execution of the last task, it performed a 'yield',
408-
// so we're doing some work stealing in order to introduce some
409-
// scheduling randomness. Otherwise we would just end up popping
410-
// that same task again. This is pretty lame and is to work around
411-
// the problem that work stealing is not designed for 'non-strict'
412-
// (non-fork-join) task parallelism.
413-
self.steal_for_yield = false;
414-
match self.try_steals() {
415-
Some(task) => {
416-
rtdebug!("stole a task after yielding");
417-
return Some(task);
418-
}
419-
None => {
420-
rtdebug!("did not steal a task after yielding");
421-
// Back to business
422-
return self.find_work();
423-
}
381+
None => {
382+
rtdebug!("scheduler trying to steal");
383+
return self.try_steals();
424384
}
425385
}
426386
}
@@ -449,7 +409,7 @@ impl Scheduler {
449409
// place.
450410

451411
fn process_task(~self, task: ~Task,
452-
schedule_fn: SchedulingFn) {
412+
schedule_fn: SchedulingFn) -> Option<~Scheduler> {
453413
let mut this = self;
454414
let mut task = task;
455415

@@ -462,23 +422,23 @@ impl Scheduler {
462422
rtdebug!("sending task home");
463423
task.give_home(Sched(home_handle));
464424
Scheduler::send_task_home(task);
465-
Local::put(this);
425+
return Some(this);
466426
} else {
467427
rtdebug!("running task here");
468428
task.give_home(Sched(home_handle));
469-
schedule_fn(this, task);
429+
return schedule_fn(this, task);
470430
}
471431
}
472432
AnySched if this.run_anything => {
473433
rtdebug!("running anysched task here");
474434
task.give_home(AnySched);
475-
schedule_fn(this, task);
435+
return schedule_fn(this, task);
476436
}
477437
AnySched => {
478438
rtdebug!("sending task to friend");
479439
task.give_home(AnySched);
480440
this.send_to_friend(task);
481-
Local::put(this);
441+
return Some(this);
482442
}
483443
}
484444
}
@@ -647,14 +607,15 @@ impl Scheduler {
647607

648608
// * Context Swapping Helpers - Here be ugliness!
649609

650-
pub fn resume_task_immediately(~self, task: ~Task) {
610+
pub fn resume_task_immediately(~self, task: ~Task) -> Option<~Scheduler> {
651611
do self.change_task_context(task) |sched, stask| {
652612
sched.sched_task = Some(stask);
653613
}
614+
return None;
654615
}
655616

656617
fn resume_task_immediately_cl(sched: ~Scheduler,
657-
task: ~Task) {
618+
task: ~Task) -> Option<~Scheduler> {
658619
sched.resume_task_immediately(task)
659620
}
660621

@@ -701,10 +662,11 @@ impl Scheduler {
701662
}
702663
}
703664

704-
fn switch_task(sched: ~Scheduler, task: ~Task) {
665+
fn switch_task(sched: ~Scheduler, task: ~Task) -> Option<~Scheduler> {
705666
do sched.switch_running_tasks_and_then(task) |sched, last_task| {
706667
sched.enqueue_blocked_task(last_task);
707668
};
669+
return None;
708670
}
709671

710672
// * Task Context Helpers
@@ -724,7 +686,7 @@ impl Scheduler {
724686

725687
pub fn run_task(task: ~Task) {
726688
let sched: ~Scheduler = Local::take();
727-
sched.process_task(task, Scheduler::switch_task);
689+
sched.process_task(task, Scheduler::switch_task).map_move(Local::put);
728690
}
729691

730692
pub fn run_task_later(next_task: ~Task) {
@@ -734,33 +696,6 @@ impl Scheduler {
734696
};
735697
}
736698

737-
/// Yield control to the scheduler, executing another task. This is guaranteed
738-
/// to introduce some amount of randomness to the scheduler. Currently the
739-
/// randomness is a result of performing a round of work stealing (which
740-
/// may end up stealing from the current scheduler).
741-
pub fn yield_now(~self) {
742-
let mut this = self;
743-
this.yield_check_count = reset_yield_check(&mut this.rng);
744-
// Tell the scheduler to start stealing on the next iteration
745-
this.steal_for_yield = true;
746-
do this.deschedule_running_task_and_then |sched, task| {
747-
sched.enqueue_blocked_task(task);
748-
}
749-
}
750-
751-
pub fn maybe_yield(~self) {
752-
// The number of times to do the yield check before yielding, chosen arbitrarily.
753-
let mut this = self;
754-
rtassert!(this.yield_check_count > 0);
755-
this.yield_check_count -= 1;
756-
if this.yield_check_count == 0 {
757-
this.yield_now();
758-
} else {
759-
Local::put(this);
760-
}
761-
}
762-
763-
764699
// * Utility Functions
765700

766701
pub fn sched_id(&self) -> uint { to_uint(self) }
@@ -783,7 +718,7 @@ impl Scheduler {
783718

784719
// Supporting types
785720

786-
type SchedulingFn = ~fn(~Scheduler, ~Task);
721+
type SchedulingFn = ~fn(~Scheduler, ~Task) -> Option<~Scheduler>;
787722

788723
pub enum SchedMessage {
789724
Wake,
@@ -1296,40 +1231,4 @@ mod test {
12961231
}
12971232
}
12981233
}
1299-
1300-
#[test]
1301-
fn dont_starve_2() {
1302-
use rt::comm::oneshot;
1303-
1304-
do stress_factor().times {
1305-
do run_in_newsched_task {
1306-
let (port, chan) = oneshot();
1307-
let (_port2, chan2) = stream();
1308-
1309-
// This task should not be able to starve the other task.
1310-
// The sends should eventually yield.
1311-
do spawntask {
1312-
while !port.peek() {
1313-
chan2.send(());
1314-
}
1315-
}
1316-
1317-
chan.send(());
1318-
}
1319-
}
1320-
}
1321-
1322-
// Regression test for a logic bug that would cause single-threaded schedulers
1323-
// to sleep forever after yielding and stealing another task.
1324-
#[test]
1325-
fn single_threaded_yield() {
1326-
use task::{spawn, spawn_sched, SingleThreaded, deschedule};
1327-
use num::Times;
1328-
1329-
do spawn_sched(SingleThreaded) {
1330-
do 5.times { deschedule(); }
1331-
}
1332-
do spawn { }
1333-
do spawn { }
1334-
}
13351234
}

0 commit comments

Comments
 (0)