From f03c9bd08cde6c83306d91bb07c4810b8b8f13ba Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 18 May 2013 00:44:47 -0700 Subject: [PATCH 01/15] core::rt: Rename WorkQueue methods, remove extra push method --- src/libcore/rt/sched.rs | 4 ++-- src/libcore/rt/work_queue.rs | 16 ++++++---------- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 7fd40fb329f47..7099ae865e934 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -112,7 +112,7 @@ pub impl Scheduler { /// to run it later. Always use this instead of pushing to the work queue /// directly. fn enqueue_task(&mut self, task: ~Coroutine) { - self.work_queue.push_front(task); + self.work_queue.push(task); self.event_loop.callback(resume_task_from_queue); fn resume_task_from_queue() { @@ -129,7 +129,7 @@ pub impl Scheduler { rtdebug!("looking in work queue for task to schedule"); let mut this = self; - match this.work_queue.pop_front() { + match this.work_queue.pop() { Some(task) => { rtdebug!("resuming task from work queue"); this.resume_task_immediately(task); diff --git a/src/libcore/rt/work_queue.rs b/src/libcore/rt/work_queue.rs index f82b5847ef2b8..7011b4ebc1040 100644 --- a/src/libcore/rt/work_queue.rs +++ b/src/libcore/rt/work_queue.rs @@ -23,25 +23,21 @@ pub impl WorkQueue { } } - fn push_back(&mut self, value: T) { - self.queue.push(value) + fn push(&mut self, value: T) { + self.queue.unshift(value) } - fn pop_back(&mut self) -> Option { + fn pop(&mut self) -> Option { if !self.queue.is_empty() { - Some(self.queue.pop()) + Some(self.queue.shift()) } else { None } } - fn push_front(&mut self, value: T) { - self.queue.unshift(value) - } - - fn pop_front(&mut self) -> Option { + fn steal(&mut self) -> Option { if !self.queue.is_empty() { - Some(self.queue.shift()) + Some(self.queue.pop()) } else { None } From ee06ed2bfd233b57c5989696bb723bddf6569622 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 18 May 2013 01:07:16 -0700 Subject: [PATCH 02/15] core::rt: Put a lock on the work queue --- src/libcore/rt/work_queue.rs | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/libcore/rt/work_queue.rs b/src/libcore/rt/work_queue.rs index 7011b4ebc1040..31f73cd09b54d 100644 --- a/src/libcore/rt/work_queue.rs +++ b/src/libcore/rt/work_queue.rs @@ -11,39 +11,48 @@ use container::Container; use option::*; use vec::OwnedVector; +use unstable::sync::{Exclusive, exclusive}; +use cell::Cell; +use kinds::Owned; pub struct WorkQueue { - priv queue: ~[T] + // XXX: Another mystery bug fixed by boxing this lock + priv queue: ~Exclusive<~[T]> } -pub impl WorkQueue { +pub impl WorkQueue { fn new() -> WorkQueue { WorkQueue { - queue: ~[] + queue: ~exclusive(~[]) } } fn push(&mut self, value: T) { - self.queue.unshift(value) + let value = Cell(value); + self.queue.with(|q| q.unshift(value.take()) ); } fn pop(&mut self) -> Option { - if !self.queue.is_empty() { - Some(self.queue.shift()) - } else { - None + do self.queue.with |q| { + if !q.is_empty() { + Some(q.shift()) + } else { + None + } } } fn steal(&mut self) -> Option { - if !self.queue.is_empty() { - Some(self.queue.pop()) - } else { - None + do self.queue.with |q| { + if !q.is_empty() { + Some(q.pop()) + } else { + None + } } } fn is_empty(&self) -> bool { - return self.queue.is_empty(); + self.queue.with_imm(|q| q.is_empty() ) } } From d2a1378ed8dd3693511836fdee656d8f79089a73 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 18 May 2013 01:38:44 -0700 Subject: [PATCH 03/15] core::rt: Add MessageQueue type This is the queue used to send messages to Schedulers --- src/libcore/rt/message_queue.rs | 44 +++++++++++++++++++++++++++++++++ src/libcore/rt/mod.rs | 5 +++- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/libcore/rt/message_queue.rs diff --git a/src/libcore/rt/message_queue.rs b/src/libcore/rt/message_queue.rs new file mode 100644 index 0000000000000..014e71d3de689 --- /dev/null +++ b/src/libcore/rt/message_queue.rs @@ -0,0 +1,44 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use container::Container; +use kinds::Owned; +use vec::OwnedVector; +use cell::Cell; +use option::*; +use unstable::sync::{Exclusive, exclusive}; + +pub struct MessageQueue { + // XXX: Another mystery bug fixed by boxing this lock + priv queue: ~Exclusive<~[T]> +} + +impl MessageQueue { + pub fn new() -> MessageQueue { + MessageQueue { + queue: ~exclusive(~[]) + } + } + + pub fn push(&mut self, value: T) { + let value = Cell(value); + self.queue.with(|q| q.push(value.take()) ); + } + + pub fn pop(&mut self) -> Option { + do self.queue.with |q| { + if !q.is_empty() { + Some(q.shift()) + } else { + None + } + } + } +} \ No newline at end of file diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index 4dce9da505b5f..3d51345336f3b 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -91,9 +91,12 @@ pub mod uv; /// Bindings to pthread/windows thread-local storage. pub mod thread_local_storage; -/// A parallel work-stealing dequeue. +/// A parallel work-stealing deque. mod work_queue; +/// A parallel queue. +mod message_queue; + /// Stack segments and caching. mod stack; From fa18a861fbd934c295990e59b20c7a0498b88f08 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sat, 18 May 2013 01:53:40 -0700 Subject: [PATCH 04/15] core::rt: Queues MessageQueue and WorkQueue are cloneable --- src/libcore/rt/message_queue.rs | 11 ++++++++++- src/libcore/rt/work_queue.rs | 9 +++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/libcore/rt/message_queue.rs b/src/libcore/rt/message_queue.rs index 014e71d3de689..eaab9288ac8d0 100644 --- a/src/libcore/rt/message_queue.rs +++ b/src/libcore/rt/message_queue.rs @@ -14,6 +14,7 @@ use vec::OwnedVector; use cell::Cell; use option::*; use unstable::sync::{Exclusive, exclusive}; +use clone::Clone; pub struct MessageQueue { // XXX: Another mystery bug fixed by boxing this lock @@ -41,4 +42,12 @@ impl MessageQueue { } } } -} \ No newline at end of file +} + +impl Clone for MessageQueue { + fn clone(&self) -> MessageQueue { + MessageQueue { + queue: self.queue.clone() + } + } +} diff --git a/src/libcore/rt/work_queue.rs b/src/libcore/rt/work_queue.rs index 31f73cd09b54d..e9eb663392b24 100644 --- a/src/libcore/rt/work_queue.rs +++ b/src/libcore/rt/work_queue.rs @@ -14,6 +14,7 @@ use vec::OwnedVector; use unstable::sync::{Exclusive, exclusive}; use cell::Cell; use kinds::Owned; +use clone::Clone; pub struct WorkQueue { // XXX: Another mystery bug fixed by boxing this lock @@ -56,3 +57,11 @@ pub impl WorkQueue { self.queue.with_imm(|q| q.is_empty() ) } } + +impl Clone for WorkQueue { + fn clone(&self) -> WorkQueue { + WorkQueue { + queue: self.queue.clone() + } + } +} From b0722c55f8205a43a0b8124ca179dada766c23ed Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 19 May 2013 01:04:01 -0700 Subject: [PATCH 05/15] core:rt:: Rename LocalServices to Task --- src/libcore/logging.rs | 2 +- src/libcore/rt/mod.rs | 16 ++----- src/libcore/rt/sched.rs | 14 +++--- src/libcore/rt/{local_services.rs => task.rs} | 47 +++++++++---------- src/libcore/rt/test.rs | 38 +++++++-------- src/libcore/sys.rs | 6 +-- src/libcore/task/local_data_priv.rs | 8 ++-- src/libcore/task/mod.rs | 4 +- src/libcore/unstable/lang.rs | 10 ++-- 9 files changed, 67 insertions(+), 78 deletions(-) rename src/libcore/rt/{local_services.rs => task.rs} (83%) diff --git a/src/libcore/logging.rs b/src/libcore/logging.rs index e137c5d3034d2..16a80866cf1ab 100644 --- a/src/libcore/logging.rs +++ b/src/libcore/logging.rs @@ -67,7 +67,7 @@ pub fn log_type(level: u32, object: &T) { fn newsched_log_str(msg: ~str) { unsafe { - match rt::local_services::unsafe_try_borrow_local_services() { + match rt::task::unsafe_try_borrow_local_task() { Some(local) => { // Use the available logger (*local).logger.log(Left(msg)); diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index 3d51345336f3b..208a6de46e822 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -31,14 +31,8 @@ access to the global heap. Unlike most of `rt` the global heap is truly a global resource and generally operates independently of the rest of the runtime. -All other runtime features are 'local', either thread-local or -task-local. Those critical to the functioning of the language are -defined in the module `local_services`. Local services are those which -are expected to be available to Rust code generally but rely on -thread- or task-local state. These currently include the local heap, +All other runtime features are task-local, including the local heap, the garbage collector, local storage, logging and the stack unwinder. -Local services are primarily implemented for tasks, but may also -be implemented for use outside of tasks. The relationship between `rt` and the rest of the core library is not entirely clear yet and some modules will be moving into or @@ -67,7 +61,10 @@ use ptr::Ptr; /// The global (exchange) heap. pub mod global_heap; -/// The Scheduler and Coroutine types. +/// Implementations of language-critical runtime features like @. +pub mod task; + +/// The coroutine task scheduler, built on the `io` event loop. mod sched; /// Thread-local access to the current Scheduler. @@ -77,9 +74,6 @@ pub mod local_sched; #[path = "io/mod.rs"] pub mod io; -/// Thread-local implementations of language-critical runtime features like @. -pub mod local_services; - /// The EventLoop and internal synchronous I/O interface. mod rtio; diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 7099ae865e934..4b2165b4d2ae3 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -16,7 +16,7 @@ use super::work_queue::WorkQueue; use super::stack::{StackPool, StackSegment}; use super::rtio::{EventLoop, EventLoopObject}; use super::context::Context; -use super::local_services::LocalServices; +use super::task::Task; use cell::Cell; // A more convenient name for external callers, e.g. `local_sched::take()` @@ -350,16 +350,16 @@ pub struct Coroutine { /// the task is dead priv saved_context: Context, /// The heap, GC, unwinding, local storage, logging - local_services: LocalServices + task: Task } pub impl Coroutine { fn new(stack_pool: &mut StackPool, start: ~fn()) -> Coroutine { - Coroutine::with_local(stack_pool, LocalServices::new(), start) + Coroutine::with_task(stack_pool, Task::new(), start) } - fn with_local(stack_pool: &mut StackPool, - local_services: LocalServices, + fn with_task(stack_pool: &mut StackPool, + task: Task, start: ~fn()) -> Coroutine { let start = Coroutine::build_start_wrapper(start); let mut stack = stack_pool.take_segment(MIN_STACK_SIZE); @@ -368,7 +368,7 @@ pub impl Coroutine { return Coroutine { current_stack_segment: stack, saved_context: initial_context, - local_services: local_services + task: task }; } @@ -385,7 +385,7 @@ pub impl Coroutine { let sched = local_sched::unsafe_borrow(); let task = (*sched).current_task.get_mut_ref(); // FIXME #6141: shouldn't neet to put `start()` in another closure - task.local_services.run(||start()); + task.task.run(||start()); } let sched = local_sched::take(); diff --git a/src/libcore/rt/local_services.rs b/src/libcore/rt/task.rs similarity index 83% rename from src/libcore/rt/local_services.rs rename to src/libcore/rt/task.rs index 8d6873be8cd56..c3832d1338ad0 100644 --- a/src/libcore/rt/local_services.rs +++ b/src/libcore/rt/task.rs @@ -13,11 +13,6 @@ //! local storage, and logging. Even a 'freestanding' Rust would likely want //! to implement this. -//! Local services may exist in at least three different contexts: -//! when running as a task, when running in the scheduler's context, -//! or when running outside of a scheduler but with local services -//! (freestanding rust with local services?). - use prelude::*; use libc::{c_void, uintptr_t}; use cast::transmute; @@ -25,7 +20,7 @@ use super::sched::local_sched; use super::local_heap::LocalHeap; use rt::logging::StdErrLogger; -pub struct LocalServices { +pub struct Task { heap: LocalHeap, gc: GarbageCollector, storage: LocalStorage, @@ -41,9 +36,9 @@ pub struct Unwinder { unwinding: bool, } -impl LocalServices { - pub fn new() -> LocalServices { - LocalServices { +impl Task { + pub fn new() -> Task { + Task { heap: LocalHeap::new(), gc: GarbageCollector, storage: LocalStorage(ptr::null(), None), @@ -53,8 +48,8 @@ impl LocalServices { } } - pub fn without_unwinding() -> LocalServices { - LocalServices { + pub fn without_unwinding() -> Task { + Task { heap: LocalHeap::new(), gc: GarbageCollector, storage: LocalStorage(ptr::null(), None), @@ -66,9 +61,9 @@ impl LocalServices { pub fn run(&mut self, f: &fn()) { // This is just an assertion that `run` was called unsafely - // and this instance of LocalServices is still accessible. - do borrow_local_services |sched| { - assert!(ptr::ref_eq(sched, self)); + // and this instance of Task is still accessible. + do borrow_local_task |task| { + assert!(ptr::ref_eq(task, self)); } match self.unwinder { @@ -86,14 +81,14 @@ impl LocalServices { /// Must be called manually before finalization to clean up /// thread-local resources. Some of the routines here expect - /// LocalServices to be available recursively so this must be - /// called unsafely, without removing LocalServices from + /// Task to be available recursively so this must be + /// called unsafely, without removing Task from /// thread-local-storage. fn destroy(&mut self) { // This is just an assertion that `destroy` was called unsafely - // and this instance of LocalServices is still accessible. - do borrow_local_services |sched| { - assert!(ptr::ref_eq(sched, self)); + // and this instance of Task is still accessible. + do borrow_local_task |task| { + assert!(ptr::ref_eq(task, self)); } match self.storage { LocalStorage(ptr, Some(ref dtor)) => { @@ -105,7 +100,7 @@ impl LocalServices { } } -impl Drop for LocalServices { +impl Drop for Task { fn finalize(&self) { assert!(self.destroyed) } } @@ -156,11 +151,11 @@ impl Unwinder { /// Borrow a pointer to the installed local services. /// Fails (likely aborting the process) if local services are not available. -pub fn borrow_local_services(f: &fn(&mut LocalServices)) { +pub fn borrow_local_task(f: &fn(&mut Task)) { do local_sched::borrow |sched| { match sched.current_task { Some(~ref mut task) => { - f(&mut task.local_services) + f(&mut task.task) } None => { fail!("no local services for schedulers yet") @@ -169,10 +164,10 @@ pub fn borrow_local_services(f: &fn(&mut LocalServices)) { } } -pub unsafe fn unsafe_borrow_local_services() -> *mut LocalServices { +pub unsafe fn unsafe_borrow_local_task() -> *mut Task { match (*local_sched::unsafe_borrow()).current_task { Some(~ref mut task) => { - let s: *mut LocalServices = &mut task.local_services; + let s: *mut Task = &mut task.task; return s; } None => { @@ -182,9 +177,9 @@ pub unsafe fn unsafe_borrow_local_services() -> *mut LocalServices { } } -pub unsafe fn unsafe_try_borrow_local_services() -> Option<*mut LocalServices> { +pub unsafe fn unsafe_try_borrow_local_task() -> Option<*mut Task> { if local_sched::exists() { - Some(unsafe_borrow_local_services()) + Some(unsafe_borrow_local_task()) } else { None } diff --git a/src/libcore/rt/test.rs b/src/libcore/rt/test.rs index d739d0110ba35..c3e52594d6e77 100644 --- a/src/libcore/rt/test.rs +++ b/src/libcore/rt/test.rs @@ -13,7 +13,7 @@ use option::*; use cell::Cell; use result::{Result, Ok, Err}; use super::io::net::ip::{IpAddr, Ipv4}; -use rt::local_services::LocalServices; +use rt::task::Task; use rt::thread::Thread; /// Creates a new scheduler in a new thread and runs a task in it, @@ -28,9 +28,9 @@ pub fn run_in_newsched_task(f: ~fn()) { do run_in_bare_thread { let mut sched = ~UvEventLoop::new_scheduler(); - let task = ~Coroutine::with_local(&mut sched.stack_pool, - LocalServices::without_unwinding(), - f.take()); + let task = ~Coroutine::with_task(&mut sched.stack_pool, + Task::without_unwinding(), + f.take()); sched.enqueue_task(task); sched.run(); } @@ -41,9 +41,9 @@ pub fn spawntask(f: ~fn()) { use super::sched::*; let mut sched = local_sched::take(); - let task = ~Coroutine::with_local(&mut sched.stack_pool, - LocalServices::without_unwinding(), - f); + let task = ~Coroutine::with_task(&mut sched.stack_pool, + Task::without_unwinding(), + f); do sched.switch_running_tasks_and_then(task) |task| { let task = Cell(task); let sched = local_sched::take(); @@ -56,9 +56,9 @@ pub fn spawntask_immediately(f: ~fn()) { use super::sched::*; let mut sched = local_sched::take(); - let task = ~Coroutine::with_local(&mut sched.stack_pool, - LocalServices::without_unwinding(), - f); + let task = ~Coroutine::with_task(&mut sched.stack_pool, + Task::without_unwinding(), + f); do sched.switch_running_tasks_and_then(task) |task| { let task = Cell(task); do local_sched::borrow |sched| { @@ -72,9 +72,9 @@ pub fn spawntask_later(f: ~fn()) { use super::sched::*; let mut sched = local_sched::take(); - let task = ~Coroutine::with_local(&mut sched.stack_pool, - LocalServices::without_unwinding(), - f); + let task = ~Coroutine::with_task(&mut sched.stack_pool, + Task::without_unwinding(), + f); sched.enqueue_task(task); local_sched::put(sched); @@ -89,9 +89,9 @@ pub fn spawntask_random(f: ~fn()) { let run_now: bool = Rand::rand(&mut rng); let mut sched = local_sched::take(); - let task = ~Coroutine::with_local(&mut sched.stack_pool, - LocalServices::without_unwinding(), - f); + let task = ~Coroutine::with_task(&mut sched.stack_pool, + Task::without_unwinding(), + f); if run_now { do sched.switch_running_tasks_and_then(task) |task| { @@ -155,9 +155,9 @@ pub fn spawntask_thread(f: ~fn()) -> Thread { let f = Cell(f); let thread = do Thread::start { let mut sched = ~UvEventLoop::new_scheduler(); - let task = ~Coroutine::with_local(&mut sched.stack_pool, - LocalServices::without_unwinding(), - f.take()); + let task = ~Coroutine::with_task(&mut sched.stack_pool, + Task::without_unwinding(), + f.take()); sched.enqueue_task(task); sched.run(); }; diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index fc57cf40d1e01..c21ce5213142b 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -204,7 +204,7 @@ impl FailWithCause for &'static str { pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { use option::Option; use rt::{context, OldTaskContext, TaskContext}; - use rt::local_services::{unsafe_borrow_local_services, Unwinder}; + use rt::task::{unsafe_borrow_local_task, Unwinder}; let context = context(); match context { @@ -233,8 +233,8 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { gc::cleanup_stack_for_failure(); - let local_services = unsafe_borrow_local_services(); - let unwinder: &mut Option = &mut (*local_services).unwinder; + let task = unsafe_borrow_local_task(); + let unwinder: &mut Option = &mut (*task).unwinder; match *unwinder { Some(ref mut unwinder) => unwinder.begin_unwind(), None => abort!("failure without unwinder. aborting process") diff --git a/src/libcore/task/local_data_priv.rs b/src/libcore/task/local_data_priv.rs index be4e639e94c32..6871dd3aecd88 100644 --- a/src/libcore/task/local_data_priv.rs +++ b/src/libcore/task/local_data_priv.rs @@ -18,7 +18,7 @@ use task::rt; use local_data::LocalDataKey; use super::rt::rust_task; -use rt::local_services::LocalStorage; +use rt::task::LocalStorage; pub enum Handle { OldHandle(*rust_task), @@ -28,15 +28,15 @@ pub enum Handle { impl Handle { pub fn new() -> Handle { use rt::{context, OldTaskContext}; - use rt::local_services::unsafe_borrow_local_services; + use rt::task::unsafe_borrow_local_task; unsafe { match context() { OldTaskContext => { OldHandle(rt::rust_get_task()) } _ => { - let local_services = unsafe_borrow_local_services(); - NewHandle(&mut (*local_services).storage) + let task = unsafe_borrow_local_task(); + NewHandle(&mut (*task).storage) } } } diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index f06b5abf04f01..372a9f6defaff 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -504,7 +504,7 @@ pub fn failing() -> bool { //! True if the running task has failed use rt::{context, OldTaskContext}; - use rt::local_services::borrow_local_services; + use rt::task::borrow_local_task; match context() { OldTaskContext => { @@ -514,7 +514,7 @@ pub fn failing() -> bool { } _ => { let mut unwinding = false; - do borrow_local_services |local| { + do borrow_local_task |local| { unwinding = match local.unwinder { Some(unwinder) => { unwinder.unwinding diff --git a/src/libcore/unstable/lang.rs b/src/libcore/unstable/lang.rs index 1ae657849c424..1efe5d0d1a41d 100644 --- a/src/libcore/unstable/lang.rs +++ b/src/libcore/unstable/lang.rs @@ -17,7 +17,7 @@ use managed::raw::BoxRepr; use str; use sys; use rt::{context, OldTaskContext}; -use rt::local_services::borrow_local_services; +use rt::task::borrow_local_task; use option::{Option, Some, None}; use io; use rt::global_heap; @@ -243,8 +243,8 @@ pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { } _ => { let mut alloc = ::ptr::null(); - do borrow_local_services |srv| { - alloc = srv.heap.alloc(td as *c_void, size as uint) as *c_char; + do borrow_local_task |task| { + alloc = task.heap.alloc(td as *c_void, size as uint) as *c_char; } return alloc; } @@ -261,8 +261,8 @@ pub unsafe fn local_free(ptr: *c_char) { rustrt::rust_upcall_free_noswitch(ptr); } _ => { - do borrow_local_services |srv| { - srv.heap.free(ptr as *c_void); + do borrow_local_task |task| { + task.heap.free(ptr as *c_void); } } } From 43c6f32ece85a7df86ee041771a54c097dae6a13 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 19 May 2013 01:13:53 -0700 Subject: [PATCH 06/15] core::rt: Add Local trait --- src/libcore/rt/local.rs | 17 +++++++++++++++++ src/libcore/rt/mod.rs | 4 ++++ 2 files changed, 21 insertions(+) create mode 100644 src/libcore/rt/local.rs diff --git a/src/libcore/rt/local.rs b/src/libcore/rt/local.rs new file mode 100644 index 0000000000000..ec54bcb99dd7f --- /dev/null +++ b/src/libcore/rt/local.rs @@ -0,0 +1,17 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub trait Local { + fn put_local(value: ~Self); + fn take_local() -> ~Self; + fn exists() -> bool; + fn borrow(f: &fn(&mut Self)); + fn unsafe_borrow() -> *mut Self; +} diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index 208a6de46e822..37ac6ad3365c3 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -81,6 +81,10 @@ mod rtio; #[path = "uv/mod.rs"] pub mod uv; +/// The Local trait for types that are accessible via thread-local +/// or task-local storage. +pub mod local; + // FIXME #5248: The import in `sched` doesn't resolve unless this is pub! /// Bindings to pthread/windows thread-local storage. pub mod thread_local_storage; From f59fcd5d5f7ba94f7c705eb2c081760dd2213067 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 19 May 2013 14:05:20 -0700 Subject: [PATCH 07/15] core::rt: Store Task as a ~ pointer --- src/libcore/rt/sched.rs | 6 +++--- src/libcore/rt/task.rs | 4 ++-- src/libcore/rt/test.rs | 12 ++++++------ 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 4b2165b4d2ae3..3abbb1f79e596 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -350,16 +350,16 @@ pub struct Coroutine { /// the task is dead priv saved_context: Context, /// The heap, GC, unwinding, local storage, logging - task: Task + task: ~Task } pub impl Coroutine { fn new(stack_pool: &mut StackPool, start: ~fn()) -> Coroutine { - Coroutine::with_task(stack_pool, Task::new(), start) + Coroutine::with_task(stack_pool, ~Task::new(), start) } fn with_task(stack_pool: &mut StackPool, - task: Task, + task: ~Task, start: ~fn()) -> Coroutine { let start = Coroutine::build_start_wrapper(start); let mut stack = stack_pool.take_segment(MIN_STACK_SIZE); diff --git a/src/libcore/rt/task.rs b/src/libcore/rt/task.rs index c3832d1338ad0..65b7c885b5735 100644 --- a/src/libcore/rt/task.rs +++ b/src/libcore/rt/task.rs @@ -155,7 +155,7 @@ pub fn borrow_local_task(f: &fn(&mut Task)) { do local_sched::borrow |sched| { match sched.current_task { Some(~ref mut task) => { - f(&mut task.task) + f(&mut *task.task) } None => { fail!("no local services for schedulers yet") @@ -167,7 +167,7 @@ pub fn borrow_local_task(f: &fn(&mut Task)) { pub unsafe fn unsafe_borrow_local_task() -> *mut Task { match (*local_sched::unsafe_borrow()).current_task { Some(~ref mut task) => { - let s: *mut Task = &mut task.task; + let s: *mut Task = &mut *task.task; return s; } None => { diff --git a/src/libcore/rt/test.rs b/src/libcore/rt/test.rs index c3e52594d6e77..66993041752cf 100644 --- a/src/libcore/rt/test.rs +++ b/src/libcore/rt/test.rs @@ -29,7 +29,7 @@ pub fn run_in_newsched_task(f: ~fn()) { do run_in_bare_thread { let mut sched = ~UvEventLoop::new_scheduler(); let task = ~Coroutine::with_task(&mut sched.stack_pool, - Task::without_unwinding(), + ~Task::without_unwinding(), f.take()); sched.enqueue_task(task); sched.run(); @@ -42,7 +42,7 @@ pub fn spawntask(f: ~fn()) { let mut sched = local_sched::take(); let task = ~Coroutine::with_task(&mut sched.stack_pool, - Task::without_unwinding(), + ~Task::without_unwinding(), f); do sched.switch_running_tasks_and_then(task) |task| { let task = Cell(task); @@ -57,7 +57,7 @@ pub fn spawntask_immediately(f: ~fn()) { let mut sched = local_sched::take(); let task = ~Coroutine::with_task(&mut sched.stack_pool, - Task::without_unwinding(), + ~Task::without_unwinding(), f); do sched.switch_running_tasks_and_then(task) |task| { let task = Cell(task); @@ -73,7 +73,7 @@ pub fn spawntask_later(f: ~fn()) { let mut sched = local_sched::take(); let task = ~Coroutine::with_task(&mut sched.stack_pool, - Task::without_unwinding(), + ~Task::without_unwinding(), f); sched.enqueue_task(task); @@ -90,7 +90,7 @@ pub fn spawntask_random(f: ~fn()) { let mut sched = local_sched::take(); let task = ~Coroutine::with_task(&mut sched.stack_pool, - Task::without_unwinding(), + ~Task::without_unwinding(), f); if run_now { @@ -156,7 +156,7 @@ pub fn spawntask_thread(f: ~fn()) -> Thread { let thread = do Thread::start { let mut sched = ~UvEventLoop::new_scheduler(); let task = ~Coroutine::with_task(&mut sched.stack_pool, - Task::without_unwinding(), + ~Task::without_unwinding(), f.take()); sched.enqueue_task(task); sched.run(); From 86ba4573498ef251933fcc784d513c7586dfaae1 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 19 May 2013 14:24:36 -0700 Subject: [PATCH 08/15] rt: Rename rust_initialize_global_state to rust_initialize_rt_tls_key --- src/libcore/rt/local_sched.rs | 10 ++++++++++ src/libcore/rt/sched.rs | 7 ++----- src/rt/rust_builtin.cpp | 4 ++-- src/rt/rustrt.def.in | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/libcore/rt/local_sched.rs b/src/libcore/rt/local_sched.rs index 895354d2218e5..5f7f8509a7b22 100644 --- a/src/libcore/rt/local_sched.rs +++ b/src/libcore/rt/local_sched.rs @@ -23,6 +23,16 @@ use unstable::finally::Finally; #[cfg(test)] use rt::uv::uvio::UvEventLoop; +/// Initialize the TLS key. Other ops will fail if this isn't executed first. +pub fn init_tls_key() { + unsafe { + rust_initialize_rt_tls_key(); + extern { + fn rust_initialize_rt_tls_key(); + } + } +} + /// Give the Scheduler to thread-local storage pub fn put(sched: ~Scheduler) { unsafe { diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 3abbb1f79e596..0cdc4e9602bad 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -64,11 +64,8 @@ pub impl Scheduler { fn new(event_loop: ~EventLoopObject) -> Scheduler { - // Lazily initialize the global state, currently the scheduler TLS key - unsafe { rust_initialize_global_state(); } - extern { - fn rust_initialize_global_state(); - } + // Lazily initialize the scheduler TLS key + local_sched::init_tls_key(); Scheduler { event_loop: event_loop, diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 1a64066b5a946..a2f253550af16 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -840,9 +840,9 @@ rust_get_rt_tls_key() { return &rt_key; } -// Initialize the global state required by the new scheduler +// Initialize the TLS key used by the new scheduler extern "C" CDECL void -rust_initialize_global_state() { +rust_initialize_rt_tls_key() { static lock_and_signal init_lock; static bool initialized = false; diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index cdc282440b830..e3e522aa7ceec 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -222,7 +222,7 @@ rust_uv_ip4_addrp rust_uv_ip6_addrp rust_uv_free_ip4_addr rust_uv_free_ip6_addr -rust_initialize_global_state +rust_initialize_rt_tls_key rust_dbg_next_port rust_new_memory_region rust_delete_memory_region From 97c2fd1a965b3af037fa22c911dfb618f818c172 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 19 May 2013 14:39:46 -0700 Subject: [PATCH 09/15] core::rt: Move some TLS functions from local_sched to local_ptr --- src/libcore/rt/local_ptr.rs | 63 +++++++++++++++++++++++++++++++++++ src/libcore/rt/local_sched.rs | 58 ++++---------------------------- src/libcore/rt/mod.rs | 13 +++++--- src/libcore/rt/sched.rs | 7 ++-- 4 files changed, 82 insertions(+), 59 deletions(-) create mode 100644 src/libcore/rt/local_ptr.rs diff --git a/src/libcore/rt/local_ptr.rs b/src/libcore/rt/local_ptr.rs new file mode 100644 index 0000000000000..3d706fbbdae19 --- /dev/null +++ b/src/libcore/rt/local_ptr.rs @@ -0,0 +1,63 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Access to a single thread-local pointer + +use libc::c_void; +use cast; +use option::{Option, Some, None}; +use tls = rt::thread_local_storage; + +/// Initialize the TLS key. Other ops will fail if this isn't executed first. +pub fn init_tls_key() { + unsafe { + rust_initialize_rt_tls_key(); + extern { + fn rust_initialize_rt_tls_key(); + } + } +} + +pub fn tls_key() -> tls::Key { + match maybe_tls_key() { + Some(key) => key, + None => abort!("runtime tls key not initialized") + } +} + +pub fn maybe_tls_key() -> Option { + unsafe { + let key: *mut c_void = rust_get_rt_tls_key(); + let key: &mut tls::Key = cast::transmute(key); + let key = *key; + // Check that the key has been initialized. + + // NB: This is a little racy because, while the key is + // initalized under a mutex and it's assumed to be initalized + // in the Scheduler ctor by any thread that needs to use it, + // we are not accessing the key under a mutex. Threads that + // are not using the new Scheduler but still *want to check* + // whether they are running under a new Scheduler may see a 0 + // value here that is in the process of being initialized in + // another thread. I think this is fine since the only action + // they could take if it was initialized would be to check the + // thread-local value and see that it's not set. + if key != -1 { + return Some(key); + } else { + return None; + } + } +} + +extern { + #[fast_ffi] + fn rust_get_rt_tls_key() -> *mut c_void; +} diff --git a/src/libcore/rt/local_sched.rs b/src/libcore/rt/local_sched.rs index 5f7f8509a7b22..6b3bc373d2210 100644 --- a/src/libcore/rt/local_sched.rs +++ b/src/libcore/rt/local_sched.rs @@ -18,25 +18,16 @@ use cell::Cell; use rt::sched::Scheduler; use rt::rtio::{EventLoop, IoFactoryObject}; -use tls = rt::thread_local_storage; use unstable::finally::Finally; +use rt::local_ptr; +use tls = rt::thread_local_storage; #[cfg(test)] use rt::uv::uvio::UvEventLoop; -/// Initialize the TLS key. Other ops will fail if this isn't executed first. -pub fn init_tls_key() { - unsafe { - rust_initialize_rt_tls_key(); - extern { - fn rust_initialize_rt_tls_key(); - } - } -} - /// Give the Scheduler to thread-local storage pub fn put(sched: ~Scheduler) { unsafe { - let key = tls_key(); + let key = local_ptr::tls_key(); let void_sched: *mut c_void = cast::transmute(sched); tls::set(key, void_sched); } @@ -45,7 +36,7 @@ pub fn put(sched: ~Scheduler) { /// Take ownership of the Scheduler from thread-local storage pub fn take() -> ~Scheduler { unsafe { - let key = tls_key(); + let key = local_ptr::tls_key(); let void_sched: *mut c_void = tls::get(key); rtassert!(void_sched.is_not_null()); let sched: ~Scheduler = cast::transmute(void_sched); @@ -57,7 +48,7 @@ pub fn take() -> ~Scheduler { /// Check whether there is a thread-local Scheduler attached to the running thread pub fn exists() -> bool { unsafe { - match maybe_tls_key() { + match local_ptr::maybe_tls_key() { Some(key) => tls::get(key).is_not_null(), None => false } @@ -89,7 +80,7 @@ pub fn borrow(f: &fn(&mut Scheduler)) { /// Because this leaves the Scheduler in thread-local storage it is possible /// For the Scheduler pointer to be aliased pub unsafe fn unsafe_borrow() -> *mut Scheduler { - let key = tls_key(); + let key = local_ptr::tls_key(); let mut void_sched: *mut c_void = tls::get(key); rtassert!(void_sched.is_not_null()); { @@ -106,43 +97,6 @@ pub unsafe fn unsafe_borrow_io() -> *mut IoFactoryObject { return io; } -fn tls_key() -> tls::Key { - match maybe_tls_key() { - Some(key) => key, - None => abort!("runtime tls key not initialized") - } -} - -fn maybe_tls_key() -> Option { - unsafe { - let key: *mut c_void = rust_get_rt_tls_key(); - let key: &mut tls::Key = cast::transmute(key); - let key = *key; - // Check that the key has been initialized. - - // NB: This is a little racy because, while the key is - // initalized under a mutex and it's assumed to be initalized - // in the Scheduler ctor by any thread that needs to use it, - // we are not accessing the key under a mutex. Threads that - // are not using the new Scheduler but still *want to check* - // whether they are running under a new Scheduler may see a 0 - // value here that is in the process of being initialized in - // another thread. I think this is fine since the only action - // they could take if it was initialized would be to check the - // thread-local value and see that it's not set. - if key != -1 { - return Some(key); - } else { - return None; - } - } -} - -extern { - #[fast_ffi] - fn rust_get_rt_tls_key() -> *mut c_void; -} - #[test] fn thread_local_scheduler_smoke_test() { let scheduler = ~UvEventLoop::new_scheduler(); diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index 37ac6ad3365c3..bda44b4c67f86 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -85,10 +85,6 @@ pub mod uv; /// or task-local storage. pub mod local; -// FIXME #5248: The import in `sched` doesn't resolve unless this is pub! -/// Bindings to pthread/windows thread-local storage. -pub mod thread_local_storage; - /// A parallel work-stealing deque. mod work_queue; @@ -126,6 +122,15 @@ pub mod tube; /// Simple reimplementation of core::comm pub mod comm; +// FIXME #5248 shouldn't be pub +/// The runtime needs to be able to put a pointer into thread-local storage. +pub mod local_ptr; + +// FIXME #5248: The import in `sched` doesn't resolve unless this is pub! +/// Bindings to pthread/windows thread-local storage. +pub mod thread_local_storage; + + /// Set up a default runtime configuration, given compiler-supplied arguments. /// /// This is invoked by the `start` _language item_ (unstable::lang) to diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 0cdc4e9602bad..8352993278cec 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -11,13 +11,14 @@ use option::*; use sys; use cast::transmute; +use cell::Cell; use super::work_queue::WorkQueue; use super::stack::{StackPool, StackSegment}; use super::rtio::{EventLoop, EventLoopObject}; use super::context::Context; use super::task::Task; -use cell::Cell; +use rt::local_ptr; // A more convenient name for external callers, e.g. `local_sched::take()` pub mod local_sched; @@ -64,8 +65,8 @@ pub impl Scheduler { fn new(event_loop: ~EventLoopObject) -> Scheduler { - // Lazily initialize the scheduler TLS key - local_sched::init_tls_key(); + // Lazily initialize the runtime TLS key + local_ptr::init_tls_key(); Scheduler { event_loop: event_loop, From 71aa6b6631547a7b2e6839931e73286e0bf6ce5d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 19 May 2013 14:57:47 -0700 Subject: [PATCH 10/15] core::rt: Move more TLS functionality into local_ptr --- src/libcore/rt/local_ptr.rs | 96 ++++++++++++++++++++++++++++++++--- src/libcore/rt/local_sched.rs | 56 ++------------------ 2 files changed, 94 insertions(+), 58 deletions(-) diff --git a/src/libcore/rt/local_ptr.rs b/src/libcore/rt/local_ptr.rs index 3d706fbbdae19..80d797e8c6543 100644 --- a/src/libcore/rt/local_ptr.rs +++ b/src/libcore/rt/local_ptr.rs @@ -8,11 +8,19 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Access to a single thread-local pointer +//! Access to a single thread-local pointer. +//! +//! The runtime will use this for storing ~Task. +//! +//! XXX: Add runtime checks for usage of inconsistent pointer types. +//! and for overwriting an existing pointer. use libc::c_void; use cast; +use ptr; +use cell::Cell; use option::{Option, Some, None}; +use unstable::finally::Finally; use tls = rt::thread_local_storage; /// Initialize the TLS key. Other ops will fail if this isn't executed first. @@ -25,14 +33,87 @@ pub fn init_tls_key() { } } -pub fn tls_key() -> tls::Key { +/// Give a pointer to thread-local storage. +/// +/// # Safety note +/// +/// Does not validate the pointer type. +pub unsafe fn put(sched: ~T) { + let key = tls_key(); + let void_ptr: *mut c_void = cast::transmute(sched); + tls::set(key, void_ptr); +} + +/// Take ownership of a pointer from thread-local storage. +/// +/// # Safety note +/// +/// Does not validate the pointer type. +pub unsafe fn take() -> ~T { + let key = tls_key(); + let void_ptr: *mut c_void = tls::get(key); + rtassert!(void_ptr.is_not_null()); + let ptr: ~T = cast::transmute(void_ptr); + tls::set(key, ptr::mut_null()); + return ptr; +} + +/// Check whether there is a thread-local pointer installed. +pub fn exists() -> bool { + unsafe { + match maybe_tls_key() { + Some(key) => tls::get(key).is_not_null(), + None => false + } + } +} + +/// Borrow the thread-local scheduler from thread-local storage. +/// While the scheduler is borrowed it is not available in TLS. +/// +/// # Safety note +/// +/// Does not validate the pointer type. +pub unsafe fn borrow(f: &fn(&mut T)) { + let mut value = take(); + + // XXX: Need a different abstraction from 'finally' here to avoid unsafety + let unsafe_ptr = cast::transmute_mut_region(&mut *value); + let value_cell = Cell(value); + + do (|| { + f(unsafe_ptr); + }).finally { + put(value_cell.take()); + } +} + +/// Borrow a mutable reference to the thread-local Scheduler +/// +/// # Safety Note +/// +/// Because this leaves the Scheduler in thread-local storage it is possible +/// For the Scheduler pointer to be aliased +pub unsafe fn unsafe_borrow() -> *mut T { + let key = tls_key(); + let mut void_sched: *mut c_void = tls::get(key); + rtassert!(void_sched.is_not_null()); + { + let sched: *mut *mut c_void = &mut void_sched; + let sched: *mut ~T = sched as *mut ~T; + let sched: *mut T = &mut **sched; + return sched; + } +} + +fn tls_key() -> tls::Key { match maybe_tls_key() { Some(key) => key, None => abort!("runtime tls key not initialized") } } -pub fn maybe_tls_key() -> Option { +fn maybe_tls_key() -> Option { unsafe { let key: *mut c_void = rust_get_rt_tls_key(); let key: &mut tls::Key = cast::transmute(key); @@ -55,9 +136,10 @@ pub fn maybe_tls_key() -> Option { return None; } } -} -extern { - #[fast_ffi] - fn rust_get_rt_tls_key() -> *mut c_void; + extern { + #[fast_ffi] + fn rust_get_rt_tls_key() -> *mut c_void; + } + } diff --git a/src/libcore/rt/local_sched.rs b/src/libcore/rt/local_sched.rs index 6b3bc373d2210..e3c0b4c4e8847 100644 --- a/src/libcore/rt/local_sched.rs +++ b/src/libcore/rt/local_sched.rs @@ -25,53 +25,17 @@ use tls = rt::thread_local_storage; #[cfg(test)] use rt::uv::uvio::UvEventLoop; /// Give the Scheduler to thread-local storage -pub fn put(sched: ~Scheduler) { - unsafe { - let key = local_ptr::tls_key(); - let void_sched: *mut c_void = cast::transmute(sched); - tls::set(key, void_sched); - } -} +pub fn put(sched: ~Scheduler) { unsafe { local_ptr::put(sched) } } /// Take ownership of the Scheduler from thread-local storage -pub fn take() -> ~Scheduler { - unsafe { - let key = local_ptr::tls_key(); - let void_sched: *mut c_void = tls::get(key); - rtassert!(void_sched.is_not_null()); - let sched: ~Scheduler = cast::transmute(void_sched); - tls::set(key, mut_null()); - return sched; - } -} +pub fn take() -> ~Scheduler { unsafe { local_ptr::take() } } /// Check whether there is a thread-local Scheduler attached to the running thread -pub fn exists() -> bool { - unsafe { - match local_ptr::maybe_tls_key() { - Some(key) => tls::get(key).is_not_null(), - None => false - } - } -} +pub fn exists() -> bool { local_ptr::exists() } /// Borrow the thread-local scheduler from thread-local storage. /// While the scheduler is borrowed it is not available in TLS. -pub fn borrow(f: &fn(&mut Scheduler)) { - let mut sched = take(); - - // XXX: Need a different abstraction from 'finally' here to avoid unsafety - unsafe { - let unsafe_sched = cast::transmute_mut_region(&mut *sched); - let sched = Cell(sched); - - do (|| { - f(unsafe_sched); - }).finally { - put(sched.take()); - } - } -} +pub fn borrow(f: &fn(&mut Scheduler)) { unsafe { local_ptr::borrow(f) } } /// Borrow a mutable reference to the thread-local Scheduler /// @@ -79,17 +43,7 @@ pub fn borrow(f: &fn(&mut Scheduler)) { /// /// Because this leaves the Scheduler in thread-local storage it is possible /// For the Scheduler pointer to be aliased -pub unsafe fn unsafe_borrow() -> *mut Scheduler { - let key = local_ptr::tls_key(); - let mut void_sched: *mut c_void = tls::get(key); - rtassert!(void_sched.is_not_null()); - { - let sched: *mut *mut c_void = &mut void_sched; - let sched: *mut ~Scheduler = sched as *mut ~Scheduler; - let sched: *mut Scheduler = &mut **sched; - return sched; - } -} +pub unsafe fn unsafe_borrow() -> *mut Scheduler { local_ptr::unsafe_borrow() } pub unsafe fn unsafe_borrow_io() -> *mut IoFactoryObject { let sched = unsafe_borrow(); From 18fab45aab8622b0bfbcd336d57652bfb2f4f4ac Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 19 May 2013 15:25:35 -0700 Subject: [PATCH 11/15] core::rt: Make local_sched a wrapper around Local --- src/libcore/rt/local.rs | 17 ++++++++++++++--- src/libcore/rt/local_sched.rs | 11 ++++++----- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/libcore/rt/local.rs b/src/libcore/rt/local.rs index ec54bcb99dd7f..09e6ecda6a04a 100644 --- a/src/libcore/rt/local.rs +++ b/src/libcore/rt/local.rs @@ -8,10 +8,21 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use rt::sched::Scheduler; +use rt::local_ptr; + pub trait Local { fn put_local(value: ~Self); fn take_local() -> ~Self; - fn exists() -> bool; - fn borrow(f: &fn(&mut Self)); - fn unsafe_borrow() -> *mut Self; + fn exists_local() -> bool; + fn borrow_local(f: &fn(&mut Self)); + unsafe fn unsafe_borrow_local() -> *mut Self; } + +impl Local for Scheduler { + fn put_local(value: ~Scheduler) { unsafe { local_ptr::put(value) }} + fn take_local() -> ~Scheduler { unsafe { local_ptr::take() } } + fn exists_local() -> bool { local_ptr::exists() } + fn borrow_local(f: &fn(&mut Scheduler)) { unsafe { local_ptr::borrow(f) } } + unsafe fn unsafe_borrow_local() -> *mut Scheduler { local_ptr::unsafe_borrow() } +} \ No newline at end of file diff --git a/src/libcore/rt/local_sched.rs b/src/libcore/rt/local_sched.rs index e3c0b4c4e8847..8923bb45f58db 100644 --- a/src/libcore/rt/local_sched.rs +++ b/src/libcore/rt/local_sched.rs @@ -21,21 +21,22 @@ use rt::rtio::{EventLoop, IoFactoryObject}; use unstable::finally::Finally; use rt::local_ptr; use tls = rt::thread_local_storage; +use rt::local::Local; #[cfg(test)] use rt::uv::uvio::UvEventLoop; /// Give the Scheduler to thread-local storage -pub fn put(sched: ~Scheduler) { unsafe { local_ptr::put(sched) } } +pub fn put(sched: ~Scheduler) { Local::put_local(sched) } /// Take ownership of the Scheduler from thread-local storage -pub fn take() -> ~Scheduler { unsafe { local_ptr::take() } } +pub fn take() -> ~Scheduler { Local::take_local() } /// Check whether there is a thread-local Scheduler attached to the running thread -pub fn exists() -> bool { local_ptr::exists() } +pub fn exists() -> bool { Local::exists_local::() } /// Borrow the thread-local scheduler from thread-local storage. /// While the scheduler is borrowed it is not available in TLS. -pub fn borrow(f: &fn(&mut Scheduler)) { unsafe { local_ptr::borrow(f) } } +pub fn borrow(f: &fn(&mut Scheduler)) { Local::borrow_local(f) } /// Borrow a mutable reference to the thread-local Scheduler /// @@ -43,7 +44,7 @@ pub fn borrow(f: &fn(&mut Scheduler)) { unsafe { local_ptr::borrow(f) } } /// /// Because this leaves the Scheduler in thread-local storage it is possible /// For the Scheduler pointer to be aliased -pub unsafe fn unsafe_borrow() -> *mut Scheduler { local_ptr::unsafe_borrow() } +pub unsafe fn unsafe_borrow() -> *mut Scheduler { Local::unsafe_borrow_local() } pub unsafe fn unsafe_borrow_io() -> *mut IoFactoryObject { let sched = unsafe_borrow(); From 06f1a64bd6e417b73f1b812b860271e86bb42b47 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 19 May 2013 15:45:39 -0700 Subject: [PATCH 12/15] core::rt: Convert users of local_sched to Local trait --- src/libcore/rt/comm.rs | 11 ++++--- src/libcore/rt/local.rs | 54 +++++++++++++++++++++++++------ src/libcore/rt/local_sched.rs | 50 +---------------------------- src/libcore/rt/mod.rs | 14 ++++---- src/libcore/rt/sched.rs | 60 ++++++++++++++++++----------------- src/libcore/rt/task.rs | 9 +++--- src/libcore/rt/test.rs | 27 ++++++++-------- src/libcore/rt/tube.rs | 25 ++++++++------- src/libcore/rt/uv/uvio.rs | 35 ++++++++++---------- src/libcore/task/spawn.rs | 3 +- 10 files changed, 143 insertions(+), 145 deletions(-) diff --git a/src/libcore/rt/comm.rs b/src/libcore/rt/comm.rs index 93afbea82786a..544d9817558c6 100644 --- a/src/libcore/rt/comm.rs +++ b/src/libcore/rt/comm.rs @@ -20,7 +20,8 @@ use cast; use util; use ops::Drop; use kinds::Owned; -use rt::sched::Coroutine; +use rt::sched::{Scheduler, Coroutine}; +use rt::local::Local; use rt::local_sched; use unstable::intrinsics::{atomic_xchg, atomic_load}; use util::Void; @@ -127,7 +128,7 @@ impl ChanOne { task_as_state => { // Port is blocked. Wake it up. let recvr: ~Coroutine = cast::transmute(task_as_state); - let sched = local_sched::take(); + let sched = Local::take::(); sched.schedule_task(recvr); } } @@ -157,7 +158,7 @@ impl PortOne { // XXX: Optimize this to not require the two context switches when data is available // Switch to the scheduler to put the ~Task into the Packet state. - let sched = local_sched::take(); + let sched = Local::take::(); do sched.deschedule_running_task_and_then |task| { unsafe { // Atomically swap the task pointer into the Packet state, issuing @@ -173,7 +174,7 @@ impl PortOne { STATE_ONE => { // Channel is closed. Switch back and check the data. let task: ~Coroutine = cast::transmute(task_as_state); - let sched = local_sched::take(); + let sched = Local::take::(); sched.resume_task_immediately(task); } _ => util::unreachable() @@ -239,7 +240,7 @@ impl Drop for ChanOneHack { // The port is blocked waiting for a message we will never send. Wake it. assert!((*this.packet()).payload.is_none()); let recvr: ~Coroutine = cast::transmute(task_as_state); - let sched = local_sched::take(); + let sched = Local::take::(); sched.schedule_task(recvr); } } diff --git a/src/libcore/rt/local.rs b/src/libcore/rt/local.rs index 09e6ecda6a04a..c054ba68d1082 100644 --- a/src/libcore/rt/local.rs +++ b/src/libcore/rt/local.rs @@ -12,17 +12,51 @@ use rt::sched::Scheduler; use rt::local_ptr; pub trait Local { - fn put_local(value: ~Self); - fn take_local() -> ~Self; - fn exists_local() -> bool; - fn borrow_local(f: &fn(&mut Self)); - unsafe fn unsafe_borrow_local() -> *mut Self; + fn put(value: ~Self); + fn take() -> ~Self; + fn exists() -> bool; + fn borrow(f: &fn(&mut Self)); + unsafe fn unsafe_borrow() -> *mut Self; } impl Local for Scheduler { - fn put_local(value: ~Scheduler) { unsafe { local_ptr::put(value) }} - fn take_local() -> ~Scheduler { unsafe { local_ptr::take() } } - fn exists_local() -> bool { local_ptr::exists() } - fn borrow_local(f: &fn(&mut Scheduler)) { unsafe { local_ptr::borrow(f) } } - unsafe fn unsafe_borrow_local() -> *mut Scheduler { local_ptr::unsafe_borrow() } + fn put(value: ~Scheduler) { unsafe { local_ptr::put(value) }} + fn take() -> ~Scheduler { unsafe { local_ptr::take() } } + fn exists() -> bool { local_ptr::exists() } + fn borrow(f: &fn(&mut Scheduler)) { unsafe { local_ptr::borrow(f) } } + unsafe fn unsafe_borrow() -> *mut Scheduler { local_ptr::unsafe_borrow() } +} + +#[cfg(test)] +mod test { + use rt::sched::Scheduler; + use rt::uv::uvio::UvEventLoop; + use super::*; + + #[test] + fn thread_local_scheduler_smoke_test() { + let scheduler = ~UvEventLoop::new_scheduler(); + Local::put(scheduler); + let _scheduler: ~Scheduler = Local::take(); + } + + #[test] + fn thread_local_scheduler_two_instances() { + let scheduler = ~UvEventLoop::new_scheduler(); + Local::put(scheduler); + let _scheduler: ~Scheduler = Local::take(); + let scheduler = ~UvEventLoop::new_scheduler(); + Local::put(scheduler); + let _scheduler: ~Scheduler = Local::take(); + } + + #[test] + fn borrow_smoke_test() { + let scheduler = ~UvEventLoop::new_scheduler(); + Local::put(scheduler); + unsafe { + let _scheduler: *mut Scheduler = Local::unsafe_borrow(); + } + let _scheduler: ~Scheduler = Local::take(); + } } \ No newline at end of file diff --git a/src/libcore/rt/local_sched.rs b/src/libcore/rt/local_sched.rs index 8923bb45f58db..48e3351c44f28 100644 --- a/src/libcore/rt/local_sched.rs +++ b/src/libcore/rt/local_sched.rs @@ -25,56 +25,8 @@ use rt::local::Local; #[cfg(test)] use rt::uv::uvio::UvEventLoop; -/// Give the Scheduler to thread-local storage -pub fn put(sched: ~Scheduler) { Local::put_local(sched) } - -/// Take ownership of the Scheduler from thread-local storage -pub fn take() -> ~Scheduler { Local::take_local() } - -/// Check whether there is a thread-local Scheduler attached to the running thread -pub fn exists() -> bool { Local::exists_local::() } - -/// Borrow the thread-local scheduler from thread-local storage. -/// While the scheduler is borrowed it is not available in TLS. -pub fn borrow(f: &fn(&mut Scheduler)) { Local::borrow_local(f) } - -/// Borrow a mutable reference to the thread-local Scheduler -/// -/// # Safety Note -/// -/// Because this leaves the Scheduler in thread-local storage it is possible -/// For the Scheduler pointer to be aliased -pub unsafe fn unsafe_borrow() -> *mut Scheduler { Local::unsafe_borrow_local() } - pub unsafe fn unsafe_borrow_io() -> *mut IoFactoryObject { - let sched = unsafe_borrow(); + let sched = Local::unsafe_borrow::(); let io: *mut IoFactoryObject = (*sched).event_loop.io().unwrap(); return io; } - -#[test] -fn thread_local_scheduler_smoke_test() { - let scheduler = ~UvEventLoop::new_scheduler(); - put(scheduler); - let _scheduler = take(); -} - -#[test] -fn thread_local_scheduler_two_instances() { - let scheduler = ~UvEventLoop::new_scheduler(); - put(scheduler); - let _scheduler = take(); - let scheduler = ~UvEventLoop::new_scheduler(); - put(scheduler); - let _scheduler = take(); -} - -#[test] -fn borrow_smoke_test() { - let scheduler = ~UvEventLoop::new_scheduler(); - put(scheduler); - unsafe { - let _scheduler = unsafe_borrow(); - } - let _scheduler = take(); -} diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index bda44b4c67f86..c8532f6b94a3a 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -188,16 +188,17 @@ pub enum RuntimeContext { pub fn context() -> RuntimeContext { use task::rt::rust_task; - use self::sched::local_sched; + use self::local::Local; + use self::sched::{local_sched, Scheduler}; // XXX: Hitting TLS twice to check if the scheduler exists // then to check for the task is not good for perf if unsafe { rust_try_get_task().is_not_null() } { return OldTaskContext; } else { - if local_sched::exists() { + if Local::exists::() { let context = ::cell::empty_cell(); - do local_sched::borrow |sched| { + do Local::borrow:: |sched| { if sched.in_task_context() { context.put_back(TaskContext); } else { @@ -219,9 +220,10 @@ pub fn context() -> RuntimeContext { #[test] fn test_context() { use unstable::run_in_bare_thread; - use self::sched::{local_sched, Coroutine}; + use self::sched::{local_sched, Scheduler, Coroutine}; use rt::uv::uvio::UvEventLoop; use cell::Cell; + use rt::local::Local; assert_eq!(context(), OldTaskContext); do run_in_bare_thread { @@ -229,11 +231,11 @@ fn test_context() { let mut sched = ~UvEventLoop::new_scheduler(); let task = ~do Coroutine::new(&mut sched.stack_pool) { assert_eq!(context(), TaskContext); - let sched = local_sched::take(); + let sched = Local::take::(); do sched.deschedule_running_task_and_then() |task| { assert_eq!(context(), SchedulerContext); let task = Cell(task); - do local_sched::borrow |sched| { + do Local::borrow:: |sched| { sched.enqueue_task(task.take()); } } diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 8352993278cec..0004ef29de02a 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -19,6 +19,7 @@ use super::rtio::{EventLoop, EventLoopObject}; use super::context::Context; use super::task::Task; use rt::local_ptr; +use rt::local::Local; // A more convenient name for external callers, e.g. `local_sched::take()` pub mod local_sched; @@ -94,12 +95,12 @@ pub impl Scheduler { }; // Give ownership of the scheduler (self) to the thread - local_sched::put(self_sched); + Local::put(self_sched); (*event_loop).run(); } - let sched = local_sched::take(); + let sched = Local::take::(); assert!(sched.work_queue.is_empty()); return sched; } @@ -114,7 +115,7 @@ pub impl Scheduler { self.event_loop.callback(resume_task_from_queue); fn resume_task_from_queue() { - let scheduler = local_sched::take(); + let scheduler = Local::take::(); scheduler.resume_task_from_queue(); } } @@ -134,7 +135,7 @@ pub impl Scheduler { } None => { rtdebug!("no tasks in queue"); - local_sched::put(this); + Local::put(this); } } } @@ -150,7 +151,7 @@ pub impl Scheduler { do self.deschedule_running_task_and_then |dead_task| { let dead_task = Cell(dead_task); - do local_sched::borrow |sched| { + do Local::borrow:: |sched| { dead_task.take().recycle(&mut sched.stack_pool); } } @@ -163,7 +164,7 @@ pub impl Scheduler { do self.switch_running_tasks_and_then(task) |last_task| { let last_task = Cell(last_task); - do local_sched::borrow |sched| { + do Local::borrow:: |sched| { sched.enqueue_task(last_task.take()); } } @@ -174,7 +175,7 @@ pub impl Scheduler { do self.switch_running_tasks_and_then(task) |last_task| { let last_task = Cell(last_task); - do local_sched::borrow |sched| { + do Local::borrow:: |sched| { sched.enqueue_task(last_task.take()); } } @@ -192,18 +193,18 @@ pub impl Scheduler { this.current_task = Some(task); this.enqueue_cleanup_job(DoNothing); - local_sched::put(this); + Local::put(this); // Take pointers to both the task and scheduler's saved registers. unsafe { - let sched = local_sched::unsafe_borrow(); + let sched = Local::unsafe_borrow::(); let (sched_context, _, next_task_context) = (*sched).get_contexts(); let next_task_context = next_task_context.unwrap(); // Context switch to the task, restoring it's registers // and saving the scheduler's Context::swap(sched_context, next_task_context); - let sched = local_sched::unsafe_borrow(); + let sched = Local::unsafe_borrow::(); // The running task should have passed ownership elsewhere assert!((*sched).current_task.is_none()); @@ -233,16 +234,16 @@ pub impl Scheduler { this.enqueue_cleanup_job(GiveTask(blocked_task, f_opaque)); } - local_sched::put(this); + Local::put(this); unsafe { - let sched = local_sched::unsafe_borrow(); + let sched = Local::unsafe_borrow::(); let (sched_context, last_task_context, _) = (*sched).get_contexts(); let last_task_context = last_task_context.unwrap(); Context::swap(last_task_context, sched_context); // We could be executing in a different thread now - let sched = local_sched::unsafe_borrow(); + let sched = Local::unsafe_borrow::(); (*sched).run_cleanup_job(); } } @@ -262,17 +263,17 @@ pub impl Scheduler { this.enqueue_cleanup_job(GiveTask(old_running_task, f_opaque)); this.current_task = Some(next_task); - local_sched::put(this); + Local::put(this); unsafe { - let sched = local_sched::unsafe_borrow(); + let sched = Local::unsafe_borrow::(); let (_, last_task_context, next_task_context) = (*sched).get_contexts(); let last_task_context = last_task_context.unwrap(); let next_task_context = next_task_context.unwrap(); Context::swap(last_task_context, next_task_context); // We could be executing in a different thread now - let sched = local_sched::unsafe_borrow(); + let sched = Local::unsafe_borrow::(); (*sched).run_cleanup_job(); } } @@ -377,16 +378,16 @@ pub impl Coroutine { // context switch to the task. The previous context may // have asked us to do some cleanup. unsafe { - let sched = local_sched::unsafe_borrow(); + let sched = Local::unsafe_borrow::(); (*sched).run_cleanup_job(); - let sched = local_sched::unsafe_borrow(); + let sched = Local::unsafe_borrow::(); let task = (*sched).current_task.get_mut_ref(); // FIXME #6141: shouldn't neet to put `start()` in another closure task.task.run(||start()); } - let sched = local_sched::take(); + let sched = Local::take::(); sched.terminate_current_task(); }; return wrapper; @@ -409,6 +410,7 @@ mod test { use rt::uv::uvio::UvEventLoop; use unstable::run_in_bare_thread; use task::spawn; + use rt::local::Local; use rt::test::*; use super::*; @@ -456,14 +458,14 @@ mod test { let mut sched = ~UvEventLoop::new_scheduler(); let task1 = ~do Coroutine::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; } - let mut sched = local_sched::take(); + let mut sched = Local::take::(); let task2 = ~do Coroutine::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; } }; // Context switch directly to the new task do sched.switch_running_tasks_and_then(task2) |task1| { let task1 = Cell(task1); - do local_sched::borrow |sched| { + do Local::borrow:: |sched| { sched.enqueue_task(task1.take()); } } @@ -493,7 +495,7 @@ mod test { assert_eq!(count, MAX); fn run_task(count_ptr: *mut int) { - do local_sched::borrow |sched| { + do Local::borrow:: |sched| { let task = ~do Coroutine::new(&mut sched.stack_pool) { unsafe { *count_ptr = *count_ptr + 1; @@ -513,11 +515,11 @@ mod test { do run_in_bare_thread { let mut sched = ~UvEventLoop::new_scheduler(); let task = ~do Coroutine::new(&mut sched.stack_pool) { - let sched = local_sched::take(); + let sched = Local::take::(); assert!(sched.in_task_context()); do sched.deschedule_running_task_and_then() |task| { let task = Cell(task); - do local_sched::borrow |sched| { + do Local::borrow:: |sched| { assert!(!sched.in_task_context()); sched.enqueue_task(task.take()); } @@ -536,17 +538,17 @@ mod test { // exit before emptying the work queue do run_in_newsched_task { do spawn { - let sched = local_sched::take(); + let sched = Local::take::(); do sched.deschedule_running_task_and_then |task| { - let mut sched = local_sched::take(); + let mut sched = Local::take::(); let task = Cell(task); do sched.event_loop.callback_ms(10) { rtdebug!("in callback"); - let mut sched = local_sched::take(); + let mut sched = Local::take::(); sched.enqueue_task(task.take()); - local_sched::put(sched); + Local::put(sched); } - local_sched::put(sched); + Local::put(sched); } } } diff --git a/src/libcore/rt/task.rs b/src/libcore/rt/task.rs index 65b7c885b5735..cfb5b96586034 100644 --- a/src/libcore/rt/task.rs +++ b/src/libcore/rt/task.rs @@ -16,7 +16,8 @@ use prelude::*; use libc::{c_void, uintptr_t}; use cast::transmute; -use super::sched::local_sched; +use super::sched::{Scheduler, local_sched}; +use rt::local::Local; use super::local_heap::LocalHeap; use rt::logging::StdErrLogger; @@ -152,7 +153,7 @@ impl Unwinder { /// Borrow a pointer to the installed local services. /// Fails (likely aborting the process) if local services are not available. pub fn borrow_local_task(f: &fn(&mut Task)) { - do local_sched::borrow |sched| { + do Local::borrow:: |sched| { match sched.current_task { Some(~ref mut task) => { f(&mut *task.task) @@ -165,7 +166,7 @@ pub fn borrow_local_task(f: &fn(&mut Task)) { } pub unsafe fn unsafe_borrow_local_task() -> *mut Task { - match (*local_sched::unsafe_borrow()).current_task { + match (*Local::unsafe_borrow::()).current_task { Some(~ref mut task) => { let s: *mut Task = &mut *task.task; return s; @@ -178,7 +179,7 @@ pub unsafe fn unsafe_borrow_local_task() -> *mut Task { } pub unsafe fn unsafe_try_borrow_local_task() -> Option<*mut Task> { - if local_sched::exists() { + if Local::exists::() { Some(unsafe_borrow_local_task()) } else { None diff --git a/src/libcore/rt/test.rs b/src/libcore/rt/test.rs index 66993041752cf..c60ae2bfeffc8 100644 --- a/src/libcore/rt/test.rs +++ b/src/libcore/rt/test.rs @@ -15,6 +15,7 @@ use result::{Result, Ok, Err}; use super::io::net::ip::{IpAddr, Ipv4}; use rt::task::Task; use rt::thread::Thread; +use rt::local::Local; /// Creates a new scheduler in a new thread and runs a task in it, /// then waits for the scheduler to exit. Failure of the task @@ -40,13 +41,13 @@ pub fn run_in_newsched_task(f: ~fn()) { pub fn spawntask(f: ~fn()) { use super::sched::*; - let mut sched = local_sched::take(); + let mut sched = Local::take::(); let task = ~Coroutine::with_task(&mut sched.stack_pool, ~Task::without_unwinding(), f); do sched.switch_running_tasks_and_then(task) |task| { let task = Cell(task); - let sched = local_sched::take(); + let sched = Local::take::(); sched.schedule_new_task(task.take()); } } @@ -55,13 +56,13 @@ pub fn spawntask(f: ~fn()) { pub fn spawntask_immediately(f: ~fn()) { use super::sched::*; - let mut sched = local_sched::take(); + let mut sched = Local::take::(); let task = ~Coroutine::with_task(&mut sched.stack_pool, ~Task::without_unwinding(), f); do sched.switch_running_tasks_and_then(task) |task| { let task = Cell(task); - do local_sched::borrow |sched| { + do Local::borrow:: |sched| { sched.enqueue_task(task.take()); } } @@ -71,13 +72,13 @@ pub fn spawntask_immediately(f: ~fn()) { pub fn spawntask_later(f: ~fn()) { use super::sched::*; - let mut sched = local_sched::take(); + let mut sched = Local::take::(); let task = ~Coroutine::with_task(&mut sched.stack_pool, ~Task::without_unwinding(), f); sched.enqueue_task(task); - local_sched::put(sched); + Local::put(sched); } /// Spawn a task and either run it immediately or run it later @@ -88,7 +89,7 @@ pub fn spawntask_random(f: ~fn()) { let mut rng = rng(); let run_now: bool = Rand::rand(&mut rng); - let mut sched = local_sched::take(); + let mut sched = Local::take::(); let task = ~Coroutine::with_task(&mut sched.stack_pool, ~Task::without_unwinding(), f); @@ -96,13 +97,13 @@ pub fn spawntask_random(f: ~fn()) { if run_now { do sched.switch_running_tasks_and_then(task) |task| { let task = Cell(task); - do local_sched::borrow |sched| { + do Local::borrow:: |sched| { sched.enqueue_task(task.take()); } } } else { sched.enqueue_task(task); - local_sched::put(sched); + Local::put(sched); } } @@ -120,21 +121,21 @@ pub fn spawntask_try(f: ~fn()) -> Result<(), ()> { // Switch to the scheduler let f = Cell(Cell(f)); - let sched = local_sched::take(); + let sched = Local::take::(); do sched.deschedule_running_task_and_then() |old_task| { let old_task = Cell(old_task); let f = f.take(); - let mut sched = local_sched::take(); + let mut sched = Local::take::(); let new_task = ~do Coroutine::new(&mut sched.stack_pool) { do (|| { (f.take())() }).finally { // Check for failure then resume the parent task unsafe { *failed_ptr = task::failing(); } - let sched = local_sched::take(); + let sched = Local::take::(); do sched.switch_running_tasks_and_then(old_task.take()) |new_task| { let new_task = Cell(new_task); - do local_sched::borrow |sched| { + do Local::borrow:: |sched| { sched.enqueue_task(new_task.take()); } } diff --git a/src/libcore/rt/tube.rs b/src/libcore/rt/tube.rs index bc9269f08faa9..2e6dc64986ebf 100644 --- a/src/libcore/rt/tube.rs +++ b/src/libcore/rt/tube.rs @@ -16,9 +16,10 @@ use option::*; use clone::Clone; use super::rc::RC; -use rt::sched::Coroutine; +use rt::sched::{Scheduler, Coroutine}; use rt::{context, TaskContext, SchedulerContext}; use rt::local_sched; +use rt::local::Local; use vec::OwnedVector; use container::Container; @@ -53,7 +54,7 @@ impl Tube { // There's a waiting task. Wake it up rtdebug!("waking blocked tube"); let task = (*state).blocked_task.swap_unwrap(); - let sched = local_sched::take(); + let sched = Local::take::(); sched.resume_task_immediately(task); } } @@ -71,7 +72,7 @@ impl Tube { rtdebug!("blocking on tube recv"); assert!(self.p.refcount() > 1); // There better be somebody to wake us up assert!((*state).blocked_task.is_none()); - let sched = local_sched::take(); + let sched = Local::take::(); do sched.deschedule_running_task_and_then |task| { (*state).blocked_task = Some(task); } @@ -97,6 +98,8 @@ mod test { use rt::local_sched; use rt::test::*; use rt::rtio::EventLoop; + use rt::sched::Scheduler; + use rt::local::Local; use super::*; #[test] @@ -105,11 +108,11 @@ mod test { let mut tube: Tube = Tube::new(); let tube_clone = tube.clone(); let tube_clone_cell = Cell(tube_clone); - let sched = local_sched::take(); + let sched = Local::take::(); do sched.deschedule_running_task_and_then |task| { let mut tube_clone = tube_clone_cell.take(); tube_clone.send(1); - let sched = local_sched::take(); + let sched = Local::take::(); sched.resume_task_immediately(task); } @@ -123,10 +126,10 @@ mod test { let mut tube: Tube = Tube::new(); let tube_clone = tube.clone(); let tube_clone = Cell(Cell(Cell(tube_clone))); - let sched = local_sched::take(); + let sched = Local::take::(); do sched.deschedule_running_task_and_then |task| { let tube_clone = tube_clone.take(); - do local_sched::borrow |sched| { + do Local::borrow:: |sched| { let tube_clone = tube_clone.take(); do sched.event_loop.callback { let mut tube_clone = tube_clone.take(); @@ -135,7 +138,7 @@ mod test { tube_clone.send(1); } } - let sched = local_sched::take(); + let sched = Local::take::(); sched.resume_task_immediately(task); } @@ -151,7 +154,7 @@ mod test { let mut tube: Tube = Tube::new(); let tube_clone = tube.clone(); let tube_clone = Cell(tube_clone); - let sched = local_sched::take(); + let sched = Local::take::(); do sched.deschedule_running_task_and_then |task| { callback_send(tube_clone.take(), 0); @@ -159,7 +162,7 @@ mod test { if i == 100 { return; } let tube = Cell(Cell(tube)); - do local_sched::borrow |sched| { + do Local::borrow:: |sched| { let tube = tube.take(); do sched.event_loop.callback { let mut tube = tube.take(); @@ -171,7 +174,7 @@ mod test { } } - let sched = local_sched::take(); + let sched = Local::take::(); sched.resume_task_immediately(task); } diff --git a/src/libcore/rt/uv/uvio.rs b/src/libcore/rt/uv/uvio.rs index 8aa1860f3521b..e83ab0dd80893 100644 --- a/src/libcore/rt/uv/uvio.rs +++ b/src/libcore/rt/uv/uvio.rs @@ -22,6 +22,7 @@ use rt::rtio::*; use rt::sched::{Scheduler, local_sched}; use rt::io::{standard_error, OtherIoError}; use rt::tube::Tube; +use rt::local::Local; #[cfg(test)] use container::Container; #[cfg(test)] use uint; @@ -118,14 +119,14 @@ impl IoFactory for UvIoFactory { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = local_sched::take(); + let scheduler = Local::take::(); assert!(scheduler.in_task_context()); // Block this task and take ownership, switch to scheduler context do scheduler.deschedule_running_task_and_then |task| { rtdebug!("connect: entered scheduler context"); - do local_sched::borrow |scheduler| { + do Local::borrow:: |scheduler| { assert!(!scheduler.in_task_context()); } let mut tcp_watcher = TcpWatcher::new(self.uv_loop()); @@ -142,7 +143,7 @@ impl IoFactory for UvIoFactory { unsafe { (*result_cell_ptr).put_back(res); } // Context switch - let scheduler = local_sched::take(); + let scheduler = Local::take::(); scheduler.resume_task_immediately(task_cell.take()); } else { rtdebug!("status is some"); @@ -150,7 +151,7 @@ impl IoFactory for UvIoFactory { do stream_watcher.close { let res = Err(uv_error_to_io_error(status.get())); unsafe { (*result_cell_ptr).put_back(res); } - let scheduler = local_sched::take(); + let scheduler = Local::take::(); scheduler.resume_task_immediately(task_cell.take()); } }; @@ -166,11 +167,11 @@ impl IoFactory for UvIoFactory { match watcher.bind(addr) { Ok(_) => Ok(~UvTcpListener::new(watcher)), Err(uverr) => { - let scheduler = local_sched::take(); + let scheduler = Local::take::(); do scheduler.deschedule_running_task_and_then |task| { let task_cell = Cell(task); do watcher.as_stream().close { - let scheduler = local_sched::take(); + let scheduler = Local::take::(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -202,11 +203,11 @@ impl UvTcpListener { impl Drop for UvTcpListener { fn finalize(&self) { let watcher = self.watcher(); - let scheduler = local_sched::take(); + let scheduler = Local::take::(); do scheduler.deschedule_running_task_and_then |task| { let task_cell = Cell(task); do watcher.as_stream().close { - let scheduler = local_sched::take(); + let scheduler = Local::take::(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -264,11 +265,11 @@ impl Drop for UvTcpStream { fn finalize(&self) { rtdebug!("closing tcp stream"); let watcher = self.watcher(); - let scheduler = local_sched::take(); + let scheduler = Local::take::(); do scheduler.deschedule_running_task_and_then |task| { let task_cell = Cell(task); do watcher.close { - let scheduler = local_sched::take(); + let scheduler = Local::take::(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -280,13 +281,13 @@ impl RtioTcpStream for UvTcpStream { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = local_sched::take(); + let scheduler = Local::take::(); assert!(scheduler.in_task_context()); let watcher = self.watcher(); let buf_ptr: *&mut [u8] = &buf; do scheduler.deschedule_running_task_and_then |task| { rtdebug!("read: entered scheduler context"); - do local_sched::borrow |scheduler| { + do Local::borrow:: |scheduler| { assert!(!scheduler.in_task_context()); } let mut watcher = watcher; @@ -314,7 +315,7 @@ impl RtioTcpStream for UvTcpStream { unsafe { (*result_cell_ptr).put_back(result); } - let scheduler = local_sched::take(); + let scheduler = Local::take::(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -326,7 +327,7 @@ impl RtioTcpStream for UvTcpStream { fn write(&mut self, buf: &[u8]) -> Result<(), IoError> { let result_cell = empty_cell(); let result_cell_ptr: *Cell> = &result_cell; - let scheduler = local_sched::take(); + let scheduler = Local::take::(); assert!(scheduler.in_task_context()); let watcher = self.watcher(); let buf_ptr: *&[u8] = &buf; @@ -343,7 +344,7 @@ impl RtioTcpStream for UvTcpStream { unsafe { (*result_cell_ptr).put_back(result); } - let scheduler = local_sched::take(); + let scheduler = Local::take::(); scheduler.resume_task_immediately(task_cell.take()); } } @@ -420,13 +421,13 @@ fn test_read_and_block() { } reads += 1; - let scheduler = local_sched::take(); + let scheduler = Local::take::(); // Yield to the other task in hopes that it // will trigger a read callback while we are // not ready for it do scheduler.deschedule_running_task_and_then |task| { let task = Cell(task); - do local_sched::borrow |scheduler| { + do Local::borrow:: |scheduler| { scheduler.enqueue_task(task.take()); } } diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs index 8d287b5c51f7d..81e5af5caab11 100644 --- a/src/libcore/task/spawn.rs +++ b/src/libcore/task/spawn.rs @@ -90,6 +90,7 @@ use task::unkillable; use uint; use util; use unstable::sync::{Exclusive, exclusive}; +use rt::local::Local; #[cfg(test)] use task::default_task_opts; @@ -575,7 +576,7 @@ pub fn spawn_raw(opts: TaskOpts, f: ~fn()) { fn spawn_raw_newsched(_opts: TaskOpts, f: ~fn()) { use rt::sched::*; - let mut sched = local_sched::take(); + let mut sched = Local::take::(); let task = ~Coroutine::new(&mut sched.stack_pool, f); sched.schedule_new_task(task); } From 2f99fb8efad8803801628a507fe3ac06a70c7871 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 19 May 2013 16:10:44 -0700 Subject: [PATCH 13/15] core::rt: Remove local_sched module --- src/libcore/rt/comm.rs | 1 - src/libcore/rt/io/net/tcp.rs | 2 +- src/libcore/rt/local_sched.rs | 32 -------------------------------- src/libcore/rt/mod.rs | 7 ++----- src/libcore/rt/sched.rs | 10 +++++++--- src/libcore/rt/task.rs | 2 +- src/libcore/rt/tube.rs | 2 -- src/libcore/rt/uv/uvio.rs | 17 +++++++++-------- 8 files changed, 20 insertions(+), 53 deletions(-) delete mode 100644 src/libcore/rt/local_sched.rs diff --git a/src/libcore/rt/comm.rs b/src/libcore/rt/comm.rs index 544d9817558c6..576a402b70919 100644 --- a/src/libcore/rt/comm.rs +++ b/src/libcore/rt/comm.rs @@ -22,7 +22,6 @@ use ops::Drop; use kinds::Owned; use rt::sched::{Scheduler, Coroutine}; use rt::local::Local; -use rt::local_sched; use unstable::intrinsics::{atomic_xchg, atomic_load}; use util::Void; use comm::{GenericChan, GenericSmartChan, GenericPort, Peekable}; diff --git a/src/libcore/rt/io/net/tcp.rs b/src/libcore/rt/io/net/tcp.rs index a5fd7a395de7f..d900341998117 100644 --- a/src/libcore/rt/io/net/tcp.rs +++ b/src/libcore/rt/io/net/tcp.rs @@ -10,7 +10,7 @@ use option::{Option, Some, None}; use result::{Ok, Err}; -use rt::sched::local_sched::unsafe_borrow_io; +use rt::sched::unsafe_borrow_io; use rt::io::net::ip::IpAddr; use rt::io::{Reader, Writer, Listener}; use rt::io::{io_error, read_error, EndOfFile}; diff --git a/src/libcore/rt/local_sched.rs b/src/libcore/rt/local_sched.rs deleted file mode 100644 index 48e3351c44f28..0000000000000 --- a/src/libcore/rt/local_sched.rs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! Access to the thread-local Scheduler - -use prelude::*; -use ptr::mut_null; -use libc::c_void; -use cast; -use cell::Cell; - -use rt::sched::Scheduler; -use rt::rtio::{EventLoop, IoFactoryObject}; -use unstable::finally::Finally; -use rt::local_ptr; -use tls = rt::thread_local_storage; -use rt::local::Local; - -#[cfg(test)] use rt::uv::uvio::UvEventLoop; - -pub unsafe fn unsafe_borrow_io() -> *mut IoFactoryObject { - let sched = Local::unsafe_borrow::(); - let io: *mut IoFactoryObject = (*sched).event_loop.io().unwrap(); - return io; -} diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index c8532f6b94a3a..2fac1df01a495 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -67,9 +67,6 @@ pub mod task; /// The coroutine task scheduler, built on the `io` event loop. mod sched; -/// Thread-local access to the current Scheduler. -pub mod local_sched; - /// Synchronous I/O. #[path = "io/mod.rs"] pub mod io; @@ -189,7 +186,7 @@ pub fn context() -> RuntimeContext { use task::rt::rust_task; use self::local::Local; - use self::sched::{local_sched, Scheduler}; + use self::sched::Scheduler; // XXX: Hitting TLS twice to check if the scheduler exists // then to check for the task is not good for perf @@ -220,7 +217,7 @@ pub fn context() -> RuntimeContext { #[test] fn test_context() { use unstable::run_in_bare_thread; - use self::sched::{local_sched, Scheduler, Coroutine}; + use self::sched::{Scheduler, Coroutine}; use rt::uv::uvio::UvEventLoop; use cell::Cell; use rt::local::Local; diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 0004ef29de02a..20c24adaa0ad0 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -20,9 +20,7 @@ use super::context::Context; use super::task::Task; use rt::local_ptr; use rt::local::Local; - -// A more convenient name for external callers, e.g. `local_sched::take()` -pub mod local_sched; +use rt::rtio::IoFactoryObject; /// The Scheduler is responsible for coordinating execution of Coroutines /// on a single thread. When the scheduler is running it is owned by @@ -403,6 +401,12 @@ pub impl Coroutine { } } +pub unsafe fn unsafe_borrow_io() -> *mut IoFactoryObject { + let sched = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = (*sched).event_loop.io().unwrap(); + return io; +} + #[cfg(test)] mod test { use int; diff --git a/src/libcore/rt/task.rs b/src/libcore/rt/task.rs index cfb5b96586034..3f98ad74ef260 100644 --- a/src/libcore/rt/task.rs +++ b/src/libcore/rt/task.rs @@ -16,7 +16,7 @@ use prelude::*; use libc::{c_void, uintptr_t}; use cast::transmute; -use super::sched::{Scheduler, local_sched}; +use super::sched::Scheduler; use rt::local::Local; use super::local_heap::LocalHeap; use rt::logging::StdErrLogger; diff --git a/src/libcore/rt/tube.rs b/src/libcore/rt/tube.rs index 2e6dc64986ebf..b2f475a696605 100644 --- a/src/libcore/rt/tube.rs +++ b/src/libcore/rt/tube.rs @@ -18,7 +18,6 @@ use clone::Clone; use super::rc::RC; use rt::sched::{Scheduler, Coroutine}; use rt::{context, TaskContext, SchedulerContext}; -use rt::local_sched; use rt::local::Local; use vec::OwnedVector; use container::Container; @@ -95,7 +94,6 @@ impl Clone for Tube { mod test { use int; use cell::Cell; - use rt::local_sched; use rt::test::*; use rt::rtio::EventLoop; use rt::sched::Scheduler; diff --git a/src/libcore/rt/uv/uvio.rs b/src/libcore/rt/uv/uvio.rs index e83ab0dd80893..b89dfcab3d330 100644 --- a/src/libcore/rt/uv/uvio.rs +++ b/src/libcore/rt/uv/uvio.rs @@ -19,7 +19,8 @@ use rt::io::net::ip::IpAddr; use rt::uv::*; use rt::uv::idle::IdleWatcher; use rt::rtio::*; -use rt::sched::{Scheduler, local_sched}; +use rt::sched::unsafe_borrow_io; +use rt::sched::Scheduler; use rt::io::{standard_error, OtherIoError}; use rt::tube::Tube; use rt::local::Local; @@ -358,7 +359,7 @@ impl RtioTcpStream for UvTcpStream { fn test_simple_io_no_connect() { do run_in_newsched_task { unsafe { - let io = local_sched::unsafe_borrow_io(); + let io = unsafe_borrow_io(); let addr = next_test_ip4(); let maybe_chan = (*io).tcp_connect(addr); assert!(maybe_chan.is_err()); @@ -374,7 +375,7 @@ fn test_simple_tcp_server_and_client() { // Start the server first so it's listening when we connect do spawntask_immediately { unsafe { - let io = local_sched::unsafe_borrow_io(); + let io = unsafe_borrow_io(); let mut listener = (*io).tcp_bind(addr).unwrap(); let mut stream = listener.accept().unwrap(); let mut buf = [0, .. 2048]; @@ -389,7 +390,7 @@ fn test_simple_tcp_server_and_client() { do spawntask_immediately { unsafe { - let io = local_sched::unsafe_borrow_io(); + let io = unsafe_borrow_io(); let mut stream = (*io).tcp_connect(addr).unwrap(); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); } @@ -403,7 +404,7 @@ fn test_read_and_block() { let addr = next_test_ip4(); do spawntask_immediately { - let io = unsafe { local_sched::unsafe_borrow_io() }; + let io = unsafe { unsafe_borrow_io() }; let mut listener = unsafe { (*io).tcp_bind(addr).unwrap() }; let mut stream = listener.accept().unwrap(); let mut buf = [0, .. 2048]; @@ -439,7 +440,7 @@ fn test_read_and_block() { do spawntask_immediately { unsafe { - let io = local_sched::unsafe_borrow_io(); + let io = unsafe_borrow_io(); let mut stream = (*io).tcp_connect(addr).unwrap(); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); @@ -459,7 +460,7 @@ fn test_read_read_read() { do spawntask_immediately { unsafe { - let io = local_sched::unsafe_borrow_io(); + let io = unsafe_borrow_io(); let mut listener = (*io).tcp_bind(addr).unwrap(); let mut stream = listener.accept().unwrap(); let buf = [1, .. 2048]; @@ -473,7 +474,7 @@ fn test_read_read_read() { do spawntask_immediately { unsafe { - let io = local_sched::unsafe_borrow_io(); + let io = unsafe_borrow_io(); let mut stream = (*io).tcp_connect(addr).unwrap(); let mut buf = [0, .. 2048]; let mut total_bytes_read = 0; From 2042696236a600b6fedec771e0aeec4b0552709d Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 19 May 2013 16:50:21 -0700 Subject: [PATCH 14/15] core::rt: Implement Local for Task --- src/libcore/logging.rs | 5 +++- src/libcore/rt/local.rs | 41 +++++++++++++++++++++++++++++ src/libcore/rt/task.rs | 40 ++-------------------------- src/libcore/sys.rs | 5 ++-- src/libcore/task/local_data_priv.rs | 6 ++--- src/libcore/task/mod.rs | 5 ++-- src/libcore/unstable/lang.rs | 7 ++--- 7 files changed, 60 insertions(+), 49 deletions(-) diff --git a/src/libcore/logging.rs b/src/libcore/logging.rs index 16a80866cf1ab..be71714a048e3 100644 --- a/src/libcore/logging.rs +++ b/src/libcore/logging.rs @@ -66,8 +66,11 @@ pub fn log_type(level: u32, object: &T) { } fn newsched_log_str(msg: ~str) { + use rt::task::Task; + use rt::local::Local; + unsafe { - match rt::task::unsafe_try_borrow_local_task() { + match Local::try_unsafe_borrow::() { Some(local) => { // Use the available logger (*local).logger.log(Left(msg)); diff --git a/src/libcore/rt/local.rs b/src/libcore/rt/local.rs index c054ba68d1082..471d6983db2aa 100644 --- a/src/libcore/rt/local.rs +++ b/src/libcore/rt/local.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use option::{Option, Some, None}; use rt::sched::Scheduler; +use rt::task::Task; use rt::local_ptr; pub trait Local { @@ -17,6 +19,7 @@ pub trait Local { fn exists() -> bool; fn borrow(f: &fn(&mut Self)); unsafe fn unsafe_borrow() -> *mut Self; + unsafe fn try_unsafe_borrow() -> Option<*mut Self>; } impl Local for Scheduler { @@ -25,6 +28,44 @@ impl Local for Scheduler { fn exists() -> bool { local_ptr::exists() } fn borrow(f: &fn(&mut Scheduler)) { unsafe { local_ptr::borrow(f) } } unsafe fn unsafe_borrow() -> *mut Scheduler { local_ptr::unsafe_borrow() } + unsafe fn try_unsafe_borrow() -> Option<*mut Scheduler> { abort!("unimpl") } +} + +impl Local for Task { + fn put(value: ~Task) { abort!("unimpl") } + fn take() -> ~Task { abort!("unimpl") } + fn exists() -> bool { abort!("unimpl") } + fn borrow(f: &fn(&mut Task)) { + do Local::borrow:: |sched| { + match sched.current_task { + Some(~ref mut task) => { + f(&mut *task.task) + } + None => { + abort!("no scheduler") + } + } + } + } + unsafe fn unsafe_borrow() -> *mut Task { + match (*Local::unsafe_borrow::()).current_task { + Some(~ref mut task) => { + let s: *mut Task = &mut *task.task; + return s; + } + None => { + // Don't fail. Infinite recursion + abort!("no scheduler") + } + } + } + unsafe fn try_unsafe_borrow() -> Option<*mut Task> { + if Local::exists::() { + Some(Local::unsafe_borrow()) + } else { + None + } + } } #[cfg(test)] diff --git a/src/libcore/rt/task.rs b/src/libcore/rt/task.rs index 3f98ad74ef260..0314137fc7f92 100644 --- a/src/libcore/rt/task.rs +++ b/src/libcore/rt/task.rs @@ -63,7 +63,7 @@ impl Task { pub fn run(&mut self, f: &fn()) { // This is just an assertion that `run` was called unsafely // and this instance of Task is still accessible. - do borrow_local_task |task| { + do Local::borrow:: |task| { assert!(ptr::ref_eq(task, self)); } @@ -88,7 +88,7 @@ impl Task { fn destroy(&mut self) { // This is just an assertion that `destroy` was called unsafely // and this instance of Task is still accessible. - do borrow_local_task |task| { + do Local::borrow:: |task| { assert!(ptr::ref_eq(task, self)); } match self.storage { @@ -150,42 +150,6 @@ impl Unwinder { } } -/// Borrow a pointer to the installed local services. -/// Fails (likely aborting the process) if local services are not available. -pub fn borrow_local_task(f: &fn(&mut Task)) { - do Local::borrow:: |sched| { - match sched.current_task { - Some(~ref mut task) => { - f(&mut *task.task) - } - None => { - fail!("no local services for schedulers yet") - } - } - } -} - -pub unsafe fn unsafe_borrow_local_task() -> *mut Task { - match (*Local::unsafe_borrow::()).current_task { - Some(~ref mut task) => { - let s: *mut Task = &mut *task.task; - return s; - } - None => { - // Don't fail. Infinite recursion - abort!("no local services for schedulers yet") - } - } -} - -pub unsafe fn unsafe_try_borrow_local_task() -> Option<*mut Task> { - if Local::exists::() { - Some(unsafe_borrow_local_task()) - } else { - None - } -} - #[cfg(test)] mod test { use rt::test::*; diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index c21ce5213142b..1f8dc8c00b5c9 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -204,7 +204,8 @@ impl FailWithCause for &'static str { pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { use option::Option; use rt::{context, OldTaskContext, TaskContext}; - use rt::task::{unsafe_borrow_local_task, Unwinder}; + use rt::task::{Task, Unwinder}; + use rt::local::Local; let context = context(); match context { @@ -233,7 +234,7 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { gc::cleanup_stack_for_failure(); - let task = unsafe_borrow_local_task(); + let task = Local::unsafe_borrow::(); let unwinder: &mut Option = &mut (*task).unwinder; match *unwinder { Some(ref mut unwinder) => unwinder.begin_unwind(), diff --git a/src/libcore/task/local_data_priv.rs b/src/libcore/task/local_data_priv.rs index 6871dd3aecd88..2f97eaacf4be2 100644 --- a/src/libcore/task/local_data_priv.rs +++ b/src/libcore/task/local_data_priv.rs @@ -18,7 +18,7 @@ use task::rt; use local_data::LocalDataKey; use super::rt::rust_task; -use rt::task::LocalStorage; +use rt::task::{Task, LocalStorage}; pub enum Handle { OldHandle(*rust_task), @@ -28,14 +28,14 @@ pub enum Handle { impl Handle { pub fn new() -> Handle { use rt::{context, OldTaskContext}; - use rt::task::unsafe_borrow_local_task; + use rt::local::Local; unsafe { match context() { OldTaskContext => { OldHandle(rt::rust_get_task()) } _ => { - let task = unsafe_borrow_local_task(); + let task = Local::unsafe_borrow::(); NewHandle(&mut (*task).storage) } } diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index 372a9f6defaff..490a69248eecb 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -504,7 +504,8 @@ pub fn failing() -> bool { //! True if the running task has failed use rt::{context, OldTaskContext}; - use rt::task::borrow_local_task; + use rt::local::Local; + use rt::task::Task; match context() { OldTaskContext => { @@ -514,7 +515,7 @@ pub fn failing() -> bool { } _ => { let mut unwinding = false; - do borrow_local_task |local| { + do Local::borrow:: |local| { unwinding = match local.unwinder { Some(unwinder) => { unwinder.unwinding diff --git a/src/libcore/unstable/lang.rs b/src/libcore/unstable/lang.rs index 1efe5d0d1a41d..350b18d454169 100644 --- a/src/libcore/unstable/lang.rs +++ b/src/libcore/unstable/lang.rs @@ -17,7 +17,8 @@ use managed::raw::BoxRepr; use str; use sys; use rt::{context, OldTaskContext}; -use rt::task::borrow_local_task; +use rt::task::Task; +use rt::local::Local; use option::{Option, Some, None}; use io; use rt::global_heap; @@ -243,7 +244,7 @@ pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { } _ => { let mut alloc = ::ptr::null(); - do borrow_local_task |task| { + do Local::borrow:: |task| { alloc = task.heap.alloc(td as *c_void, size as uint) as *c_char; } return alloc; @@ -261,7 +262,7 @@ pub unsafe fn local_free(ptr: *c_char) { rustrt::rust_upcall_free_noswitch(ptr); } _ => { - do borrow_local_task |task| { + do Local::borrow:: |task| { task.heap.free(ptr as *c_void); } } From a246e8faf362a1615b5bb4938455dd70642e0f4b Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 19 May 2013 19:11:59 -0700 Subject: [PATCH 15/15] core::rt: Convert unsafe_borrow_io to a Local impl --- src/libcore/rt/io/net/tcp.rs | 11 +++++++---- src/libcore/rt/local.rs | 15 +++++++++++++++ src/libcore/rt/sched.rs | 6 ------ src/libcore/rt/uv/uvio.rs | 15 +++++++-------- 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/src/libcore/rt/io/net/tcp.rs b/src/libcore/rt/io/net/tcp.rs index d900341998117..f7c03c13a5812 100644 --- a/src/libcore/rt/io/net/tcp.rs +++ b/src/libcore/rt/io/net/tcp.rs @@ -10,13 +10,13 @@ use option::{Option, Some, None}; use result::{Ok, Err}; -use rt::sched::unsafe_borrow_io; use rt::io::net::ip::IpAddr; use rt::io::{Reader, Writer, Listener}; use rt::io::{io_error, read_error, EndOfFile}; -use rt::rtio::{IoFactory, +use rt::rtio::{IoFactory, IoFactoryObject, RtioTcpListener, RtioTcpListenerObject, RtioTcpStream, RtioTcpStreamObject}; +use rt::local::Local; pub struct TcpStream { rtstream: ~RtioTcpStreamObject @@ -32,7 +32,7 @@ impl TcpStream { pub fn connect(addr: IpAddr) -> Option { let stream = unsafe { rtdebug!("borrowing io to connect"); - let io = unsafe_borrow_io(); + let io = Local::unsafe_borrow::(); rtdebug!("about to connect"); (*io).tcp_connect(addr) }; @@ -88,7 +88,10 @@ pub struct TcpListener { impl TcpListener { pub fn bind(addr: IpAddr) -> Option { - let listener = unsafe { (*unsafe_borrow_io()).tcp_bind(addr) }; + let listener = unsafe { + let io = Local::unsafe_borrow::(); + (*io).tcp_bind(addr) + }; match listener { Ok(l) => { Some(TcpListener { diff --git a/src/libcore/rt/local.rs b/src/libcore/rt/local.rs index 471d6983db2aa..64a384ddff0b9 100644 --- a/src/libcore/rt/local.rs +++ b/src/libcore/rt/local.rs @@ -12,6 +12,7 @@ use option::{Option, Some, None}; use rt::sched::Scheduler; use rt::task::Task; use rt::local_ptr; +use rt::rtio::{EventLoop, IoFactoryObject}; pub trait Local { fn put(value: ~Self); @@ -68,6 +69,20 @@ impl Local for Task { } } +// XXX: This formulation won't work once ~IoFactoryObject is a real trait pointer +impl Local for IoFactoryObject { + fn put(value: ~IoFactoryObject) { abort!("unimpl") } + fn take() -> ~IoFactoryObject { abort!("unimpl") } + fn exists() -> bool { abort!("unimpl") } + fn borrow(f: &fn(&mut IoFactoryObject)) { abort!("unimpl") } + unsafe fn unsafe_borrow() -> *mut IoFactoryObject { + let sched = Local::unsafe_borrow::(); + let io: *mut IoFactoryObject = (*sched).event_loop.io().unwrap(); + return io; + } + unsafe fn try_unsafe_borrow() -> Option<*mut IoFactoryObject> { abort!("unimpl") } +} + #[cfg(test)] mod test { use rt::sched::Scheduler; diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs index 20c24adaa0ad0..50c6a894093f3 100644 --- a/src/libcore/rt/sched.rs +++ b/src/libcore/rt/sched.rs @@ -401,12 +401,6 @@ pub impl Coroutine { } } -pub unsafe fn unsafe_borrow_io() -> *mut IoFactoryObject { - let sched = Local::unsafe_borrow::(); - let io: *mut IoFactoryObject = (*sched).event_loop.io().unwrap(); - return io; -} - #[cfg(test)] mod test { use int; diff --git a/src/libcore/rt/uv/uvio.rs b/src/libcore/rt/uv/uvio.rs index b89dfcab3d330..cacd67314ebac 100644 --- a/src/libcore/rt/uv/uvio.rs +++ b/src/libcore/rt/uv/uvio.rs @@ -19,7 +19,6 @@ use rt::io::net::ip::IpAddr; use rt::uv::*; use rt::uv::idle::IdleWatcher; use rt::rtio::*; -use rt::sched::unsafe_borrow_io; use rt::sched::Scheduler; use rt::io::{standard_error, OtherIoError}; use rt::tube::Tube; @@ -359,7 +358,7 @@ impl RtioTcpStream for UvTcpStream { fn test_simple_io_no_connect() { do run_in_newsched_task { unsafe { - let io = unsafe_borrow_io(); + let io = Local::unsafe_borrow::(); let addr = next_test_ip4(); let maybe_chan = (*io).tcp_connect(addr); assert!(maybe_chan.is_err()); @@ -375,7 +374,7 @@ fn test_simple_tcp_server_and_client() { // Start the server first so it's listening when we connect do spawntask_immediately { unsafe { - let io = unsafe_borrow_io(); + let io = Local::unsafe_borrow::(); let mut listener = (*io).tcp_bind(addr).unwrap(); let mut stream = listener.accept().unwrap(); let mut buf = [0, .. 2048]; @@ -390,7 +389,7 @@ fn test_simple_tcp_server_and_client() { do spawntask_immediately { unsafe { - let io = unsafe_borrow_io(); + let io = Local::unsafe_borrow::(); let mut stream = (*io).tcp_connect(addr).unwrap(); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); } @@ -404,7 +403,7 @@ fn test_read_and_block() { let addr = next_test_ip4(); do spawntask_immediately { - let io = unsafe { unsafe_borrow_io() }; + let io = unsafe { Local::unsafe_borrow::() }; let mut listener = unsafe { (*io).tcp_bind(addr).unwrap() }; let mut stream = listener.accept().unwrap(); let mut buf = [0, .. 2048]; @@ -440,7 +439,7 @@ fn test_read_and_block() { do spawntask_immediately { unsafe { - let io = unsafe_borrow_io(); + let io = Local::unsafe_borrow::(); let mut stream = (*io).tcp_connect(addr).unwrap(); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); stream.write([0, 1, 2, 3, 4, 5, 6, 7]); @@ -460,7 +459,7 @@ fn test_read_read_read() { do spawntask_immediately { unsafe { - let io = unsafe_borrow_io(); + let io = Local::unsafe_borrow::(); let mut listener = (*io).tcp_bind(addr).unwrap(); let mut stream = listener.accept().unwrap(); let buf = [1, .. 2048]; @@ -474,7 +473,7 @@ fn test_read_read_read() { do spawntask_immediately { unsafe { - let io = unsafe_borrow_io(); + let io = Local::unsafe_borrow::(); let mut stream = (*io).tcp_connect(addr).unwrap(); let mut buf = [0, .. 2048]; let mut total_bytes_read = 0;