Skip to content

Commit ed03b9c

Browse files
committed
---
yaml --- r: 60575 b: refs/heads/auto c: 7abcc14 h: refs/heads/master i: 60573: 912f113 60571: 08a76b4 60567: bc2d41a 60559: cc516eb 60543: 960555c v: v3
1 parent 0e25915 commit ed03b9c

File tree

24 files changed

+521
-329
lines changed

24 files changed

+521
-329
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ refs/heads/try3: 9387340aab40a73e8424c48fd42f0c521a4875c0
1414
refs/tags/release-0.3.1: 495bae036dfe5ec6ceafd3312b4dca48741e845b
1515
refs/tags/release-0.4: e828ea2080499553b97dfe33b3f4d472b4562ad7
1616
refs/tags/release-0.5: 7e3bcfbf21278251ee936ad53e92e9b719702d73
17-
refs/heads/auto: d86a32bbb2ff79232bf3edc0f475062f45b6ea90
17+
refs/heads/auto: 7abcc142e5da1b87c59a1510fa87aefc4122bd6d
1818
refs/heads/servo: af82457af293e2a842ba6b7759b70288da276167
1919
refs/tags/release-0.6: b4ebcfa1812664df5e142f0134a5faea3918544c

branches/auto/src/libcore/logging.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,11 @@ pub fn log_type<T>(level: u32, object: &T) {
6666
}
6767

6868
fn newsched_log_str(msg: ~str) {
69+
use rt::task::Task;
70+
use rt::local::Local;
71+
6972
unsafe {
70-
match rt::local_services::unsafe_try_borrow_local_services() {
73+
match Local::try_unsafe_borrow::<Task>() {
7174
Some(local) => {
7275
// Use the available logger
7376
(*local).logger.log(Left(msg));

branches/auto/src/libcore/ptr.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use cast;
1414
use libc;
1515
use libc::{c_void, size_t};
16+
use option::{Option, Some, None};
1617
use sys;
1718

1819
#[cfg(not(test))] use cmp::{Eq, Ord};
@@ -209,6 +210,7 @@ pub unsafe fn array_each<T>(arr: **T, cb: &fn(*T)) {
209210
pub trait Ptr<T> {
210211
fn is_null(&const self) -> bool;
211212
fn is_not_null(&const self) -> bool;
213+
unsafe fn to_option(&const self) -> Option<&T>;
212214
fn offset(&self, count: uint) -> Self;
213215
}
214216

@@ -222,6 +224,23 @@ impl<T> Ptr<T> for *T {
222224
#[inline(always)]
223225
fn is_not_null(&const self) -> bool { is_not_null(*self) }
224226

227+
///
228+
/// Returns `None` if the pointer is null, or else returns the value wrapped
229+
/// in `Some`.
230+
///
231+
/// # Safety Notes
232+
///
233+
/// While this method is useful for null-safety, it is important to note
234+
/// that this is still an unsafe operation because the returned value could
235+
/// be pointing to invalid memory.
236+
///
237+
#[inline(always)]
238+
unsafe fn to_option(&const self) -> Option<&T> {
239+
if self.is_null() { None } else {
240+
Some(cast::transmute(*self))
241+
}
242+
}
243+
225244
/// Calculates the offset from a pointer.
226245
#[inline(always)]
227246
fn offset(&self, count: uint) -> *T { offset(*self, count) }
@@ -237,6 +256,23 @@ impl<T> Ptr<T> for *mut T {
237256
#[inline(always)]
238257
fn is_not_null(&const self) -> bool { is_not_null(*self) }
239258

259+
///
260+
/// Returns `None` if the pointer is null, or else returns the value wrapped
261+
/// in `Some`.
262+
///
263+
/// # Safety Notes
264+
///
265+
/// While this method is useful for null-safety, it is important to note
266+
/// that this is still an unsafe operation because the returned value could
267+
/// be pointing to invalid memory.
268+
///
269+
#[inline(always)]
270+
unsafe fn to_option(&const self) -> Option<&T> {
271+
if self.is_null() { None } else {
272+
Some(cast::transmute(*self))
273+
}
274+
}
275+
240276
/// Calculates the offset from a mutable pointer.
241277
#[inline(always)]
242278
fn offset(&self, count: uint) -> *mut T { mut_offset(*self, count) }
@@ -423,6 +459,21 @@ pub mod ptr_tests {
423459
assert!(mq.is_not_null());
424460
}
425461

462+
#[test]
463+
fn test_to_option() {
464+
let p: *int = null();
465+
// FIXME (#6641): Usage of unsafe methods in safe code doesn't cause an error.
466+
assert_eq!(p.to_option(), None);
467+
468+
let q: *int = &2;
469+
assert_eq!(q.to_option().unwrap(), &2); // FIXME (#6641)
470+
471+
let p: *mut int = mut_null();
472+
assert_eq!(p.to_option(), None); // FIXME (#6641)
473+
474+
let q: *mut int = &mut 2;
475+
assert_eq!(q.to_option().unwrap(), &2); // FIXME (#6641)
476+
}
426477

427478
#[test]
428479
fn test_ptr_array_each_with_len() {

branches/auto/src/libcore/rt/comm.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use cast;
2020
use util;
2121
use ops::Drop;
2222
use kinds::Owned;
23-
use rt::sched::Coroutine;
24-
use rt::local_sched;
23+
use rt::sched::{Scheduler, Coroutine};
24+
use rt::local::Local;
2525
use unstable::intrinsics::{atomic_xchg, atomic_load};
2626
use util::Void;
2727
use comm::{GenericChan, GenericSmartChan, GenericPort, Peekable};
@@ -127,7 +127,7 @@ impl<T> ChanOne<T> {
127127
task_as_state => {
128128
// Port is blocked. Wake it up.
129129
let recvr: ~Coroutine = cast::transmute(task_as_state);
130-
let sched = local_sched::take();
130+
let sched = Local::take::<Scheduler>();
131131
sched.schedule_task(recvr);
132132
}
133133
}
@@ -157,7 +157,7 @@ impl<T> PortOne<T> {
157157
// XXX: Optimize this to not require the two context switches when data is available
158158

159159
// Switch to the scheduler to put the ~Task into the Packet state.
160-
let sched = local_sched::take();
160+
let sched = Local::take::<Scheduler>();
161161
do sched.deschedule_running_task_and_then |task| {
162162
unsafe {
163163
// Atomically swap the task pointer into the Packet state, issuing
@@ -173,7 +173,7 @@ impl<T> PortOne<T> {
173173
STATE_ONE => {
174174
// Channel is closed. Switch back and check the data.
175175
let task: ~Coroutine = cast::transmute(task_as_state);
176-
let sched = local_sched::take();
176+
let sched = Local::take::<Scheduler>();
177177
sched.resume_task_immediately(task);
178178
}
179179
_ => util::unreachable()
@@ -239,7 +239,7 @@ impl<T> Drop for ChanOneHack<T> {
239239
// The port is blocked waiting for a message we will never send. Wake it.
240240
assert!((*this.packet()).payload.is_none());
241241
let recvr: ~Coroutine = cast::transmute(task_as_state);
242-
let sched = local_sched::take();
242+
let sched = Local::take::<Scheduler>();
243243
sched.schedule_task(recvr);
244244
}
245245
}

branches/auto/src/libcore/rt/context.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,7 @@ fn new_regs() -> ~Registers { ~([0, .. 32]) }
183183

184184
#[cfg(target_arch = "mips")]
185185
fn initialize_call_frame(regs: &mut Registers, fptr: *c_void, arg: *c_void, sp: *mut uint) {
186-
let sp = align_down(sp);
187-
// sp of mips o32 is 8-byte aligned
188-
let sp = mut_offset(sp, -2);
186+
let sp = mut_offset(sp, -1);
189187

190188
// The final return address. 0 indicates the bottom of the stack
191189
unsafe { *sp = 0; }

branches/auto/src/libcore/rt/io/net/tcp.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010

1111
use option::{Option, Some, None};
1212
use result::{Ok, Err};
13-
use rt::sched::local_sched::unsafe_borrow_io;
1413
use rt::io::net::ip::IpAddr;
1514
use rt::io::{Reader, Writer, Listener};
1615
use rt::io::{io_error, read_error, EndOfFile};
17-
use rt::rtio::{IoFactory,
16+
use rt::rtio::{IoFactory, IoFactoryObject,
1817
RtioTcpListener, RtioTcpListenerObject,
1918
RtioTcpStream, RtioTcpStreamObject};
19+
use rt::local::Local;
2020

2121
pub struct TcpStream {
2222
rtstream: ~RtioTcpStreamObject
@@ -32,7 +32,7 @@ impl TcpStream {
3232
pub fn connect(addr: IpAddr) -> Option<TcpStream> {
3333
let stream = unsafe {
3434
rtdebug!("borrowing io to connect");
35-
let io = unsafe_borrow_io();
35+
let io = Local::unsafe_borrow::<IoFactoryObject>();
3636
rtdebug!("about to connect");
3737
(*io).tcp_connect(addr)
3838
};
@@ -88,7 +88,10 @@ pub struct TcpListener {
8888

8989
impl TcpListener {
9090
pub fn bind(addr: IpAddr) -> Option<TcpListener> {
91-
let listener = unsafe { (*unsafe_borrow_io()).tcp_bind(addr) };
91+
let listener = unsafe {
92+
let io = Local::unsafe_borrow::<IoFactoryObject>();
93+
(*io).tcp_bind(addr)
94+
};
9295
match listener {
9396
Ok(l) => {
9497
Some(TcpListener {

branches/auto/src/libcore/rt/local.rs

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
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::{Option, Some, None};
12+
use rt::sched::Scheduler;
13+
use rt::task::Task;
14+
use rt::local_ptr;
15+
use rt::rtio::{EventLoop, IoFactoryObject};
16+
17+
pub trait Local {
18+
fn put(value: ~Self);
19+
fn take() -> ~Self;
20+
fn exists() -> bool;
21+
fn borrow(f: &fn(&mut Self));
22+
unsafe fn unsafe_borrow() -> *mut Self;
23+
unsafe fn try_unsafe_borrow() -> Option<*mut Self>;
24+
}
25+
26+
impl Local for Scheduler {
27+
fn put(value: ~Scheduler) { unsafe { local_ptr::put(value) }}
28+
fn take() -> ~Scheduler { unsafe { local_ptr::take() } }
29+
fn exists() -> bool { local_ptr::exists() }
30+
fn borrow(f: &fn(&mut Scheduler)) { unsafe { local_ptr::borrow(f) } }
31+
unsafe fn unsafe_borrow() -> *mut Scheduler { local_ptr::unsafe_borrow() }
32+
unsafe fn try_unsafe_borrow() -> Option<*mut Scheduler> { abort!("unimpl") }
33+
}
34+
35+
impl Local for Task {
36+
fn put(value: ~Task) { abort!("unimpl") }
37+
fn take() -> ~Task { abort!("unimpl") }
38+
fn exists() -> bool { abort!("unimpl") }
39+
fn borrow(f: &fn(&mut Task)) {
40+
do Local::borrow::<Scheduler> |sched| {
41+
match sched.current_task {
42+
Some(~ref mut task) => {
43+
f(&mut *task.task)
44+
}
45+
None => {
46+
abort!("no scheduler")
47+
}
48+
}
49+
}
50+
}
51+
unsafe fn unsafe_borrow() -> *mut Task {
52+
match (*Local::unsafe_borrow::<Scheduler>()).current_task {
53+
Some(~ref mut task) => {
54+
let s: *mut Task = &mut *task.task;
55+
return s;
56+
}
57+
None => {
58+
// Don't fail. Infinite recursion
59+
abort!("no scheduler")
60+
}
61+
}
62+
}
63+
unsafe fn try_unsafe_borrow() -> Option<*mut Task> {
64+
if Local::exists::<Scheduler>() {
65+
Some(Local::unsafe_borrow())
66+
} else {
67+
None
68+
}
69+
}
70+
}
71+
72+
// XXX: This formulation won't work once ~IoFactoryObject is a real trait pointer
73+
impl Local for IoFactoryObject {
74+
fn put(value: ~IoFactoryObject) { abort!("unimpl") }
75+
fn take() -> ~IoFactoryObject { abort!("unimpl") }
76+
fn exists() -> bool { abort!("unimpl") }
77+
fn borrow(f: &fn(&mut IoFactoryObject)) { abort!("unimpl") }
78+
unsafe fn unsafe_borrow() -> *mut IoFactoryObject {
79+
let sched = Local::unsafe_borrow::<Scheduler>();
80+
let io: *mut IoFactoryObject = (*sched).event_loop.io().unwrap();
81+
return io;
82+
}
83+
unsafe fn try_unsafe_borrow() -> Option<*mut IoFactoryObject> { abort!("unimpl") }
84+
}
85+
86+
#[cfg(test)]
87+
mod test {
88+
use rt::sched::Scheduler;
89+
use rt::uv::uvio::UvEventLoop;
90+
use super::*;
91+
92+
#[test]
93+
fn thread_local_scheduler_smoke_test() {
94+
let scheduler = ~UvEventLoop::new_scheduler();
95+
Local::put(scheduler);
96+
let _scheduler: ~Scheduler = Local::take();
97+
}
98+
99+
#[test]
100+
fn thread_local_scheduler_two_instances() {
101+
let scheduler = ~UvEventLoop::new_scheduler();
102+
Local::put(scheduler);
103+
let _scheduler: ~Scheduler = Local::take();
104+
let scheduler = ~UvEventLoop::new_scheduler();
105+
Local::put(scheduler);
106+
let _scheduler: ~Scheduler = Local::take();
107+
}
108+
109+
#[test]
110+
fn borrow_smoke_test() {
111+
let scheduler = ~UvEventLoop::new_scheduler();
112+
Local::put(scheduler);
113+
unsafe {
114+
let _scheduler: *mut Scheduler = Local::unsafe_borrow();
115+
}
116+
let _scheduler: ~Scheduler = Local::take();
117+
}
118+
}

0 commit comments

Comments
 (0)