Skip to content

Commit 676e029

Browse files
committed
core: Add rt mod and add the new scheduler code
1 parent a6bb4a0 commit 676e029

26 files changed

+2789
-253
lines changed

src/libcore/core.rc

+2-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,8 @@ pub mod unicode;
243243
#[path = "num/cmath.rs"]
244244
pub mod cmath;
245245
pub mod stackwalk;
246-
246+
#[path = "rt/mod.rs"]
247+
pub mod rt;
247248

248249
// A curious inner-module that's not exported that contains the binding
249250
// 'core' so that macro-expanded references to core::error and such

src/libcore/option.rs

+38
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,27 @@ pub pure fn get_ref<T>(opt: &r/Option<T>) -> &r/T {
130130
}
131131
}
132132
133+
pub pure fn get_mut_ref<T>(opt: &r/mut Option<T>) -> &r/mut T {
134+
/*!
135+
Gets a mutable reference to the value inside an option.
136+
137+
# Failure
138+
139+
Fails if the value equals `None`
140+
141+
# Safety note
142+
143+
In general, because this function may fail, its use is discouraged
144+
(calling `get` on `None` is akin to dereferencing a null pointer).
145+
Instead, prefer to use pattern matching and handle the `None`
146+
case explicitly.
147+
*/
148+
match *opt {
149+
Some(ref mut x) => x,
150+
None => fail!(~"option::get_mut_ref none")
151+
}
152+
}
153+
133154
#[inline(always)]
134155
pub pure fn map<T, U>(opt: &r/Option<T>, f: &fn(x: &r/T) -> U) -> Option<U> {
135156
//! Maps a `some` value by reference from one type to another
@@ -364,6 +385,23 @@ pub impl<T> Option<T> {
364385
#[inline(always)]
365386
pure fn get_ref(&self) -> &self/T { get_ref(self) }
366387
388+
/**
389+
Gets a mutable reference to the value inside an option.
390+
391+
# Failure
392+
393+
Fails if the value equals `None`
394+
395+
# Safety note
396+
397+
In general, because this function may fail, its use is discouraged
398+
(calling `get` on `None` is akin to dereferencing a null pointer).
399+
Instead, prefer to use pattern matching and handle the `None`
400+
case explicitly.
401+
*/
402+
#[inline(always)]
403+
pure fn get_mut_ref(&mut self) -> &self/mut T { get_mut_ref(self) }
404+
367405
/**
368406
* Gets the value out of an option without copying.
369407
*

src/libcore/rt/context.rs

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
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 super::stack::StackSegment;
12+
use libc::c_void;
13+
use cast::{transmute, transmute_mut_unsafe,
14+
transmute_region, transmute_mut_region};
15+
16+
// XXX: Registers is boxed so that it is 16-byte aligned, for storing
17+
// SSE regs. It would be marginally better not to do this. In C++ we
18+
// use an attribute on a struct.
19+
pub struct Context(~Registers);
20+
21+
pub impl Context {
22+
static fn empty() -> Context {
23+
Context(new_regs())
24+
}
25+
26+
/// 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+
static fn new(start: &~fn(), stack: &mut StackSegment) -> Context {
30+
31+
// The C-ABI function that is the task entry point
32+
extern fn task_start_wrapper(f: &~fn()) { (*f)() }
33+
34+
let fp: *c_void = task_start_wrapper as *c_void;
35+
let argp: *c_void = unsafe { transmute::<&~fn(), *c_void>(&*start) };
36+
let sp: *uint = stack.end();
37+
let sp: *mut uint = unsafe { transmute_mut_unsafe(sp) };
38+
39+
// Save and then immediately load the current context,
40+
// which we will then modify to call the given function when restored
41+
let mut regs = new_regs();
42+
unsafe {
43+
swap_registers(transmute_mut_region(&mut *regs),
44+
transmute_region(&*regs))
45+
};
46+
47+
initialize_call_frame(&mut *regs, fp, argp, sp);
48+
49+
return Context(regs);
50+
}
51+
52+
static fn swap(out_context: &mut Context, in_context: &Context) {
53+
let out_regs: &mut Registers = match out_context {
54+
&Context(~ref mut r) => r
55+
};
56+
let in_regs: &Registers = match in_context {
57+
&Context(~ref r) => r
58+
};
59+
60+
unsafe { swap_registers(out_regs, in_regs) };
61+
}
62+
}
63+
64+
extern {
65+
fn swap_registers(out_regs: *mut Registers, in_regs: *Registers);
66+
}
67+
68+
// Definitions of these registers are in rt/arch/x86_64/regs.h
69+
#[cfg(target_arch = "x86_64")]
70+
type Registers = [uint * 22];
71+
72+
#[cfg(target_arch = "x86_64")]
73+
fn new_regs() -> ~Registers { ~[0, .. 22] }
74+
75+
#[cfg(target_arch = "x86_64")]
76+
fn initialize_call_frame(regs: &mut Registers,
77+
fptr: *c_void, arg: *c_void, sp: *mut uint) {
78+
79+
// Redefinitions from regs.h
80+
const RUSTRT_ARG0: uint = 3;
81+
const RUSTRT_RSP: uint = 1;
82+
const RUSTRT_IP: uint = 8;
83+
const RUSTRT_RBP: uint = 2;
84+
85+
let sp = align_down(sp);
86+
let sp = mut_offset(sp, -1);
87+
88+
// The final return address. 0 indicates the bottom of the stack
89+
unsafe { *sp = 0; }
90+
91+
rtdebug!("creating call frame");
92+
rtdebug!("fptr %x", fptr as uint);
93+
rtdebug!("arg %x", arg as uint);
94+
rtdebug!("sp %x", sp as uint);
95+
96+
regs[RUSTRT_ARG0] = arg as uint;
97+
regs[RUSTRT_RSP] = sp as uint;
98+
regs[RUSTRT_IP] = fptr as uint;
99+
100+
// Last base pointer on the stack should be 0
101+
regs[RUSTRT_RBP] = 0;
102+
}
103+
104+
#[cfg(target_arch = "x86")]
105+
struct Registers {
106+
eax: u32, ebx: u32, ecx: u32, edx: u32,
107+
ebp: u32, esi: u32, edi: u32, esp: u32,
108+
cs: u16, ds: u16, ss: u16, es: u16, fs: u16, gs: u16,
109+
eflags: u32, eip: u32
110+
}
111+
112+
#[cfg(target_arch = "x86")]
113+
fn new_regs() -> ~Registers {
114+
~Registers {
115+
eax: 0, ebx: 0, ecx: 0, edx: 0,
116+
ebp: 0, esi: 0, edi: 0, esp: 0,
117+
cs: 0, ds: 0, ss: 0, es: 0, fs: 0, gs: 0,
118+
eflags: 0, eip: 0
119+
}
120+
}
121+
122+
#[cfg(target_arch = "x86")]
123+
fn initialize_call_frame(regs: &mut Registers,
124+
fptr: *c_void, arg: *c_void, sp: *mut uint) {
125+
126+
let sp = align_down(sp);
127+
let sp = mut_offset(sp, -4); // XXX: -4 words? Needs this be done at all?
128+
129+
unsafe { *sp = arg as uint; }
130+
let sp = mut_offset(sp, -1);
131+
unsafe { *sp = 0; } // The final return address
132+
133+
regs.esp = sp as u32;
134+
regs.eip = fptr as u32;
135+
136+
// Last base pointer on the stack is 0
137+
regs.ebp = 0;
138+
}
139+
140+
fn align_down(sp: *mut uint) -> *mut uint {
141+
unsafe {
142+
let sp = transmute::<*mut uint, uint>(sp);
143+
let sp = sp & !(16 - 1);
144+
transmute::<uint, *mut uint>(sp)
145+
}
146+
}
147+
148+
// XXX: ptr::offset is positive ints only
149+
#[inline(always)]
150+
pub pure fn mut_offset<T>(ptr: *mut T, count: int) -> *mut T {
151+
use core::sys::size_of;
152+
unsafe {
153+
(ptr as int + count * (size_of::<T>() as int)) as *mut T
154+
}
155+
}
156+

src/libcore/rt/io.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 result::*;
13+
14+
// XXX: ~object doesn't work currently so these are some placeholder
15+
// types to use instead
16+
pub type EventLoopObject = super::uvio::UvEventLoop;
17+
pub type IoFactoryObject = super::uvio::UvIoFactory;
18+
pub type StreamObject = super::uvio::UvStream;
19+
pub type TcpListenerObject = super::uvio::UvTcpListener;
20+
21+
pub trait EventLoop {
22+
fn run(&mut self);
23+
fn callback(&mut self, ~fn());
24+
/// The asynchronous I/O services. Not all event loops may provide one
25+
fn io(&mut self) -> Option<&self/mut IoFactoryObject>;
26+
}
27+
28+
pub trait IoFactory {
29+
fn connect(&mut self, addr: IpAddr) -> Option<~StreamObject>;
30+
fn bind(&mut self, addr: IpAddr) -> Option<~TcpListenerObject>;
31+
}
32+
33+
pub trait TcpListener {
34+
fn listen(&mut self) -> Option<~StreamObject>;
35+
}
36+
37+
pub trait Stream {
38+
fn read(&mut self, buf: &mut [u8]) -> Result<uint, ()>;
39+
fn write(&mut self, buf: &[u8]) -> Result<(), ()>;
40+
}
41+
42+
pub enum IpAddr {
43+
Ipv4(u8, u8, u8, u8, u16),
44+
Ipv6
45+
}

src/libcore/rt/mod.rs

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
// XXX: Missing some implementation for other architectures
12+
#[cfg(target_os = "linux")];
13+
#[cfg(target_os = "mac")];
14+
#[cfg(target_os = "win32")];
15+
16+
// Some basic logging
17+
macro_rules! rtdebug (
18+
($( $arg:expr),+) => ( {
19+
dumb_println(fmt!( $($arg),+ ));
20+
21+
fn dumb_println(s: &str) {
22+
use str::as_c_str;
23+
use libc::c_char;
24+
25+
extern {
26+
fn printf(s: *c_char);
27+
}
28+
29+
do as_c_str(s.to_str() + "\n") |s| {
30+
unsafe { printf(s); }
31+
}
32+
}
33+
34+
} )
35+
)
36+
37+
// An alternate version with no output, for turning off logging
38+
macro_rules! rtdebug_ (
39+
($( $arg:expr),+) => ( $(let _ = $arg)*; )
40+
)
41+
42+
mod sched;
43+
mod io;
44+
mod uvio;
45+
mod uv;
46+
// FIXME #5248: The import in `sched` doesn't resolve unless this is pub!
47+
pub mod thread_local_storage;
48+
mod work_queue;
49+
mod stack;
50+
mod context;
51+
mod thread;

0 commit comments

Comments
 (0)