Skip to content

Commit 566b805

Browse files
committed
---
yaml --- r: 7093 b: refs/heads/master c: 98f5109 h: refs/heads/master i: 7091: 755c54d v: v3
1 parent 8da8c31 commit 566b805

File tree

9 files changed

+87
-178
lines changed

9 files changed

+87
-178
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: e88905cd2882919f95084f41539ca9601ebf5cfc
2+
refs/heads/master: 98f5109cde838e66d629bf05c804ad1ca9b06c42

trunk/src/comp/middle/trans_closure.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import trans::{
3333
// struct closure_box {
3434
// unsigned ref_count; // only used for sharid environments
3535
// struct closure {
36-
// type_desc *tydesc; // descriptor for the env type
36+
// type_desc *tydesc; // descriptor for the "struct closure" type
3737
// type_desc *bound_tdescs[]; // bound descriptors
3838
// struct {
3939
// upvar1_t upvar1;

trunk/src/libcore/task.rs

Lines changed: 53 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import comm;
3131
import option::{some, none};
3232
import option = option::t;
3333
import ptr;
34+
import c = ctypes;
3435

3536
export task;
3637
export joinable_task;
@@ -46,7 +47,6 @@ export tr_success;
4647
export tr_failure;
4748
export get_task;
4849
export spawn;
49-
export spawn_notify;
5050
export spawn_joinable;
5151

5252
#[abi = "rust-intrinsic"]
@@ -55,6 +55,10 @@ native mod rusti {
5555
fn task_sleep(task: *rust_task, time_in_us: uint, &killed: bool);
5656
}
5757

58+
type rust_closure = {
59+
fnptr: c::intptr_t, envptr: c::intptr_t
60+
};
61+
5862
#[link_name = "rustrt"]
5963
#[abi = "cdecl"]
6064
native mod rustrt {
@@ -70,8 +74,7 @@ native mod rustrt {
7074

7175
fn migrate_alloc(alloc: *u8, target: task_id);
7276

73-
fn start_task(id: task, closure: *u8);
74-
77+
fn start_task(id: task, closure: *rust_closure);
7578
}
7679

7780
/* Section: Types */
@@ -93,13 +96,60 @@ A handle to a task
9396
*/
9497
type task = task_id;
9598

99+
/*
100+
Function: spawn
101+
102+
Creates and executes a new child task
103+
104+
Sets up a new task with its own call stack and schedules it to be
105+
executed. Upon execution, the closure `f()` will be invoked.
106+
107+
Parameters:
108+
109+
f - A function to execute in the new task
110+
111+
Returns:
112+
113+
A handle to the new task
114+
*/
115+
fn spawn(-f: sendfn()) -> task unsafe {
116+
let closure: *rust_closure = unsafe::reinterpret_cast(ptr::addr_of(f));
117+
#debug("spawn: closure={%x,%x}", (*closure).fnptr, (*closure).envptr);
118+
let id = rustrt::new_task();
119+
rustrt::start_task(id, closure);
120+
unsafe::leak(f);
121+
ret id;
122+
}
123+
96124
/*
97125
Type: joinable_task
98126
99127
A task that sends notification upon termination
100128
*/
101129
type joinable_task = (task, comm::port<task_notification>);
102130

131+
fn spawn_joinable(-f: sendfn()) -> joinable_task {
132+
resource notify_rsrc(data: (comm::chan<task_notification>,
133+
task,
134+
@mutable task_result)) {
135+
let (chan, task, tr) = data;
136+
let msg = exit(task, *tr);
137+
comm::send(chan, msg);
138+
}
139+
140+
let notify_port = comm::port();
141+
let notify_chan = comm::chan(notify_port);
142+
let g = sendfn[copy notify_chan; move f]() {
143+
let this_task = rustrt::get_task_id();
144+
let result = @mutable tr_failure;
145+
let _rsrc = notify_rsrc((notify_chan, this_task, result));
146+
f();
147+
*result = tr_success; // rsrc will fire msg when fn returns
148+
};
149+
let task = spawn(g);
150+
ret (task, notify_port);
151+
}
152+
103153
/*
104154
Tag: task_result
105155
@@ -213,130 +263,6 @@ Unpin the current task and future child tasks
213263
*/
214264
fn unpin() { rustrt::unpin_task(); }
215265

216-
/*
217-
Function: spawn
218-
219-
Creates and executes a new child task
220-
221-
Sets up a new task with its own call stack and schedules it to be executed.
222-
Upon execution the new task will call function `f` with the provided
223-
argument `data`.
224-
225-
Function `f` is a bare function, meaning it may not close over any data, as do
226-
shared functions (fn@) and lambda blocks. `data` must be a uniquely owned
227-
type; it is moved into the new task and thus can no longer be accessed
228-
locally.
229-
230-
Parameters:
231-
232-
data - A unique-type value to pass to the new task
233-
f - A function to execute in the new task
234-
235-
Returns:
236-
237-
A handle to the new task
238-
*/
239-
fn spawn<T: send>(-data: T, f: fn(T)) -> task {
240-
spawn_inner(data, f, none)
241-
}
242-
243-
/*
244-
Function: spawn_notify
245-
246-
Create and execute a new child task, requesting notification upon its
247-
termination
248-
249-
Immediately before termination, either on success or failure, the spawned
250-
task will send a <task_notification> message on the provided channel.
251-
*/
252-
fn spawn_notify<T: send>(-data: T, f: fn(T),
253-
notify: comm::chan<task_notification>) -> task {
254-
spawn_inner(data, f, some(notify))
255-
}
256-
257-
/*
258-
Function: spawn_joinable
259-
260-
Create and execute a task which can later be joined with the <join> function
261-
262-
This is a convenience wrapper around spawn_notify which, when paired
263-
with <join> can be easily used to spawn a task then wait for it to
264-
complete.
265-
*/
266-
fn spawn_joinable<T: send>(-data: T, f: fn(T)) -> joinable_task {
267-
let p = comm::port::<task_notification>();
268-
let id = spawn_notify(data, f, comm::chan::<task_notification>(p));
269-
ret (id, p);
270-
}
271-
272-
// FIXME: To transition from the unsafe spawn that spawns a shared closure to
273-
// the safe spawn that spawns a bare function we're going to write
274-
// barefunc-spawn on top of unsafe-spawn. Sadly, bind does not work reliably
275-
// enough to suite our needs (#1034, probably others yet to be discovered), so
276-
// we're going to copy the bootstrap data into a unique pointer, cast it to an
277-
// unsafe pointer then wrap up the bare function and the unsafe pointer in a
278-
// shared closure to spawn.
279-
//
280-
// After the transition this should all be rewritten.
281-
282-
fn spawn_inner<T: send>(-data: T, f: fn(T),
283-
notify: option<comm::chan<task_notification>>)
284-
-> task unsafe {
285-
286-
fn wrapper<T: send>(data: *u8, f: fn(T)) unsafe {
287-
let data: ~T = unsafe::reinterpret_cast(data);
288-
f(*data);
289-
}
290-
291-
let data = ~data;
292-
let dataptr: *u8 = unsafe::reinterpret_cast(data);
293-
unsafe::leak(data);
294-
let wrapped = bind wrapper(dataptr, f);
295-
ret unsafe_spawn_inner(wrapped, notify);
296-
}
297-
298-
// FIXME: This is the old spawn function that spawns a shared closure.
299-
// It is a hack and needs to be rewritten.
300-
fn unsafe_spawn_inner(-thunk: fn@(),
301-
notify: option<comm::chan<task_notification>>) ->
302-
task unsafe {
303-
let id = rustrt::new_task();
304-
305-
let raw_thunk: {code: uint, env: uint} = cast(thunk);
306-
307-
// set up the task pointer
308-
let task_ptr <- rust_task_ptr(rustrt::get_task_pointer(id));
309-
310-
assert (ptr::null() != (**task_ptr).stack_ptr);
311-
312-
// copy the thunk from our stack to the new stack
313-
let sp: uint = cast((**task_ptr).stack_ptr);
314-
let ptrsize = sys::size_of::<*u8>();
315-
let thunkfn: *mutable uint = cast(sp - ptrsize * 2u);
316-
let thunkenv: *mutable uint = cast(sp - ptrsize);
317-
*thunkfn = cast(raw_thunk.code);;
318-
*thunkenv = cast(raw_thunk.env);;
319-
// Advance the stack pointer. No need to align because
320-
// the native code will do that for us
321-
(**task_ptr).stack_ptr = cast(sp - ptrsize * 2u);
322-
323-
// set up notifications if they are enabled.
324-
alt notify {
325-
some(c) {
326-
(**task_ptr).notify_enabled = 1;
327-
(**task_ptr).notify_chan = c;
328-
}
329-
none { }
330-
}
331-
332-
// give the thunk environment's allocation to the new task
333-
rustrt::migrate_alloc(cast(raw_thunk.env), id);
334-
rustrt::start_task(id, cast(thunkfn));
335-
// don't cleanup the thunk in this task
336-
unsafe::leak(thunk);
337-
ret id;
338-
}
339-
340266
// Local Variables:
341267
// mode: rust;
342268
// fill-column: 78;

trunk/src/libstd/test.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ type test_name = str;
4949
// to support isolation of tests into tasks.
5050
type test_fn<T> = T;
5151

52-
type default_test_fn = test_fn<fn()>;
52+
type default_test_fn = test_fn<sendfn()>;
5353

5454
// The definition of a single test. A test runner will run a list of
5555
// these.
@@ -336,11 +336,10 @@ fn run_test<T: copy>(test: test_desc<T>,
336336
// We need to run our tests in another task in order to trap test failures.
337337
// This function only works with functions that don't contain closures.
338338
fn default_test_to_task(&&f: default_test_fn) -> joinable {
339-
fn run_task(f: default_test_fn) {
339+
ret task::spawn_joinable(sendfn[copy f]() {
340340
configure_test_task();
341341
f();
342-
}
343-
ret task::spawn_joinable(copy f, run_task);
342+
});
344343
}
345344

346345
// Call from within a test task to make sure it's set up correctly

trunk/src/rt/rust.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
9898
DLOG(sched, dom, "startup: arg[%d] = '%s'", i, args->argv[i]);
9999
}
100100

101-
root_task->start(main_fn, (uintptr_t)args->args);
101+
root_task->start((spawn_fn)main_fn, (uintptr_t)args->args);
102102
root_task->deref();
103103
root_task = NULL;
104104

@@ -119,6 +119,5 @@ rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {
119119
// indent-tabs-mode: nil
120120
// c-basic-offset: 4
121121
// buffer-file-coding-system: utf-8-unix
122-
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
123122
// End:
124123
//

trunk/src/rt/rust_builtin.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "rust_internal.h"
44
#include "rust_scheduler.h"
5+
#include "rust_task.h"
56

67
#if !defined(__WIN32__)
78
#include <sys/time.h>
@@ -424,18 +425,11 @@ struct fn_env_pair {
424425
intptr_t env;
425426
};
426427

427-
// FIXME This is probably not needed at all anymore. Have to rearrange some
428-
// argument passing to remove it.
429-
void rust_spawn_wrapper(void* retptr, void* envptr,
430-
void(*func)(void*, void*)) {
431-
func(retptr, envptr);
432-
}
433-
434428
extern "C" CDECL void
435429
start_task(rust_task_id id, fn_env_pair *f) {
436430
rust_task *task = rust_scheduler::get_task();
437431
rust_task *target = task->kernel->get_task_by_id(id);
438-
target->start((uintptr_t)rust_spawn_wrapper, f->f, f->env);
432+
target->start((spawn_fn)f->f, f->env);
439433
target->deref();
440434
}
441435

@@ -578,6 +572,5 @@ port_recv(uintptr_t *dptr, rust_port *port,
578572
// indent-tabs-mode: nil
579573
// c-basic-offset: 4
580574
// buffer-file-coding-system: utf-8-unix
581-
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
582575
// End:
583576
//

0 commit comments

Comments
 (0)