Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A new scheduler prototype #5022

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions src/libcore/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,27 @@ pub pure fn get_ref<T>(opt: &r/Option<T>) -> &r/T {
}
}

pub pure fn get_mut_ref<T>(opt: &r/mut Option<T>) -> &r/mut T {
/*!
Gets a mutable reference to the value inside an option.

# Failure

Fails if the value equals `None`

# Safety note

In general, because this function may fail, its use is discouraged
(calling `get` on `None` is akin to dereferencing a null pointer).
Instead, prefer to use pattern matching and handle the `None`
case explicitly.
*/
match *opt {
Some(ref mut x) => x,
None => die!(~"option::get_mut_ref none")
}
}

#[inline(always)]
pub pure fn map<T, U>(opt: &r/Option<T>, f: fn(x: &r/T) -> U) -> Option<U> {
//! Maps a `some` value by reference from one type to another
Expand Down Expand Up @@ -332,6 +353,23 @@ impl<T> Option<T> {
#[inline(always)]
pure fn get_ref(&self) -> &self/T { get_ref(self) }

/**
Gets a mutable reference to the value inside an option.

# Failure

Fails if the value equals `None`

# Safety note

In general, because this function may fail, its use is discouraged
(calling `get` on `None` is akin to dereferencing a null pointer).
Instead, prefer to use pattern matching and handle the `None`
case explicitly.
*/
#[inline(always)]
pure fn get_mut_ref(&mut self) -> &self/mut T { get_mut_ref(self) }

/**
* Gets the value out of an option without copying.
*
Expand Down
20 changes: 8 additions & 12 deletions src/libcore/private.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ for it to terminate.
The executing thread has no access to a task pointer and will be using
a normal large stack.
*/
pub unsafe fn run_in_bare_thread(f: ~fn()) {
pub fn run_in_bare_thread(f: ~fn()) {
let (port, chan) = pipes::stream();
// FIXME #4525: Unfortunate that this creates an extra scheduler but it's
// necessary since rust_raw_thread_join_delete is blocking
Expand All @@ -80,22 +80,18 @@ pub unsafe fn run_in_bare_thread(f: ~fn()) {

#[test]
fn test_run_in_bare_thread() {
unsafe {
let i = 100;
do run_in_bare_thread {
assert i == 100;
}
let i = 100;
do run_in_bare_thread {
assert i == 100;
}
}

#[test]
fn test_run_in_bare_thread_exchange() {
unsafe {
// Does the exchange heap work without the runtime?
let i = ~100;
do run_in_bare_thread {
assert i == ~100;
}
// Does the exchange heap work without the runtime?
let i = ~100;
do run_in_bare_thread {
assert i == ~100;
}
}

Expand Down
34 changes: 34 additions & 0 deletions src/libstd/uv_ll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,19 @@

use core::libc::size_t;
use core::libc;
use core::libc::c_void;
use core::prelude::*;
use core::ptr::to_unsafe_ptr;
use core::ptr;
use core::str;
use core::vec;
use core::pipes::{stream, Chan, SharedChan, Port};

pub type uv_handle_t = c_void;
pub type uv_loop_t = c_void;
pub type uv_idle_t = c_void;
pub type uv_idle_cb = *u8;

// libuv struct mappings
pub struct uv_ip4_addr {
ip: ~[u8],
Expand Down Expand Up @@ -668,13 +674,21 @@ pub mod uv_ll_struct_stubgen {

#[nolink]
extern mod rustrt {

// libuv public API
unsafe fn rust_uv_loop_new() -> *libc::c_void;
unsafe fn rust_uv_loop_delete(lp: *libc::c_void);
unsafe fn rust_uv_run(loop_handle: *libc::c_void);
unsafe fn rust_uv_close(handle: *libc::c_void, cb: *u8);
unsafe fn rust_uv_walk(loop_handle: *libc::c_void, cb: *u8,
arg: *libc::c_void);

unsafe fn rust_uv_idle_new() -> *uv_idle_t;
unsafe fn rust_uv_idle_delete(handle: *uv_idle_t);
unsafe fn rust_uv_idle_init(loop_handle: *uv_loop_t, handle: *uv_idle_t) -> libc::c_int;
unsafe fn rust_uv_idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> libc::c_int;
unsafe fn rust_uv_idle_stop(handle: *uv_idle_t) -> libc::c_int;

unsafe fn rust_uv_async_send(handle: *uv_async_t);
unsafe fn rust_uv_async_init(loop_handle: *libc::c_void,
async_handle: *uv_async_t,
Expand Down Expand Up @@ -828,6 +842,26 @@ pub unsafe fn walk(loop_handle: *libc::c_void, cb: *u8, arg: *libc::c_void) {
rustrt::rust_uv_walk(loop_handle, cb, arg);
}

pub unsafe fn idle_new() -> *uv_idle_t {
rustrt::rust_uv_idle_new()
}

pub unsafe fn idle_delete(handle: *uv_idle_t) {
rustrt::rust_uv_idle_delete(handle)
}

pub unsafe fn idle_init(loop_handle: *uv_loop_t, handle: *uv_idle_t) -> libc::c_int {
rustrt::rust_uv_idle_init(loop_handle, handle)
}

pub unsafe fn idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> libc::c_int {
rustrt::rust_uv_idle_start(handle, cb)
}

pub unsafe fn idle_stop(handle: *uv_idle_t) -> libc::c_int {
rustrt::rust_uv_idle_stop(handle)
}

pub unsafe fn tcp_init(loop_handle: *libc::c_void, handle: *uv_tcp_t)
-> libc::c_int {
return rustrt::rust_uv_tcp_init(loop_handle, handle);
Expand Down
13 changes: 13 additions & 0 deletions src/rt/rust.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@

void* global_crate_map = NULL;

#ifndef _WIN32
pthread_key_t sched_key;
#else
DWORD sched_key;
#endif

extern "C" void*
rust_get_sched_tls_key() {
return &sched_key;
}

/**
The runtime entrypoint. The (C ABI) main function generated by rustc calls
`rust_start`, providing the address of the Rust ABI main function, the
Expand All @@ -30,6 +41,8 @@ void* global_crate_map = NULL;
extern "C" CDECL int
rust_start(uintptr_t main_fn, int argc, char **argv, void* crate_map) {

pthread_key_create(&sched_key, NULL);

// Load runtime configuration options from the environment.
// FIXME #1497: Should provide a way to get these from the command
// line as well.
Expand Down
14 changes: 6 additions & 8 deletions src/rt/rust_builtin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,7 @@ vec_reserve_shared_actual(type_desc* ty, rust_vec_box** vp,
extern "C" CDECL void
vec_reserve_shared(type_desc* ty, rust_vec_box** vp,
size_t n_elts) {
rust_task *task = rust_get_current_task();
reserve_vec_exact(task, vp, n_elts * ty->size);
reserve_vec_exact(vp, n_elts * ty->size);
}

extern "C" CDECL rust_vec*
Expand Down Expand Up @@ -523,9 +522,8 @@ void tm_to_rust_tm(tm* in_tm, rust_tm* out_tm, int32_t gmtoff,
out_tm->tm_nsec = nsec;

if (zone != NULL) {
rust_task *task = rust_get_current_task();
size_t size = strlen(zone);
reserve_vec_exact(task, &out_tm->tm_zone, size + 1);
reserve_vec_exact(&out_tm->tm_zone, size + 1);
memcpy(out_tm->tm_zone->body.data, zone, size);
out_tm->tm_zone->body.fill = size + 1;
out_tm->tm_zone->body.data[size] = '\0';
Expand Down Expand Up @@ -901,20 +899,20 @@ extern "C" CDECL void record_sp_limit(void *limit);

class raw_thread: public rust_thread {
public:
fn_env_pair *fn;
fn_env_pair fn;

raw_thread(fn_env_pair *fn) : fn(fn) { }
raw_thread(fn_env_pair fn) : fn(fn) { }

virtual void run() {
record_sp_limit(0);
fn->f(NULL, fn->env, NULL);
fn.f(NULL, fn.env, NULL);
}
};

extern "C" raw_thread*
rust_raw_thread_start(fn_env_pair *fn) {
assert(fn);
raw_thread *thread = new raw_thread(fn);
raw_thread *thread = new raw_thread(*fn);
thread->start();
return thread;
}
Expand Down
7 changes: 6 additions & 1 deletion src/rt/rust_upcall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,12 @@ extern "C" CDECL void
upcall_fail(char const *expr,
char const *file,
size_t line) {
rust_task *task = rust_get_current_task();
rust_task *task = rust_try_get_current_task();
if (task == NULL) {
// NOTE: Need to think about what to do here
printf("failure outside of a task");
abort();
}
s_fail_args args = {task,expr,file,line};
UPCALL_SWITCH_STACK(task, &args, upcall_s_fail);
}
Expand Down
11 changes: 6 additions & 5 deletions src/rt/rust_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,17 +82,18 @@ inline void reserve_vec_exact_shared(rust_task* task, rust_vec_box** vpp,
}
}

inline void reserve_vec_exact(rust_task* task, rust_vec_box** vpp,
inline void reserve_vec_exact(rust_vec_box** vpp,
size_t size) {
if (size > (*vpp)->body.alloc) {
*vpp = (rust_vec_box*)task->kernel
->realloc(*vpp, size + sizeof(rust_vec_box));
rust_exchange_alloc exchange_alloc;
*vpp = (rust_vec_box*)exchange_alloc
.realloc(*vpp, size + sizeof(rust_vec_box));
(*vpp)->body.alloc = size;
}
}

inline void reserve_vec(rust_task* task, rust_vec_box** vpp, size_t size) {
reserve_vec_exact(task, vpp, next_power_of_two(size));
inline void reserve_vec(rust_vec_box** vpp, size_t size) {
reserve_vec_exact(vpp, next_power_of_two(size));
}

typedef rust_vec_box rust_str;
Expand Down
41 changes: 25 additions & 16 deletions src/rt/rust_uv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,16 +376,7 @@ current_kernel_malloc_alloc_cb(uv_handle_t* handle,

extern "C" void
rust_uv_buf_init(uv_buf_t* out_buf, char* base, size_t len) {
rust_task* task = rust_get_current_task();
LOG(task, stdlib,"rust_uv_buf_init: base: %lu" \
"len: %lu",
(unsigned long int)base,
(unsigned long int)len);
*out_buf = uv_buf_init(base, len);
LOG(task, stdlib, "rust_uv_buf_init: after: "
"result->base: %" PRIxPTR " len: %" PRIxPTR,
(unsigned long int)(*out_buf).base,
(unsigned long int)(*out_buf).len);
}

extern "C" uv_loop_t*
Expand Down Expand Up @@ -481,18 +472,11 @@ rust_uv_free_base_of_buf(uv_buf_t buf) {

extern "C" struct sockaddr_in
rust_uv_ip4_addr(const char* ip, int port) {
rust_task* task = rust_get_current_task();
LOG(task, stdlib, "before creating addr_ptr.. ip %s" \
" port %d\n", ip, port);
struct sockaddr_in addr = uv_ip4_addr(ip, port);
LOG(task, stdlib, "after creating .. port: %d", addr.sin_port);
return addr;
}
extern "C" struct sockaddr_in6
rust_uv_ip6_addr(const char* ip, int port) {
rust_task* task = rust_get_current_task();
LOG(task, stdlib, "before creating addr_ptr.. ip %s" \
" port %d\n", ip, port);
return uv_ip6_addr(ip, port);
}
extern "C" int
Expand Down Expand Up @@ -554,3 +538,28 @@ extern "C" sockaddr_in6*
rust_uv_addrinfo_as_sockaddr_in6(addrinfo* input) {
return (sockaddr_in6*)input->ai_addr;
}

extern "C" uv_idle_t*
rust_uv_idle_new() {
return new uv_idle_t;
}

extern "C" void
rust_uv_idle_delete(uv_idle_t* handle) {
delete handle;
}

extern "C" int
rust_uv_idle_init(uv_loop_t* loop, uv_idle_t* idle) {
return uv_idle_init(loop, idle);
}

extern "C" int
rust_uv_idle_start(uv_idle_t* idle, uv_idle_cb cb) {
return uv_idle_start(idle, cb);
}

extern "C" int
rust_uv_idle_stop(uv_idle_t* idle) {
return uv_idle_stop(idle);
}
7 changes: 7 additions & 0 deletions src/rt/rustrt.def.in
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ rust_uv_current_kernel_malloc
rust_uv_current_kernel_free
rust_uv_getaddrinfo
rust_uv_freeaddrinfo
rust_uv_idle_new
rust_uv_idle_delete
rust_uv_idle_init
rust_uv_idle_start
rust_uv_idle_stop
rust_dbg_lock_create
rust_dbg_lock_destroy
rust_dbg_lock_lock
Expand Down Expand Up @@ -191,3 +196,5 @@ rust_get_global_data_ptr
rust_inc_weak_task_count
rust_dec_weak_task_count
rust_get_exchange_count_ptr
rust_get_sched_tls_key
swap_registers
44 changes: 44 additions & 0 deletions src/test/run-pass/newrt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// compile-flags: --test

// Using uv_ll, cell, net::ip
extern mod std;

// Some basic logging
fn macros() {
macro_rules! rtdebug_ (
($( $arg:expr),+) => ( {
dumb_println(fmt!( $($arg),+ ));

fn dumb_println(s: &str) {
use core::str::as_c_str;
use core::libc::c_char;

extern {
fn printf(s: *c_char);
}

do as_c_str(s.to_str() + "\n") |s| {
unsafe { printf(s); }
}
}

} )
)

// An alternate version with no output, for turning off logging
macro_rules! rtdebug (
($( $arg:expr),+) => ( { } )
)
}

// FIXME #4981: Wish I would write these `mod sched #[path = "newrt_sched.rs"];`
#[path = "newrt_sched.rs"] mod sched;
#[path = "newrt_io.rs"] mod io;
#[path = "newrt_uvio.rs"] mod uvio;
#[path = "newrt_uv.rs"] mod uv;
// FIXME: The import in `sched` doesn't resolve unless this is pub!
#[path = "newrt_thread_local_storage.rs"] pub mod thread_local_storage;
#[path = "newrt_work_queue.rs"] mod work_queue;
#[path = "newrt_stack.rs"] mod stack;
#[path = "newrt_context.rs"] mod context;
#[path = "newrt_thread.rs"] mod thread;
Loading