Skip to content

Commit bb87969

Browse files
committed
---
yaml --- r: 31714 b: refs/heads/dist-snap c: 64ba7a3 h: refs/heads/master v: v3
1 parent acf233b commit bb87969

File tree

2 files changed

+45
-17
lines changed

2 files changed

+45
-17
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: d0c6ce338884ee21843f4b40bf6bf18d222ce5df
99
refs/heads/incoming: d9317a174e434d4c99fc1a37fd7dc0d2f5328d37
10-
refs/heads/dist-snap: a3f9e18b7acb64d905db4c76e483f5b555cb9188
10+
refs/heads/dist-snap: 64ba7a31cbf2218c8f9e69aa778d1bfe332ab218
1111
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1212
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/dist-snap/src/libcore/sync.rs

Lines changed: 44 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,23 @@ type signal_end = pipes::chan<()>;
1717
type waitqueue = { head: pipes::port<signal_end>,
1818
tail: pipes::chan<signal_end> };
1919

20-
fn new_waiter() -> (signal_end, wait_end) { pipes::stream() }
20+
fn waitqueue() -> waitqueue {
21+
let (tail, head) = pipes::stream();
22+
{ head: head, tail: tail }
23+
}
2124

22-
/// A counting semaphore.
23-
enum semaphore = exclusive<{
25+
/// A counting, blocking, bounded-waiting semaphore.
26+
enum semaphore = exclusive<semaphore_inner>;
27+
type semaphore_inner = {
2428
mut count: int,
2529
waiters: waitqueue,
26-
}>;
30+
//blocked: waitqueue,
31+
};
2732

2833
/// Create a new semaphore with the specified count.
2934
fn new_semaphore(count: int) -> semaphore {
30-
let (tail, head) = pipes::stream();
3135
semaphore(exclusive({ mut count: count,
32-
waiters: { head: head, tail: tail } }))
36+
waiters: waitqueue(), /* blocked: waitqueue() */ }))
3337
}
3438

3539
impl semaphore for &semaphore {
@@ -42,20 +46,21 @@ impl semaphore for &semaphore {
4246
* Acquires a resource represented by the semaphore. Blocks if necessary
4347
* until resource(s) become available.
4448
*/
45-
fn wait() {
49+
fn acquire() {
4650
let mut waiter_nobe = none;
4751
unsafe {
4852
do (**self).with |state| {
4953
state.count -= 1;
5054
if state.count < 0 {
51-
let (signal_end,wait_end) = new_waiter();
55+
let (signal_end,wait_end) = pipes::stream();
5256
waiter_nobe = some(wait_end);
5357
// Enqueue ourself.
5458
state.waiters.tail.send(signal_end);
5559
}
5660
}
5761
}
58-
for 1000.times { task::yield(); }
62+
// Uncomment if you wish to test for sem races. Not valgrind-friendly.
63+
/* for 1000.times { task::yield(); } */
5964
// Need to wait outside the exclusive.
6065
if waiter_nobe.is_some() {
6166
let _ = option::unwrap(waiter_nobe).recv();
@@ -66,7 +71,7 @@ impl semaphore for &semaphore {
6671
* Release a held resource represented by the semaphore. Wakes a blocked
6772
* contending task, if any exist.
6873
*/
69-
fn signal() {
74+
fn release() {
7075
unsafe {
7176
do (**self).with |state| {
7277
state.count += 1;
@@ -85,7 +90,7 @@ impl semaphore for &semaphore {
8590

8691
/// Runs a function with ownership of one of the semaphore's resources.
8792
fn access<U>(blk: fn() -> U) -> U {
88-
self.wait();
93+
self.acquire();
8994
let _x = sem_release(self);
9095
blk()
9196
}
@@ -95,7 +100,7 @@ impl semaphore for &semaphore {
95100
struct sem_release {
96101
sem: &semaphore;
97102
new(sem: &semaphore) { self.sem = sem; }
98-
drop { self.sem.signal(); }
103+
drop { self.sem.release(); }
99104
}
100105

101106
#[cfg(test)]
@@ -120,11 +125,11 @@ mod tests {
120125
let s = ~new_semaphore(0);
121126
let s2 = ~s.clone();
122127
do task::spawn {
123-
s2.wait();
128+
s2.acquire();
124129
c.send(());
125130
}
126131
for 10.times { task::yield(); }
127-
s.signal();
132+
s.release();
128133
let _ = p.recv();
129134

130135
/* Parent waits and child signals */
@@ -133,14 +138,16 @@ mod tests {
133138
let s2 = ~s.clone();
134139
do task::spawn {
135140
for 10.times { task::yield(); }
136-
s2.signal();
141+
s2.release();
137142
let _ = p.recv();
138143
}
139-
s.wait();
144+
s.acquire();
140145
c.send(());
141146
}
142147
#[test]
143148
fn test_sem_mutual_exclusion() {
149+
// Unsafely achieve shared state, and do the textbook
150+
// "load tmp <- ptr; inc tmp; store ptr <- tmp" dance.
144151
let (c,p) = pipes::stream();
145152
let s = ~new_semaphore(1);
146153
let s2 = ~s.clone();
@@ -167,7 +174,28 @@ mod tests {
167174
}
168175
}
169176
#[test]
177+
fn test_sem_multi_resource() {
178+
// Parent and child both get in the critical section at the same
179+
// time, and shake hands.
180+
let s = ~new_semaphore(2);
181+
let s2 = ~s.clone();
182+
let (c1,p1) = pipes::stream();
183+
let (c2,p2) = pipes::stream();
184+
do task::spawn {
185+
do s2.access {
186+
let _ = p2.recv();
187+
c1.send(());
188+
}
189+
}
190+
do s.access {
191+
c2.send(());
192+
let _ = p1.recv();
193+
}
194+
}
195+
#[test]
170196
fn test_sem_runtime_friendly_blocking() {
197+
// Force the runtime to schedule two threads on the same sched_loop.
198+
// When one blocks, it should schedule the other one.
171199
do task::spawn_sched(task::manual_threads(1)) {
172200
let s = ~new_semaphore(1);
173201
let s2 = ~s.clone();

0 commit comments

Comments
 (0)