From 253fad77883869511e2030352e86904ac2165d7c Mon Sep 17 00:00:00 2001 From: Jeff Olson Date: Mon, 16 Apr 2012 23:21:27 -0700 Subject: [PATCH] replace impl of globa_async_handle with one using atomic compare-and-swap --- src/libstd/uv_hl.rs | 50 ++++++++++++++++++++++++++++++------------ src/rt/rust_kernel.cpp | 7 +++--- src/rt/rust_kernel.h | 8 +++---- src/rt/rust_uv.cpp | 6 +---- src/rt/rustrt.def.in | 1 - 5 files changed, 43 insertions(+), 29 deletions(-) diff --git a/src/libstd/uv_hl.rs b/src/libstd/uv_hl.rs index 507ac14d68a..bf1bc68ff3a 100644 --- a/src/libstd/uv_hl.rs +++ b/src/libstd/uv_hl.rs @@ -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, 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, 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.. diff --git a/src/rt/rust_kernel.cpp b/src/rt/rust_kernel.cpp index 1ff6fad64ab..9afb010a3db 100644 --- a/src/rt/rust_kernel.cpp +++ b/src/rt/rust_kernel.cpp @@ -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 diff --git a/src/rt/rust_kernel.h b/src/rt/rust_kernel.h index b77f9850bef..58739b2ada0 100644 --- a/src/rt/rust_kernel.h +++ b/src/rt/rust_kernel.h @@ -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 struct kernel_owned { diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index 01517539e7a..a0184f78e5f 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -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); -} diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 6388f846476..8b5d9c8fc8e 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -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