Skip to content

Commit 41dcec2

Browse files
committed
auto merge of #7265 : brson/rust/io-upstream, r=brson
r? @graydon, @nikomatsakis, @pcwalton, or @catamorphism Sorry this is so huge, but it's been accumulating for about a month. There's lots of stuff here, mostly oriented toward enabling multithreaded scheduling and improving compatibility between the old and new runtimes. Adds task pinning so that we can create the 'platform thread' in servo. [Here](https://github.com/brson/rust/blob/e1555f9b5628af2b6c6ed344cad621399cb7684d/src/libstd/rt/mod.rs#L201) is the current runtime setup code. About half of this has already been reviewed.
2 parents 137d1fb + 413d51e commit 41dcec2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+5646
-2089
lines changed

src/libextra/test.rs

+4-13
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,6 @@ use std::u64;
3636
use std::uint;
3737
use std::vec;
3838

39-
pub mod rustrt {
40-
use std::libc::size_t;
41-
42-
#[abi = "cdecl"]
43-
pub extern {
44-
pub unsafe fn rust_sched_threads() -> size_t;
45-
}
46-
}
4739

4840
// The name of a test. By convention this follows the rules for rust
4941
// paths; i.e. it should be a series of identifiers separated by double
@@ -493,11 +485,10 @@ static SCHED_OVERCOMMIT : uint = 1;
493485
static SCHED_OVERCOMMIT : uint = 4u;
494486
495487
fn get_concurrency() -> uint {
496-
unsafe {
497-
let threads = rustrt::rust_sched_threads() as uint;
498-
if threads == 1 { 1 }
499-
else { threads * SCHED_OVERCOMMIT }
500-
}
488+
use std::rt;
489+
let threads = rt::util::default_sched_threads();
490+
if threads == 1 { 1 }
491+
else { threads * SCHED_OVERCOMMIT }
501492
}
502493
503494
#[allow(non_implicitly_copyable_typarams)]

src/libstd/at_vec.rs

+48-26
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,6 @@ use vec::{ImmutableVector, OwnedVector};
2222
/// Code for dealing with @-vectors. This is pretty incomplete, and
2323
/// contains a bunch of duplication from the code for ~-vectors.
2424
25-
pub mod rustrt {
26-
use libc;
27-
use vec;
28-
#[cfg(stage0)]
29-
use intrinsic::{TyDesc};
30-
#[cfg(not(stage0))]
31-
use unstable::intrinsics::{TyDesc};
32-
33-
#[abi = "cdecl"]
34-
#[link_name = "rustrt"]
35-
pub extern {
36-
pub unsafe fn vec_reserve_shared_actual(t: *TyDesc,
37-
v: **vec::raw::VecRepr,
38-
n: libc::size_t);
39-
}
40-
}
41-
4225
/// Returns the number of elements the vector can hold without reallocating
4326
#[inline]
4427
pub fn capacity<T>(v: @[T]) -> uint {
@@ -192,18 +175,17 @@ pub mod traits {
192175
pub mod traits {}
193176

194177
pub mod raw {
195-
use at_vec::{capacity, rustrt};
178+
use at_vec::capacity;
179+
use cast;
196180
use cast::{transmute, transmute_copy};
197181
use libc;
198182
use ptr;
199183
use sys;
200184
use uint;
201-
use unstable::intrinsics::{move_val_init};
185+
use unstable::intrinsics;
186+
use unstable::intrinsics::{move_val_init, TyDesc};
202187
use vec;
203-
#[cfg(stage0)]
204-
use intrinsic::{get_tydesc};
205-
#[cfg(not(stage0))]
206-
use unstable::intrinsics::{get_tydesc};
188+
use vec::UnboxedVecRepr;
207189

208190
pub type VecRepr = vec::raw::VecRepr;
209191
pub type SliceRepr = vec::raw::SliceRepr;
@@ -264,9 +246,49 @@ pub mod raw {
264246
pub unsafe fn reserve<T>(v: &mut @[T], n: uint) {
265247
// Only make the (slow) call into the runtime if we have to
266248
if capacity(*v) < n {
267-
let ptr: **VecRepr = transmute(v);
268-
rustrt::vec_reserve_shared_actual(get_tydesc::<T>(),
269-
ptr, n as libc::size_t);
249+
let ptr: *mut *mut VecRepr = transmute(v);
250+
let ty = intrinsics::get_tydesc::<T>();
251+
// XXX transmute shouldn't be necessary
252+
let ty = cast::transmute(ty);
253+
return reserve_raw(ty, ptr, n);
254+
}
255+
}
256+
257+
// Implementation detail. Shouldn't be public
258+
#[allow(missing_doc)]
259+
pub fn reserve_raw(ty: *TyDesc, ptr: *mut *mut VecRepr, n: uint) {
260+
261+
unsafe {
262+
let size_in_bytes = n * (*ty).size;
263+
if size_in_bytes > (**ptr).unboxed.alloc {
264+
let total_size = size_in_bytes + sys::size_of::<UnboxedVecRepr>();
265+
// XXX: UnboxedVecRepr has an extra u8 at the end
266+
let total_size = total_size - sys::size_of::<u8>();
267+
(*ptr) = local_realloc(*ptr as *(), total_size) as *mut VecRepr;
268+
(**ptr).unboxed.alloc = size_in_bytes;
269+
}
270+
}
271+
272+
fn local_realloc(ptr: *(), size: uint) -> *() {
273+
use rt;
274+
use rt::OldTaskContext;
275+
use rt::local::Local;
276+
use rt::task::Task;
277+
278+
if rt::context() == OldTaskContext {
279+
unsafe {
280+
return rust_local_realloc(ptr, size as libc::size_t);
281+
}
282+
283+
extern {
284+
#[fast_ffi]
285+
fn rust_local_realloc(ptr: *(), size: libc::size_t) -> *();
286+
}
287+
} else {
288+
do Local::borrow::<Task, *()> |task| {
289+
task.heap.realloc(ptr as *libc::c_void, size) as *()
290+
}
291+
}
270292
}
271293
}
272294

src/libstd/cleanup.rs

+15-102
Original file line numberDiff line numberDiff line change
@@ -10,105 +10,13 @@
1010

1111
#[doc(hidden)];
1212

13-
use libc::{c_char, intptr_t, uintptr_t};
13+
use libc::c_void;
1414
use ptr::{mut_null};
1515
use repr::BoxRepr;
1616
use cast::transmute;
1717
use unstable::intrinsics::TyDesc;
18-
#[cfg(not(test))] use unstable::lang::clear_task_borrow_list;
1918

20-
/**
21-
* Runtime structures
22-
*
23-
* NB: These must match the representation in the C++ runtime.
24-
*/
25-
26-
type TaskID = uintptr_t;
27-
28-
struct StackSegment { priv opaque: () }
29-
struct Scheduler { priv opaque: () }
30-
struct SchedulerLoop { priv opaque: () }
31-
struct Kernel { priv opaque: () }
32-
struct Env { priv opaque: () }
33-
struct AllocHeader { priv opaque: () }
34-
struct MemoryRegion { priv opaque: () }
35-
36-
#[cfg(target_arch="x86")]
37-
struct Registers {
38-
data: [u32, ..16]
39-
}
40-
41-
#[cfg(target_arch="arm")]
42-
#[cfg(target_arch="mips")]
43-
struct Registers {
44-
data: [u32, ..32]
45-
}
46-
47-
#[cfg(target_arch="x86")]
48-
#[cfg(target_arch="arm")]
49-
#[cfg(target_arch="mips")]
50-
struct Context {
51-
regs: Registers,
52-
next: *Context,
53-
pad: [u32, ..3]
54-
}
55-
56-
#[cfg(target_arch="x86_64")]
57-
struct Registers {
58-
data: [u64, ..22]
59-
}
60-
61-
#[cfg(target_arch="x86_64")]
62-
struct Context {
63-
regs: Registers,
64-
next: *Context,
65-
pad: uintptr_t
66-
}
67-
68-
struct BoxedRegion {
69-
env: *Env,
70-
backing_region: *MemoryRegion,
71-
live_allocs: *BoxRepr
72-
}
73-
74-
#[cfg(target_arch="x86")]
75-
#[cfg(target_arch="arm")]
76-
#[cfg(target_arch="mips")]
77-
struct Task {
78-
// Public fields
79-
refcount: intptr_t, // 0
80-
id: TaskID, // 4
81-
pad: [u32, ..2], // 8
82-
ctx: Context, // 16
83-
stack_segment: *StackSegment, // 96
84-
runtime_sp: uintptr_t, // 100
85-
scheduler: *Scheduler, // 104
86-
scheduler_loop: *SchedulerLoop, // 108
87-
88-
// Fields known only to the runtime
89-
kernel: *Kernel, // 112
90-
name: *c_char, // 116
91-
list_index: i32, // 120
92-
boxed_region: BoxedRegion // 128
93-
}
94-
95-
#[cfg(target_arch="x86_64")]
96-
struct Task {
97-
// Public fields
98-
refcount: intptr_t,
99-
id: TaskID,
100-
ctx: Context,
101-
stack_segment: *StackSegment,
102-
runtime_sp: uintptr_t,
103-
scheduler: *Scheduler,
104-
scheduler_loop: *SchedulerLoop,
105-
106-
// Fields known only to the runtime
107-
kernel: *Kernel,
108-
name: *c_char,
109-
list_index: i32,
110-
boxed_region: BoxedRegion
111-
}
19+
type DropGlue<'self> = &'self fn(**TyDesc, *c_void);
11220

11321
/*
11422
* Box annihilation
@@ -127,9 +35,9 @@ unsafe fn each_live_alloc(read_next_before: bool,
12735
//! Walks the internal list of allocations
12836
12937
use managed;
38+
use rt::local_heap;
13039

131-
let task: *Task = transmute(rustrt::rust_get_task());
132-
let box = (*task).boxed_region.live_allocs;
40+
let box = local_heap::live_allocs();
13341
let mut box: *mut BoxRepr = transmute(copy box);
13442
while box != mut_null() {
13543
let next_before = transmute(copy (*box).header.next);
@@ -151,7 +59,13 @@ unsafe fn each_live_alloc(read_next_before: bool,
15159

15260
#[cfg(unix)]
15361
fn debug_mem() -> bool {
154-
::rt::env::get().debug_mem
62+
use rt;
63+
use rt::OldTaskContext;
64+
// XXX: Need to port the environment struct to newsched
65+
match rt::context() {
66+
OldTaskContext => ::rt::env::get().debug_mem,
67+
_ => false
68+
}
15569
}
15670

15771
#[cfg(windows)]
@@ -173,13 +87,12 @@ unsafe fn call_drop_glue(tydesc: *TyDesc, data: *i8) {
17387
}
17488

17589
/// Destroys all managed memory (i.e. @ boxes) held by the current task.
176-
#[cfg(not(test))]
177-
#[lang="annihilate"]
17890
pub unsafe fn annihilate() {
179-
use unstable::lang::local_free;
91+
use rt::local_heap::local_free;
18092
use io::WriterUtil;
18193
use io;
18294
use libc;
95+
use rt::borrowck;
18396
use sys;
18497
use managed;
18598

@@ -191,7 +104,7 @@ pub unsafe fn annihilate() {
191104

192105
// Quick hack: we need to free this list upon task exit, and this
193106
// is a convenient place to do it.
194-
clear_task_borrow_list();
107+
borrowck::clear_task_borrow_list();
195108

196109
// Pass 1: Make all boxes immortal.
197110
//
@@ -213,7 +126,7 @@ pub unsafe fn annihilate() {
213126
// callback, as the original value may have been freed.
214127
for each_live_alloc(false) |box, uniq| {
215128
if !uniq {
216-
let tydesc = (*box).header.type_desc;
129+
let tydesc: *TyDesc = transmute(copy (*box).header.type_desc);
217130
let data = transmute(&(*box).data);
218131
call_drop_glue(tydesc, data);
219132
}

src/libstd/comm.rs

+25-15
Original file line numberDiff line numberDiff line change
@@ -220,48 +220,58 @@ impl<T: Send> Peekable<T> for PortSet<T> {
220220

221221
/// A channel that can be shared between many senders.
222222
pub struct SharedChan<T> {
223-
ch: Exclusive<pipesy::Chan<T>>
223+
inner: Either<Exclusive<pipesy::Chan<T>>, rtcomm::SharedChan<T>>
224224
}
225225

226226
impl<T: Send> SharedChan<T> {
227227
/// Converts a `chan` into a `shared_chan`.
228228
pub fn new(c: Chan<T>) -> SharedChan<T> {
229229
let Chan { inner } = c;
230230
let c = match inner {
231-
Left(c) => c,
232-
Right(_) => fail!("SharedChan not implemented")
231+
Left(c) => Left(exclusive(c)),
232+
Right(c) => Right(rtcomm::SharedChan::new(c))
233233
};
234-
SharedChan { ch: exclusive(c) }
234+
SharedChan { inner: c }
235235
}
236236
}
237237

238238
impl<T: Send> GenericChan<T> for SharedChan<T> {
239239
fn send(&self, x: T) {
240-
unsafe {
241-
let mut xx = Some(x);
242-
do self.ch.with_imm |chan| {
243-
let x = replace(&mut xx, None);
244-
chan.send(x.unwrap())
240+
match self.inner {
241+
Left(ref chan) => {
242+
unsafe {
243+
let mut xx = Some(x);
244+
do chan.with_imm |chan| {
245+
let x = replace(&mut xx, None);
246+
chan.send(x.unwrap())
247+
}
248+
}
245249
}
250+
Right(ref chan) => chan.send(x)
246251
}
247252
}
248253
}
249254

250255
impl<T: Send> GenericSmartChan<T> for SharedChan<T> {
251256
fn try_send(&self, x: T) -> bool {
252-
unsafe {
253-
let mut xx = Some(x);
254-
do self.ch.with_imm |chan| {
255-
let x = replace(&mut xx, None);
256-
chan.try_send(x.unwrap())
257+
match self.inner {
258+
Left(ref chan) => {
259+
unsafe {
260+
let mut xx = Some(x);
261+
do chan.with_imm |chan| {
262+
let x = replace(&mut xx, None);
263+
chan.try_send(x.unwrap())
264+
}
265+
}
257266
}
267+
Right(ref chan) => chan.try_send(x)
258268
}
259269
}
260270
}
261271

262272
impl<T: Send> ::clone::Clone for SharedChan<T> {
263273
fn clone(&self) -> SharedChan<T> {
264-
SharedChan { ch: self.ch.clone() }
274+
SharedChan { inner: self.inner.clone() }
265275
}
266276
}
267277

0 commit comments

Comments
 (0)