replace impl of globa_async_handle with one using atomic compare-and-swap

This commit is contained in:
Jeff Olson 2012-04-16 23:21:27 -07:00 committed by Brian Anderson
parent d7a87aa0a1
commit 253fad7788
5 changed files with 43 additions and 29 deletions

View file

@ -15,8 +15,10 @@ import ll = uv_ll;
native mod rustrt {
fn rust_uv_get_kernel_global_chan_ptr() -> *libc::uintptr_t;
fn rust_uv_get_kernel_global_async_handle() -> **libc::c_void;
fn rust_uv_set_kernel_global_async_handle(handle: *ll::uv_async_t);
fn rust_uv_get_kernel_global_async_handle() -> *libc::uintptr_t;
fn rust_compare_and_swap_ptr(address: *libc::uintptr_t,
oldval: libc::uintptr_t,
newval: libc::uintptr_t) -> bool;
}
#[doc = "
@ -75,7 +77,8 @@ fn get_global_loop() -> high_level_loop unsafe {
outer_global_loop_body(port);
};
log(debug, "after priv::chan_from_global_ptr");
let handle = get_global_async_handle();
let handle = get_global_async_handle_native_representation()
as **ll::uv_async_t;
ret { async_handle: handle, op_chan: chan };
}
}
@ -104,7 +107,7 @@ unsafe fn run_high_level_loop(loop_ptr: *libc::c_void,
msg_po: comm::port<high_level_msg>,
before_run: fn~(*global_loop_data),
before_msg_drain: fn~() -> bool,
before_tear_down: fn~()) {
before_tear_down: fn~(*global_loop_data)) {
// set up the special async handle we'll use to allow multi-task
// communication with this loop
let async = ll::async_t();
@ -117,7 +120,7 @@ unsafe fn run_high_level_loop(loop_ptr: *libc::c_void,
async_handle: async_handle,
mut active: true,
before_msg_drain: before_msg_drain,
before_tear_down: before_tear_down,
before_tear_down: gdc_callback(before_tear_down),
msg_po_ptr: ptr::addr_of(msg_po),
mut refd_handles: [mut],
mut unrefd_handles: [mut]
@ -263,7 +266,11 @@ crust fn tear_down_close_cb(handle: *ll::uv_async_t) unsafe {
fn high_level_tear_down(data: *global_loop_data) unsafe {
log(debug, "high_level_tear_down() called, close async_handle");
// call user-suppled before_tear_down cb
(*data).before_tear_down();
alt (*data).before_tear_down {
gdc_callback(cb) {
cb(data);
}
}
let async_handle = (*data).async_handle;
ll::close(async_handle as *libc::c_void, tear_down_close_cb);
}
@ -330,19 +337,32 @@ enum high_level_msg {
tear_down
}
fn get_global_async_handle() -> **ll::uv_async_t {
ret rustrt::rust_uv_get_kernel_global_async_handle() as **ll::uv_async_t;
unsafe fn get_global_async_handle_native_representation()
-> *libc::uintptr_t {
ret rustrt::rust_uv_get_kernel_global_async_handle();
}
fn set_global_async_handle(handle: *ll::uv_async_t) {
rustrt::rust_uv_set_kernel_global_async_handle(handle);
unsafe fn get_global_async_handle() -> *ll::uv_async_t {
ret (*get_global_async_handle_native_representation()) as *ll::uv_async_t;
}
unsafe fn set_global_async_handle(old: *ll::uv_async_t,
new_ptr: *ll::uv_async_t) {
rustrt::rust_compare_and_swap_ptr(
get_global_async_handle_native_representation(),
old as libc::uintptr_t,
new_ptr as libc::uintptr_t);
}
enum global_data_callback {
gdc_callback(fn~(*global_loop_data))
}
type global_loop_data = {
async_handle: *ll::uv_async_t,
mut active: bool,
before_msg_drain: fn~() -> bool,
before_tear_down: fn~(),
before_tear_down: global_data_callback,
msg_po_ptr: *comm::port<high_level_msg>,
mut refd_handles: [mut *libc::c_void],
mut unrefd_handles: [mut *libc::c_void]
@ -399,7 +419,8 @@ unsafe fn inner_global_loop_body(weak_exit_po_in: comm::port<()>,
// before_run
{|data|
// set the handle as the global
set_global_async_handle((*data).async_handle);
set_global_async_handle(0u as *ll::uv_async_t,
(*data).async_handle);
// when this is ran, our async_handle is set up, so let's
// do an async_send with it
ll::async_send((*data).async_handle);
@ -422,8 +443,9 @@ unsafe fn inner_global_loop_body(weak_exit_po_in: comm::port<()>,
}
},
// before_tear_down
{||
set_global_async_handle(0 as *ll::uv_async_t);
{|data|
set_global_async_handle((*data).async_handle,
0 as *ll::uv_async_t);
});
// supposed to return a bool to indicate to the enclosing loop whether
// it should continue or not..

View file

@ -27,10 +27,9 @@ rust_kernel::rust_kernel(rust_env *env) :
// set up storage of pointers needed to
// access the global loop.
global_loop_chan = 0;
int foo = 0;
async_handle_stub = (void*)&foo;
global_async_handle = &async_handle_stub;
*global_async_handle = (void*)0;
async_handle_inner = (uintptr_t)0;
global_async_handle = &async_handle_inner;
*global_async_handle = (uintptr_t)0;
// Create the single threaded scheduler that will run on the platform's
// main thread

View file

@ -75,8 +75,8 @@ class rust_kernel {
// Used to communicate with the process-side, global libuv loop
uintptr_t global_loop_chan;
void* async_handle_stub;
void** global_async_handle;
uintptr_t async_handle_inner;
uintptr_t* global_async_handle;
public:
struct rust_env *env;
@ -124,9 +124,7 @@ public:
bool send_to_port(rust_port_id chan, void *sptr);
uintptr_t* get_global_loop() { return &global_loop_chan; }
void** get_global_async_handle() { return global_async_handle; }
void set_global_async_handle(void* handle) {
*global_async_handle = handle; }
uintptr_t* get_global_async_handle() { return global_async_handle; }
};
template <typename T> struct kernel_owned {

View file

@ -446,11 +446,7 @@ rust_uv_get_kernel_global_chan_ptr() {
return result;
}
extern "C" void**
extern "C" uintptr_t*
rust_uv_get_kernel_global_async_handle() {
return rust_get_current_task()->kernel->get_global_async_handle();
}
extern "C" void
rust_uv_set_kernel_global_async_handle(uv_async_t* handle) {
rust_get_current_task()->kernel->set_global_async_handle((void*)handle);
}

View file

@ -138,7 +138,6 @@ rust_uv_get_base_from_buf
rust_uv_get_len_from_buf
rust_uv_get_kernel_global_chan_ptr
rust_uv_get_kernel_global_async_handle
rust_uv_set_kernel_global_async_handle
rust_dbg_lock_create
rust_dbg_lock_destroy
rust_dbg_lock_lock