Skip to content

Commit ef282db

Browse files
committed
auto merge of #5409 : brson/rust/rt, r=brson
r? There are a lot of commits here, but not all that much substance. Mostly just refactoring. I started sketching out the beginnings of a very simple I/O API in `core::rt::io` that represents I/O streams as a single `Stream` trait instead of `Reader` / `Writer` pairs. This seems to be the more common pattern (at least this is how the .NET BCL does it) and it seems to me that separate readers and writers would make duplex streams very awkward. Regardless, I don't intend to go very far down the I/O API design road without some mailing list discussion. I've also started on the uv bindings for file I/O but haven't gotten very far. Also hooked up the new scheduler to `rust_start` and the compiletest driver. 70% of run-pass test cases already pass, but I wouldn't read too much into that. I also split the direct, low-level uv bindings in two so that the scheduler can have its own set, leaving `std::net` on its own.
2 parents 6d4499c + 30d4124 commit ef282db

29 files changed

+1815
-1086
lines changed

Makefile.in

+1-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ $(foreach target,$(CFG_TARGET_TRIPLES),\
238238

239239
CORELIB_CRATE := $(S)src/libcore/core.rc
240240
CORELIB_INPUTS := $(wildcard $(addprefix $(S)src/libcore/, \
241-
core.rc *.rs */*.rs))
241+
core.rc *.rs */*.rs */*/*rs))
242242

243243
######################################################################
244244
# Standard library variables

mk/tests.mk

+11-3
Original file line numberDiff line numberDiff line change
@@ -244,21 +244,29 @@ $(foreach host,$(CFG_HOST_TRIPLES), \
244244

245245
define TEST_RUNNER
246246

247+
# If NO_REBUILD is set then break the dependencies on std so we can
248+
# test crates without rebuilding core and std first
249+
ifeq ($(NO_REBUILD),)
250+
STDTESTDEP_$(1)_$(2)_$(3) = $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB_$(2))
251+
else
252+
STDTESTDEP_$(1)_$(2)_$(3) =
253+
endif
254+
247255
$(3)/test/coretest.stage$(1)-$(2)$$(X_$(2)): \
248256
$$(CORELIB_CRATE) $$(CORELIB_INPUTS) \
249-
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB_$(2))
257+
$$(STDTESTDEP_$(1)_$(2)_$(3))
250258
@$$(call E, compile_and_link: $$@)
251259
$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test
252260

253261
$(3)/test/stdtest.stage$(1)-$(2)$$(X_$(2)): \
254262
$$(STDLIB_CRATE) $$(STDLIB_INPUTS) \
255-
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB_$(2))
263+
$$(STDTESTDEP_$(1)_$(2)_$(3))
256264
@$$(call E, compile_and_link: $$@)
257265
$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test
258266

259267
$(3)/test/syntaxtest.stage$(1)-$(2)$$(X_$(2)): \
260268
$$(LIBSYNTAX_CRATE) $$(LIBSYNTAX_INPUTS) \
261-
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB_$(2))
269+
$$(STDTESTDEP_$(1)_$(2)_$(3))
262270
@$$(call E, compile_and_link: $$@)
263271
$$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< --test
264272

src/compiletest/common.rs

+3
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ pub struct config {
6363
// Run tests using the JIT
6464
jit: bool,
6565

66+
// Run tests using the new runtime
67+
newrt: bool,
68+
6669
// Explain what's going on
6770
verbose: bool
6871

src/compiletest/compiletest.rc

+4-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ pub fn parse_config(args: ~[~str]) -> config {
6161
getopts::optopt(~"runtool"), getopts::optopt(~"rustcflags"),
6262
getopts::optflag(~"verbose"),
6363
getopts::optopt(~"logfile"),
64-
getopts::optflag(~"jit")];
64+
getopts::optflag(~"jit"),
65+
getopts::optflag(~"newrt")];
6566

6667
fail_unless!(!args.is_empty());
6768
let args_ = vec::tail(args);
@@ -95,6 +96,7 @@ pub fn parse_config(args: ~[~str]) -> config {
9596
runtool: getopts::opt_maybe_str(matches, ~"runtool"),
9697
rustcflags: getopts::opt_maybe_str(matches, ~"rustcflags"),
9798
jit: getopts::opt_present(matches, ~"jit"),
99+
newrt: getopts::opt_present(matches, ~"newrt"),
98100
verbose: getopts::opt_present(matches, ~"verbose")
99101
}
100102
}
@@ -114,6 +116,7 @@ pub fn log_config(config: config) {
114116
logv(c, fmt!("runtool: %s", opt_str(config.runtool)));
115117
logv(c, fmt!("rustcflags: %s", opt_str(config.rustcflags)));
116118
logv(c, fmt!("jit: %b", config.jit));
119+
logv(c, fmt!("newrt: %b", config.newrt));
117120
logv(c, fmt!("verbose: %b", config.verbose));
118121
logv(c, fmt!("\n"));
119122
}

src/compiletest/runtest.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -484,9 +484,17 @@ fn compile_test_(config: config, props: TestProps,
484484

485485
fn exec_compiled_test(config: config, props: TestProps,
486486
testfile: &Path) -> ProcRes {
487+
488+
// If testing the new runtime then set the RUST_NEWRT env var
489+
let env = if config.newrt {
490+
props.exec_env + ~[(~"RUST_NEWRT", ~"1")]
491+
} else {
492+
props.exec_env
493+
};
494+
487495
compose_and_run(config, testfile,
488496
make_run_args(config, props, testfile),
489-
props.exec_env,
497+
env,
490498
config.run_lib_path, None)
491499
}
492500

src/libcore/rt/context.rs

+37-19
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use option::*;
1112
use super::stack::StackSegment;
1213
use libc::c_void;
1314
use cast::{transmute, transmute_mut_unsafe,
@@ -16,17 +17,30 @@ use cast::{transmute, transmute_mut_unsafe,
1617
// XXX: Registers is boxed so that it is 16-byte aligned, for storing
1718
// SSE regs. It would be marginally better not to do this. In C++ we
1819
// use an attribute on a struct.
19-
pub struct Context(~Registers);
20+
// XXX: It would be nice to define regs as `~Option<Registers>` since
21+
// the registers are sometimes empty, but the discriminant would
22+
// then misalign the regs again.
23+
pub struct Context {
24+
/// The context entry point, saved here for later destruction
25+
start: Option<~~fn()>,
26+
/// Hold the registers while the task or scheduler is suspended
27+
regs: ~Registers
28+
}
2029

2130
pub impl Context {
2231
fn empty() -> Context {
23-
Context(new_regs())
32+
Context {
33+
start: None,
34+
regs: new_regs()
35+
}
2436
}
2537

2638
/// Create a new context that will resume execution by running ~fn()
27-
/// # Safety Note
28-
/// The `start` closure must remain valid for the life of the Task
29-
fn new(start: &~fn(), stack: &mut StackSegment) -> Context {
39+
fn new(start: ~fn(), stack: &mut StackSegment) -> Context {
40+
// XXX: Putting main into a ~ so it's a thin pointer and can
41+
// be passed to the spawn function. Another unfortunate
42+
// allocation
43+
let start = ~start;
3044

3145
// The C-ABI function that is the task entry point
3246
extern fn task_start_wrapper(f: &~fn()) { (*f)() }
@@ -40,21 +54,29 @@ pub impl Context {
4054
// which we will then modify to call the given function when restored
4155
let mut regs = new_regs();
4256
unsafe {
43-
swap_registers(transmute_mut_region(&mut *regs),
44-
transmute_region(&*regs))
57+
swap_registers(transmute_mut_region(&mut *regs), transmute_region(&*regs))
4558
};
4659

4760
initialize_call_frame(&mut *regs, fp, argp, sp);
4861

49-
return Context(regs);
62+
return Context {
63+
start: Some(start),
64+
regs: regs
65+
}
5066
}
5167

68+
/* Switch contexts
69+
70+
Suspend the current execution context and resume another by
71+
saving the registers values of the executing thread to a Context
72+
then loading the registers from a previously saved Context.
73+
*/
5274
fn swap(out_context: &mut Context, in_context: &Context) {
5375
let out_regs: &mut Registers = match out_context {
54-
&Context(~ref mut r) => r
76+
&Context { regs: ~ref mut r, _ } => r
5577
};
5678
let in_regs: &Registers = match in_context {
57-
&Context(~ref r) => r
79+
&Context { regs: ~ref r, _ } => r
5880
};
5981

6082
unsafe { swap_registers(out_regs, in_regs) };
@@ -84,11 +106,10 @@ fn new_regs() -> ~Registers {
84106
}
85107

86108
#[cfg(target_arch = "x86")]
87-
fn initialize_call_frame(regs: &mut Registers,
88-
fptr: *c_void, arg: *c_void, sp: *mut uint) {
109+
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
89110

90111
let sp = align_down(sp);
91-
let sp = mut_offset(sp, -4); // XXX: -4 words? Needs this be done at all?
112+
let sp = mut_offset(sp, -4);
92113

93114
unsafe { *sp = arg as uint; }
94115
let sp = mut_offset(sp, -1);
@@ -108,8 +129,7 @@ type Registers = [uint * 22];
108129
fn new_regs() -> ~Registers { ~[0, .. 22] }
109130

110131
#[cfg(target_arch = "x86_64")]
111-
fn initialize_call_frame(regs: &mut Registers,
112-
fptr: *c_void, arg: *c_void, sp: *mut uint) {
132+
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
113133

114134
// Redefinitions from regs.h
115135
static RUSTRT_ARG0: uint = 3;
@@ -143,8 +163,7 @@ type Registers = [uint * 32];
143163
fn new_regs() -> ~Registers { ~[0, .. 32] }
144164

145165
#[cfg(target_arch = "arm")]
146-
fn initialize_call_frame(regs: &mut Registers,
147-
fptr: *c_void, arg: *c_void, sp: *mut uint) {
166+
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
148167
let sp = mut_offset(sp, -1);
149168

150169
// The final return address. 0 indicates the bottom of the stack
@@ -162,8 +181,7 @@ type Registers = [uint * 32];
162181
fn new_regs() -> ~Registers { ~[0, .. 32] }
163182

164183
#[cfg(target_arch = "mips")]
165-
fn initialize_call_frame(regs: &mut Registers,
166-
fptr: *c_void, arg: *c_void, sp: *mut uint) {
184+
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
167185
let sp = mut_offset(sp, -1);
168186

169187
// The final return address. 0 indicates the bottom of the stack

src/libcore/rt/io/file.rs

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use prelude::*;
12+
use super::super::sched::*;
13+
use super::super::rtio::*;
14+
use super::Stream;
15+
16+
pub struct FileStream;
17+
18+
pub impl FileStream {
19+
fn new(_path: Path) -> FileStream {
20+
fail!()
21+
}
22+
}
23+
24+
impl Stream for FileStream {
25+
fn read(&mut self, _buf: &mut [u8]) -> uint {
26+
fail!()
27+
}
28+
29+
fn eof(&mut self) -> bool {
30+
fail!()
31+
}
32+
33+
fn write(&mut self, _v: &const [u8]) {
34+
fail!()
35+
}
36+
}
37+
38+
#[test]
39+
#[ignore]
40+
fn super_simple_smoke_test_lets_go_read_some_files_and_have_a_good_time() {
41+
let message = "it's alright. have a good time";
42+
let filename = Path("test.txt");
43+
let mut outstream = FileStream::new(filename);
44+
outstream.write(message.to_bytes());
45+
}

src/libcore/rt/io/mod.rs

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use option::*;
12+
use comm::{GenericPort, GenericChan};
13+
14+
pub mod file;
15+
16+
// FIXME #5370 Strongly want this to be StreamError(&mut Stream)
17+
pub struct StreamError;
18+
19+
// XXX: Can't put doc comments on macros
20+
// Raised by `Stream` instances on error. Returning `true` from the handler
21+
// indicates that the `Stream` should continue, `false` that it should fail.
22+
condition! {
23+
stream_error: super::StreamError -> bool;
24+
}
25+
26+
pub trait Stream {
27+
/// Read bytes, up to the length of `buf` and place them in `buf`,
28+
/// returning the number of bytes read or an `IoError`. Reads
29+
/// 0 bytes on EOF.
30+
///
31+
/// # Failure
32+
///
33+
/// Raises the `reader_error` condition on error
34+
fn read(&mut self, buf: &mut [u8]) -> uint;
35+
36+
/// Return whether the Reader has reached the end of the stream
37+
fn eof(&mut self) -> bool;
38+
39+
/// Write the given buffer
40+
///
41+
/// # Failure
42+
///
43+
/// Raises the `writer_error` condition on error
44+
fn write(&mut self, v: &const [u8]);
45+
}

src/libcore/rt/mod.rs

+30-11
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,18 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use libc::c_char;
1112

1213
// Some basic logging
1314
macro_rules! rtdebug_ (
1415
($( $arg:expr),+) => ( {
1516
dumb_println(fmt!( $($arg),+ ));
1617

1718
fn dumb_println(s: &str) {
18-
use str::as_c_str;
19-
use libc::c_char;
20-
21-
extern {
22-
fn printf(s: *c_char);
23-
}
24-
25-
do as_c_str(s.to_str() + "\n") |s| {
26-
unsafe { printf(s); }
27-
}
19+
use io::WriterUtil;
20+
let dbg = ::libc::STDERR_FILENO as ::io::fd_t;
21+
dbg.write_str(s);
22+
dbg.write_str("\n");
2823
}
2924

3025
} )
@@ -36,13 +31,37 @@ macro_rules! rtdebug (
3631
)
3732

3833
mod sched;
39-
mod io;
34+
mod rtio;
35+
pub mod uvll;
4036
mod uvio;
37+
#[path = "uv/mod.rs"]
4138
mod uv;
39+
#[path = "io/mod.rs"]
40+
mod io;
4241
// FIXME #5248: The import in `sched` doesn't resolve unless this is pub!
4342
pub mod thread_local_storage;
4443
mod work_queue;
4544
mod stack;
4645
mod context;
4746
mod thread;
4847
pub mod env;
48+
49+
pub fn start(main: *u8, _argc: int, _argv: *c_char, _crate_map: *u8) -> int {
50+
use self::sched::{Scheduler, Task};
51+
use self::uvio::UvEventLoop;
52+
53+
let loop_ = ~UvEventLoop::new();
54+
let mut sched = ~Scheduler::new(loop_);
55+
let main_task = ~do Task::new(&mut sched.stack_pool) {
56+
// XXX: Can't call a C function pointer from Rust yet
57+
unsafe { rust_call_nullary_fn(main) };
58+
};
59+
sched.task_queue.push_back(main_task);
60+
sched.run();
61+
return 0;
62+
63+
extern {
64+
fn rust_call_nullary_fn(f: *u8);
65+
}
66+
}
67+
File renamed without changes.

0 commit comments

Comments
 (0)