Skip to content

Commit 7516513

Browse files
committed
---
yaml --- r: 11128 b: refs/heads/master c: 35ba971 h: refs/heads/master v: v3
1 parent 1a25fa9 commit 7516513

File tree

4 files changed

+101
-8
lines changed

4 files changed

+101
-8
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: 2f4e7c157eb3ab9cd8270c3e9fffedd03f0cb055
2+
refs/heads/master: 35ba9715fafe14c96081049327c808fd0c5a2792
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: 4a81779abd786ff22d71434c6d9a5917ea4cdfff
55
refs/heads/try: 2898dcc5d97da9427ac367542382b6239d9c0bbf

trunk/src/libcore/task.rs

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export get_task;
4444
export spawn;
4545
export spawn_joinable;
4646
export spawn_connected;
47+
export spawn_sched;
4748
export connected_fn;
4849
export connected_task;
4950
export currently_unwinding;
@@ -62,10 +63,15 @@ type rust_closure = {
6263
#[link_name = "rustrt"]
6364
#[abi = "cdecl"]
6465
native mod rustrt {
66+
fn rust_get_sched_id() -> sched_id;
67+
fn rust_new_sched(num_threads: c::uintptr_t) -> sched_id;
68+
6569
fn get_task_id() -> task_id;
6670
fn rust_get_task() -> *rust_task;
6771

6872
fn new_task() -> task_id;
73+
fn rust_new_task_in_sched(id: sched_id) -> task_id;
74+
6975
fn drop_task(task_id: *rust_task);
7076
fn get_task_pointer(id: task_id) -> *rust_task;
7177

@@ -85,6 +91,7 @@ type rust_task =
8591

8692
resource rust_task_ptr(task: *rust_task) { rustrt::drop_task(task); }
8793

94+
type sched_id = int;
8895
type task_id = int;
8996

9097
/*
@@ -111,14 +118,17 @@ Returns:
111118
A handle to the new task
112119
*/
113120
fn spawn(+f: fn~()) -> task {
114-
spawn_inner(f, none)
121+
spawn_inner(f, none, new_task_in_this_sched)
115122
}
116123

117-
fn spawn_inner(-f: fn~(),
118-
notify: option<comm::chan<task_notification>>) -> task unsafe {
124+
fn spawn_inner(
125+
-f: fn~(),
126+
notify: option<comm::chan<task_notification>>,
127+
new_task: fn() -> task_id
128+
) -> task unsafe {
119129
let closure: *rust_closure = unsafe::reinterpret_cast(ptr::addr_of(f));
120130
#debug("spawn: closure={%x,%x}", (*closure).fnptr, (*closure).envptr);
121-
let id = rustrt::new_task();
131+
let id = new_task();
122132

123133
// set up notifications if they are enabled.
124134
option::may(notify) {|c|
@@ -132,6 +142,39 @@ fn spawn_inner(-f: fn~(),
132142
ret id;
133143
}
134144

145+
fn new_task_in_this_sched() -> task_id {
146+
rustrt::new_task()
147+
}
148+
149+
fn new_task_in_new_sched(num_threads: uint) -> task_id {
150+
let sched_id = rustrt::rust_new_sched(num_threads);
151+
rustrt::rust_new_task_in_sched(sched_id)
152+
}
153+
154+
/*
155+
Function: spawn_sched
156+
157+
Creates a new scheduler and executes a task on it. Tasks subsequently
158+
spawned by that task will also execute on the new scheduler. When
159+
there are no more tasks to execute the scheduler terminates.
160+
161+
Arguments:
162+
163+
num_threads - The number of OS threads to dedicate schedule tasks on
164+
f - A unique closure to execute as a task on the new scheduler
165+
166+
Failure:
167+
168+
The number of threads must be greater than 0
169+
170+
*/
171+
fn spawn_sched(num_threads: uint, +f: fn~()) -> task {
172+
if num_threads < 1u {
173+
fail "Can not create a scheduler with no threads";
174+
}
175+
spawn_inner(f, none, bind new_task_in_new_sched(num_threads))
176+
}
177+
135178
/*
136179
Type: joinable_task
137180
@@ -142,7 +185,7 @@ type joinable_task = (task, comm::port<task_notification>);
142185
fn spawn_joinable(+f: fn~()) -> joinable_task {
143186
let notify_port = comm::port();
144187
let notify_chan = comm::chan(notify_port);
145-
let task = spawn_inner(f, some(notify_chan));
188+
let task = spawn_inner(f, some(notify_chan), new_task_in_this_sched);
146189
ret (task, notify_port);
147190
/*
148191
resource notify_rsrc(data: (comm::chan<task_notification>,
@@ -411,6 +454,56 @@ mod tests {
411454
_ { fail; }
412455
}
413456
}
457+
458+
#[test]
459+
#[should_fail]
460+
#[ignore(cfg(target_os = "win32"))]
461+
fn spawn_sched_no_threads() {
462+
spawn_sched(0u) {|| };
463+
}
464+
465+
#[test]
466+
fn spawn_sched_1() {
467+
let po = comm::port();
468+
let ch = comm::chan(po);
469+
470+
fn f(i: int, ch: comm::chan<()>) {
471+
let parent_sched_id = rustrt::rust_get_sched_id();
472+
473+
spawn_sched(1u) {||
474+
let child_sched_id = rustrt::rust_get_sched_id();
475+
assert parent_sched_id != child_sched_id;
476+
477+
if (i == 0) {
478+
comm::send(ch, ());
479+
} else {
480+
f(i - 1, ch);
481+
}
482+
};
483+
484+
}
485+
f(10, ch);
486+
comm::recv(po);
487+
}
488+
489+
#[test]
490+
fn spawn_sched_childs_on_same_sched() {
491+
let po = comm::port();
492+
let ch = comm::chan(po);
493+
494+
spawn_sched(1u) {||
495+
let parent_sched_id = rustrt::rust_get_sched_id();
496+
spawn {||
497+
let child_sched_id = rustrt::rust_get_sched_id();
498+
// This should be on the same scheduler
499+
assert parent_sched_id == child_sched_id;
500+
comm::send(ch, ());
501+
};
502+
};
503+
504+
comm::recv(po);
505+
}
506+
414507
}
415508

416509

trunk/src/rt/rust_builtin.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ rust_get_sched_id() {
438438
}
439439

440440
extern "C" CDECL rust_sched_id
441-
rust_new_sched(size_t threads) {
441+
rust_new_sched(uintptr_t threads) {
442442
rust_task *task = rust_task_thread::get_task();
443443
A(task->thread, threads > 0,
444444
"Can't create a scheduler with no threads, silly!");

trunk/src/test/run-pass/rt-sched-1.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ type task = *ctypes::void;
77
type closure = *ctypes::void;
88

99
native mod rustrt {
10-
fn rust_new_sched(num_threads: ctypes::size_t) -> sched_id;
10+
fn rust_new_sched(num_threads: uint) -> sched_id;
1111
fn rust_get_sched_id() -> sched_id;
1212
fn rust_new_task_in_sched(id: sched_id) -> task_id;
1313
fn start_task(id: task_id, f: closure);

0 commit comments

Comments
 (0)