about summary refs log tree commit diff
path: root/src/libstd/rt
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-08-19 04:32:04 -0700
committerbors <bors@rust-lang.org>2013-08-19 04:32:04 -0700
commit81a78161b5354c9cfecd8c659cc1dc3711d347d6 (patch)
treebe212089ce62d2909018cf36d7c3aa563b886d94 /src/libstd/rt
parent3e4f40ec5aee04c0e5386153644255b6beeba095 (diff)
parent0479d946c83cf9ed90bba5b33820ea4118dd8f9e (diff)
downloadrust-81a78161b5354c9cfecd8c659cc1dc3711d347d6.tar.gz
rust-81a78161b5354c9cfecd8c659cc1dc3711d347d6.zip
auto merge of #8535 : nikomatsakis/rust/issue-3678-wrappers-be-gone-2, r=graydon
Long-standing branch to remove foreign function wrappers altogether. Calls to C functions are done "in place" with no stack manipulation; the scheme relies entirely on the correct use of `#[fixed_stack_segment]` to guarantee adequate stack space. A linter is added to detect when `#[fixed_stack_segment]` annotations are missing. An `externfn!` macro is added to make it easier to declare foreign fns and wrappers in one go: this macro may need some refinement, though, for example it might be good to be able to declare a group of foreign fns. I leave that for future work (hopefully somebody else's work :) ).

Fixes #3678.

Diffstat (limited to 'src/libstd/rt')
-rw-r--r--src/libstd/rt/args.rs18
-rw-r--r--src/libstd/rt/borrowck.rs1
-rw-r--r--src/libstd/rt/global_heap.rs9
-rw-r--r--src/libstd/rt/local_heap.rs5
-rw-r--r--src/libstd/rt/local_ptr.rs6
-rw-r--r--src/libstd/rt/logging.rs6
-rw-r--r--src/libstd/rt/mod.rs16
-rw-r--r--src/libstd/rt/stack.rs4
-rw-r--r--src/libstd/rt/task.rs2
-rw-r--r--src/libstd/rt/test.rs3
-rw-r--r--src/libstd/rt/thread.rs6
-rw-r--r--src/libstd/rt/thread_local_storage.rs12
-rw-r--r--src/libstd/rt/util.rs13
-rw-r--r--src/libstd/rt/uv/mod.rs4
-rw-r--r--src/libstd/rt/uv/uvio.rs13
-rw-r--r--src/libstd/rt/uv/uvll.rs151
16 files changed, 254 insertions, 15 deletions
diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs
index 6f26e3bd9ef..71eae56c894 100644
--- a/src/libstd/rt/args.rs
+++ b/src/libstd/rt/args.rs
@@ -118,12 +118,22 @@ mod imp {
         args
     }
 
-    extern {
-        fn rust_take_global_args_lock();
-        fn rust_drop_global_args_lock();
-        fn rust_get_global_args_ptr() -> *mut Option<~~[~str]>;
+    #[cfg(stage0)]
+    mod macro_hack {
+    #[macro_escape];
+    macro_rules! externfn(
+        (fn $name:ident () $(-> $ret_ty:ty),*) => (
+            extern {
+                fn $name() $(-> $ret_ty),*;
+            }
+        )
+    )
     }
 
+    externfn!(fn rust_take_global_args_lock())
+    externfn!(fn rust_drop_global_args_lock())
+    externfn!(fn rust_get_global_args_ptr() -> *mut Option<~~[~str]>)
+
     #[cfg(test)]
     mod tests {
         use option::{Some, None};
diff --git a/src/libstd/rt/borrowck.rs b/src/libstd/rt/borrowck.rs
index ba4cbc66803..6400c1b660d 100644
--- a/src/libstd/rt/borrowck.rs
+++ b/src/libstd/rt/borrowck.rs
@@ -136,6 +136,7 @@ impl DebugPrints for io::fd_t {
     }
 
     unsafe fn write_cstr(&self, p: *c_char) {
+        #[fixed_stack_segment]; #[inline(never)];
         use libc::strlen;
         use vec;
 
diff --git a/src/libstd/rt/global_heap.rs b/src/libstd/rt/global_heap.rs
index 7488b08da42..7d3f5f91774 100644
--- a/src/libstd/rt/global_heap.rs
+++ b/src/libstd/rt/global_heap.rs
@@ -35,8 +35,9 @@ fn align_to(size: uint, align: uint) -> uint {
 }
 
 /// A wrapper around libc::malloc, aborting on out-of-memory
-#[inline]
 pub unsafe fn malloc_raw(size: uint) -> *c_void {
+    #[fixed_stack_segment]; #[inline(never)];
+
     let p = malloc(size as size_t);
     if p.is_null() {
         // we need a non-allocating way to print an error here
@@ -46,8 +47,9 @@ pub unsafe fn malloc_raw(size: uint) -> *c_void {
 }
 
 /// A wrapper around libc::realloc, aborting on out-of-memory
-#[inline]
 pub unsafe fn realloc_raw(ptr: *mut c_void, size: uint) -> *mut c_void {
+    #[fixed_stack_segment]; #[inline(never)];
+
     let p = realloc(ptr, size as size_t);
     if p.is_null() {
         // we need a non-allocating way to print an error here
@@ -97,8 +99,9 @@ pub unsafe fn exchange_free_(ptr: *c_char) {
     exchange_free(ptr)
 }
 
-#[inline]
 pub unsafe fn exchange_free(ptr: *c_char) {
+    #[fixed_stack_segment]; #[inline(never)];
+
     free(ptr as *c_void);
 }
 
diff --git a/src/libstd/rt/local_heap.rs b/src/libstd/rt/local_heap.rs
index 8715e768e32..bca1b4a70f4 100644
--- a/src/libstd/rt/local_heap.rs
+++ b/src/libstd/rt/local_heap.rs
@@ -37,6 +37,7 @@ pub struct LocalHeap {
 }
 
 impl LocalHeap {
+    #[fixed_stack_segment] #[inline(never)]
     pub fn new() -> LocalHeap {
         unsafe {
             // Don't need synchronization for the single-threaded local heap
@@ -55,18 +56,21 @@ impl LocalHeap {
         }
     }
 
+    #[fixed_stack_segment] #[inline(never)]
     pub fn alloc(&mut self, td: *TypeDesc, size: uint) -> *OpaqueBox {
         unsafe {
             return rust_boxed_region_malloc(self.boxed_region, td, size as size_t);
         }
     }
 
+    #[fixed_stack_segment] #[inline(never)]
     pub fn realloc(&mut self, ptr: *OpaqueBox, size: uint) -> *OpaqueBox {
         unsafe {
             return rust_boxed_region_realloc(self.boxed_region, ptr, size as size_t);
         }
     }
 
+    #[fixed_stack_segment] #[inline(never)]
     pub fn free(&mut self, box: *OpaqueBox) {
         unsafe {
             return rust_boxed_region_free(self.boxed_region, box);
@@ -75,6 +79,7 @@ impl LocalHeap {
 }
 
 impl Drop for LocalHeap {
+    #[fixed_stack_segment] #[inline(never)]
     fn drop(&self) {
         unsafe {
             rust_delete_boxed_region(self.boxed_region);
diff --git a/src/libstd/rt/local_ptr.rs b/src/libstd/rt/local_ptr.rs
index 2ec43980419..77303cb8c06 100644
--- a/src/libstd/rt/local_ptr.rs
+++ b/src/libstd/rt/local_ptr.rs
@@ -24,6 +24,8 @@ use unstable::finally::Finally;
 use tls = rt::thread_local_storage;
 
 /// Initialize the TLS key. Other ops will fail if this isn't executed first.
+#[fixed_stack_segment]
+#[inline(never)]
 pub fn init_tls_key() {
     unsafe {
         rust_initialize_rt_tls_key();
@@ -124,6 +126,8 @@ fn tls_key() -> tls::Key {
     }
 }
 
+#[fixed_stack_segment]
+#[inline(never)]
 fn maybe_tls_key() -> Option<tls::Key> {
     unsafe {
         let key: *mut c_void = rust_get_rt_tls_key();
@@ -149,8 +153,6 @@ fn maybe_tls_key() -> Option<tls::Key> {
     }
 
     extern {
-        #[fast_ffi]
         fn rust_get_rt_tls_key() -> *mut c_void;
     }
-
 }
diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs
index 4ee65a2b449..f35304865bb 100644
--- a/src/libstd/rt/logging.rs
+++ b/src/libstd/rt/logging.rs
@@ -57,6 +57,7 @@ impl Logger for StdErrLogger {
 
 /// Configure logging by traversing the crate map and setting the
 /// per-module global logging flags based on the logging spec
+#[fixed_stack_segment] #[inline(never)]
 pub fn init(crate_map: *u8) {
     use c_str::ToCStr;
     use os;
@@ -78,8 +79,13 @@ pub fn init(crate_map: *u8) {
     }
 }
 
+#[fixed_stack_segment] #[inline(never)]
 pub fn console_on() { unsafe { rust_log_console_on() } }
+
+#[fixed_stack_segment] #[inline(never)]
 pub fn console_off() { unsafe { rust_log_console_off() } }
+
+#[fixed_stack_segment] #[inline(never)]
 fn should_log_console() -> bool { unsafe { rust_should_log_console() != 0 } }
 
 extern {
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index 58e86f97f71..db1bfdf1bf5 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -200,6 +200,18 @@ pub fn start_on_main_thread(argc: int, argv: **u8, crate_map: *u8, main: ~fn())
     return exit_code;
 }
 
+#[cfg(stage0)]
+mod macro_hack {
+#[macro_escape];
+macro_rules! externfn(
+    (fn $name:ident ($($arg_name:ident : $arg_ty:ty),*) $(-> $ret_ty:ty),*) => (
+        extern {
+            fn $name($($arg_name : $arg_ty),*) $(-> $ret_ty),*;
+        }
+    )
+)
+}
+
 /// One-time runtime initialization.
 ///
 /// Initializes global state, including frobbing
@@ -215,9 +227,7 @@ pub fn init(argc: int, argv: **u8, crate_map: *u8) {
         rust_update_gc_metadata(crate_map);
     }
 
-    extern {
-        fn rust_update_gc_metadata(crate_map: *u8);
-    }
+    externfn!(fn rust_update_gc_metadata(crate_map: *u8));
 }
 
 /// One-time runtime cleanup.
diff --git a/src/libstd/rt/stack.rs b/src/libstd/rt/stack.rs
index a1269968921..4b2a9b7a6cc 100644
--- a/src/libstd/rt/stack.rs
+++ b/src/libstd/rt/stack.rs
@@ -21,6 +21,8 @@ pub struct StackSegment {
 
 impl StackSegment {
     pub fn new(size: uint) -> StackSegment {
+        #[fixed_stack_segment]; #[inline(never)];
+
         unsafe {
             // Crate a block of uninitialized values
             let mut stack = vec::with_capacity(size);
@@ -50,6 +52,8 @@ impl StackSegment {
 
 impl Drop for StackSegment {
     fn drop(&self) {
+        #[fixed_stack_segment]; #[inline(never)];
+
         unsafe {
             // XXX: Using the FFI to call a C macro. Slow
             rust_valgrind_stack_deregister(self.valgrind_id);
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs
index 01a8882e4f9..22d26005078 100644
--- a/src/libstd/rt/task.rs
+++ b/src/libstd/rt/task.rs
@@ -441,6 +441,8 @@ impl Unwinder {
     }
 
     pub fn begin_unwind(&mut self) -> ! {
+        #[fixed_stack_segment]; #[inline(never)];
+
         self.unwinding = true;
         unsafe {
             rust_begin_unwind(UNWIND_TOKEN);
diff --git a/src/libstd/rt/test.rs b/src/libstd/rt/test.rs
index ca94468e1ad..a9331157749 100644
--- a/src/libstd/rt/test.rs
+++ b/src/libstd/rt/test.rs
@@ -98,6 +98,8 @@ mod darwin_fd_limit {
     static RLIMIT_NOFILE: libc::c_int = 8;
 
     pub unsafe fn raise_fd_limit() {
+        #[fixed_stack_segment]; #[inline(never)];
+
         // The strategy here is to fetch the current resource limits, read the kern.maxfilesperproc
         // sysctl value, and bump the soft resource limit for maxfiles up to the sysctl value.
         use ptr::{to_unsafe_ptr, to_mut_unsafe_ptr, mut_null};
@@ -305,6 +307,7 @@ pub fn cleanup_task(mut task: ~Task) {
 }
 
 /// Get a port number, starting at 9600, for use in tests
+#[fixed_stack_segment] #[inline(never)]
 pub fn next_test_port() -> u16 {
     unsafe {
         return rust_dbg_next_port(base_port() as libc::uintptr_t) as u16;
diff --git a/src/libstd/rt/thread.rs b/src/libstd/rt/thread.rs
index 9f6cf68245e..61db08f4813 100644
--- a/src/libstd/rt/thread.rs
+++ b/src/libstd/rt/thread.rs
@@ -23,6 +23,8 @@ pub struct Thread {
 impl Thread {
     pub fn start(main: ~fn()) -> Thread {
         fn substart(main: &~fn()) -> *raw_thread {
+            #[fixed_stack_segment]; #[inline(never)];
+
             unsafe { rust_raw_thread_start(main) }
         }
         let raw = substart(&main);
@@ -34,6 +36,8 @@ impl Thread {
     }
 
     pub fn join(self) {
+        #[fixed_stack_segment]; #[inline(never)];
+
         assert!(!self.joined);
         let mut this = self;
         unsafe { rust_raw_thread_join(this.raw_thread); }
@@ -43,6 +47,8 @@ impl Thread {
 
 impl Drop for Thread {
     fn drop(&self) {
+        #[fixed_stack_segment]; #[inline(never)];
+
         assert!(self.joined);
         unsafe { rust_raw_thread_delete(self.raw_thread) }
     }
diff --git a/src/libstd/rt/thread_local_storage.rs b/src/libstd/rt/thread_local_storage.rs
index 5041b559ecb..a9cd29c18c9 100644
--- a/src/libstd/rt/thread_local_storage.rs
+++ b/src/libstd/rt/thread_local_storage.rs
@@ -20,16 +20,22 @@ use libc::types::os::arch::extra::{DWORD, LPVOID, BOOL};
 pub type Key = pthread_key_t;
 
 #[cfg(unix)]
+#[fixed_stack_segment]
+#[inline(never)]
 pub unsafe fn create(key: &mut Key) {
     assert_eq!(0, pthread_key_create(key, null()));
 }
 
 #[cfg(unix)]
+#[fixed_stack_segment]
+#[inline(never)]
 pub unsafe fn set(key: Key, value: *mut c_void) {
     assert_eq!(0, pthread_setspecific(key, value));
 }
 
 #[cfg(unix)]
+#[fixed_stack_segment]
+#[inline(never)]
 pub unsafe fn get(key: Key) -> *mut c_void {
     pthread_getspecific(key)
 }
@@ -58,6 +64,8 @@ extern {
 pub type Key = DWORD;
 
 #[cfg(windows)]
+#[fixed_stack_segment]
+#[inline(never)]
 pub unsafe fn create(key: &mut Key) {
     static TLS_OUT_OF_INDEXES: DWORD = 0xFFFFFFFF;
     *key = TlsAlloc();
@@ -65,11 +73,15 @@ pub unsafe fn create(key: &mut Key) {
 }
 
 #[cfg(windows)]
+#[fixed_stack_segment]
+#[inline(never)]
 pub unsafe fn set(key: Key, value: *mut c_void) {
     assert!(0 != TlsSetValue(key, value))
 }
 
 #[cfg(windows)]
+#[fixed_stack_segment]
+#[inline(never)]
 pub unsafe fn get(key: Key) -> *mut c_void {
     TlsGetValue(key)
 }
diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs
index 6280b64ecf5..b8c7c8761e8 100644
--- a/src/libstd/rt/util.rs
+++ b/src/libstd/rt/util.rs
@@ -17,6 +17,8 @@ use str::StrSlice;
 
 /// Get the number of cores available
 pub fn num_cpus() -> uint {
+    #[fixed_stack_segment]; #[inline(never)];
+
     unsafe {
         return rust_get_num_cpus();
     }
@@ -94,11 +96,16 @@ memory and partly incapable of presentation to others.",
     rterrln!("%s", "");
     rterrln!("fatal runtime error: %s", msg);
 
-    unsafe { libc::abort(); }
+    abort();
+
+    fn abort() -> ! {
+        #[fixed_stack_segment]; #[inline(never)];
+        unsafe { libc::abort() }
+    }
 }
 
 pub fn set_exit_status(code: int) {
-
+    #[fixed_stack_segment]; #[inline(never)];
     unsafe {
         return rust_set_exit_status_newrt(code as libc::uintptr_t);
     }
@@ -109,7 +116,7 @@ pub fn set_exit_status(code: int) {
 }
 
 pub fn get_exit_status() -> int {
-
+    #[fixed_stack_segment]; #[inline(never)];
     unsafe {
         return rust_get_exit_status_newrt() as int;
     }
diff --git a/src/libstd/rt/uv/mod.rs b/src/libstd/rt/uv/mod.rs
index 59833a16ed8..9312efbf03e 100644
--- a/src/libstd/rt/uv/mod.rs
+++ b/src/libstd/rt/uv/mod.rs
@@ -310,6 +310,8 @@ pub fn slice_to_uv_buf(v: &[u8]) -> Buf {
 
 /// Transmute an owned vector to a Buf
 pub fn vec_to_uv_buf(v: ~[u8]) -> Buf {
+    #[fixed_stack_segment]; #[inline(never)];
+
     unsafe {
         let data = malloc(v.len() as size_t) as *u8;
         assert!(data.is_not_null());
@@ -323,6 +325,8 @@ pub fn vec_to_uv_buf(v: ~[u8]) -> Buf {
 
 /// Transmute a Buf that was once a ~[u8] back to ~[u8]
 pub fn vec_from_uv_buf(buf: Buf) -> Option<~[u8]> {
+    #[fixed_stack_segment]; #[inline(never)];
+
     if !(buf.len == 0 && buf.base.is_null()) {
         let v = unsafe { vec::from_buf(buf.base, buf.len as uint) };
         unsafe { free(buf.base as *c_void) };
diff --git a/src/libstd/rt/uv/uvio.rs b/src/libstd/rt/uv/uvio.rs
index a26b8a3ad59..d4794da9b0f 100644
--- a/src/libstd/rt/uv/uvio.rs
+++ b/src/libstd/rt/uv/uvio.rs
@@ -45,6 +45,7 @@ enum SocketNameKind {
 
 fn socket_name<T, U: Watcher + NativeHandle<*T>>(sk: SocketNameKind,
                                                  handle: U) -> Result<SocketAddr, IoError> {
+    #[fixed_stack_segment]; #[inline(never)];
 
     let getsockname = match sk {
         TcpPeer => uvll::rust_uv_tcp_getpeername,
@@ -406,6 +407,8 @@ impl RtioTcpListener for UvTcpListener {
     }
 
     fn accept_simultaneously(&mut self) -> Result<(), IoError> {
+        #[fixed_stack_segment]; #[inline(never)];
+
         let r = unsafe {
             uvll::rust_uv_tcp_simultaneous_accepts(self.watcher.native_handle(), 1 as c_int)
         };
@@ -417,6 +420,8 @@ impl RtioTcpListener for UvTcpListener {
     }
 
     fn dont_accept_simultaneously(&mut self) -> Result<(), IoError> {
+        #[fixed_stack_segment]; #[inline(never)];
+
         let r = unsafe {
             uvll::rust_uv_tcp_simultaneous_accepts(self.watcher.native_handle(), 0 as c_int)
         };
@@ -524,6 +529,8 @@ impl RtioTcpStream for UvTcpStream {
     }
 
     fn control_congestion(&mut self) -> Result<(), IoError> {
+        #[fixed_stack_segment]; #[inline(never)];
+
         let r = unsafe {
             uvll::rust_uv_tcp_nodelay(self.native_handle(), 0 as c_int)
         };
@@ -535,6 +542,8 @@ impl RtioTcpStream for UvTcpStream {
     }
 
     fn nodelay(&mut self) -> Result<(), IoError> {
+        #[fixed_stack_segment]; #[inline(never)];
+
         let r = unsafe {
             uvll::rust_uv_tcp_nodelay(self.native_handle(), 1 as c_int)
         };
@@ -546,6 +555,8 @@ impl RtioTcpStream for UvTcpStream {
     }
 
     fn keepalive(&mut self, delay_in_seconds: uint) -> Result<(), IoError> {
+        #[fixed_stack_segment]; #[inline(never)];
+
         let r = unsafe {
             uvll::rust_uv_tcp_keepalive(self.native_handle(), 1 as c_int,
                                         delay_in_seconds as c_uint)
@@ -558,6 +569,8 @@ impl RtioTcpStream for UvTcpStream {
     }
 
     fn letdie(&mut self) -> Result<(), IoError> {
+        #[fixed_stack_segment]; #[inline(never)];
+
         let r = unsafe {
             uvll::rust_uv_tcp_keepalive(self.native_handle(), 0 as c_int, 0 as c_uint)
         };
diff --git a/src/libstd/rt/uv/uvll.rs b/src/libstd/rt/uv/uvll.rs
index c04004dfbf6..65c0cffe5a0 100644
--- a/src/libstd/rt/uv/uvll.rs
+++ b/src/libstd/rt/uv/uvll.rs
@@ -124,6 +124,8 @@ pub enum uv_membership {
 }
 
 pub unsafe fn malloc_handle(handle: uv_handle_type) -> *c_void {
+    #[fixed_stack_segment]; #[inline(never)];
+
     assert!(handle != UV_UNKNOWN_HANDLE && handle != UV_HANDLE_TYPE_MAX);
     let size = rust_uv_handle_size(handle as uint);
     let p = malloc(size);
@@ -132,10 +134,14 @@ pub unsafe fn malloc_handle(handle: uv_handle_type) -> *c_void {
 }
 
 pub unsafe fn free_handle(v: *c_void) {
+    #[fixed_stack_segment]; #[inline(never)];
+
     free(v)
 }
 
 pub unsafe fn malloc_req(req: uv_req_type) -> *c_void {
+    #[fixed_stack_segment]; #[inline(never)];
+
     assert!(req != UV_UNKNOWN_REQ && req != UV_REQ_TYPE_MAX);
     let size = rust_uv_req_size(req as uint);
     let p = malloc(size);
@@ -144,17 +150,22 @@ pub unsafe fn malloc_req(req: uv_req_type) -> *c_void {
 }
 
 pub unsafe fn free_req(v: *c_void) {
+    #[fixed_stack_segment]; #[inline(never)];
+
     free(v)
 }
 
 #[test]
 fn handle_sanity_check() {
+    #[fixed_stack_segment]; #[inline(never)];
     unsafe {
         assert_eq!(UV_HANDLE_TYPE_MAX as uint, rust_uv_handle_type_max());
     }
 }
 
 #[test]
+#[fixed_stack_segment]
+#[inline(never)]
 fn request_sanity_check() {
     unsafe {
         assert_eq!(UV_REQ_TYPE_MAX as uint, rust_uv_req_type_max());
@@ -162,59 +173,87 @@ fn request_sanity_check() {
 }
 
 pub unsafe fn loop_new() -> *c_void {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_loop_new();
 }
 
 pub unsafe fn loop_delete(loop_handle: *c_void) {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_loop_delete(loop_handle);
 }
 
 pub unsafe fn run(loop_handle: *c_void) {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_run(loop_handle);
 }
 
 pub unsafe fn close<T>(handle: *T, cb: *u8) {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_close(handle as *c_void, cb);
 }
 
 pub unsafe fn walk(loop_handle: *c_void, cb: *u8, arg: *c_void) {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_walk(loop_handle, cb, arg);
 }
 
 pub unsafe fn idle_new() -> *uv_idle_t {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_idle_new()
 }
 
 pub unsafe fn idle_delete(handle: *uv_idle_t) {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_idle_delete(handle)
 }
 
 pub unsafe fn idle_init(loop_handle: *uv_loop_t, handle: *uv_idle_t) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_idle_init(loop_handle, handle)
 }
 
 pub unsafe fn idle_start(handle: *uv_idle_t, cb: uv_idle_cb) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_idle_start(handle, cb)
 }
 
 pub unsafe fn idle_stop(handle: *uv_idle_t) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_idle_stop(handle)
 }
 
 pub unsafe fn udp_init(loop_handle: *uv_loop_t, handle: *uv_udp_t) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_udp_init(loop_handle, handle);
 }
 
 pub unsafe fn udp_bind(server: *uv_udp_t, addr: *sockaddr_in, flags: c_uint) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_udp_bind(server, addr, flags);
 }
 
 pub unsafe fn udp_bind6(server: *uv_udp_t, addr: *sockaddr_in6, flags: c_uint) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_udp_bind6(server, addr, flags);
 }
 
 pub unsafe fn udp_send<T>(req: *uv_udp_send_t, handle: *T, buf_in: &[uv_buf_t],
                           addr: *sockaddr_in, cb: uv_udp_send_cb) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     let buf_ptr = vec::raw::to_ptr(buf_in);
     let buf_cnt = buf_in.len() as i32;
     return rust_uv_udp_send(req, handle as *c_void, buf_ptr, buf_cnt, addr, cb);
@@ -222,6 +261,8 @@ pub unsafe fn udp_send<T>(req: *uv_udp_send_t, handle: *T, buf_in: &[uv_buf_t],
 
 pub unsafe fn udp_send6<T>(req: *uv_udp_send_t, handle: *T, buf_in: &[uv_buf_t],
                           addr: *sockaddr_in6, cb: uv_udp_send_cb) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     let buf_ptr = vec::raw::to_ptr(buf_in);
     let buf_cnt = buf_in.len() as i32;
     return rust_uv_udp_send6(req, handle as *c_void, buf_ptr, buf_cnt, addr, cb);
@@ -229,124 +270,184 @@ pub unsafe fn udp_send6<T>(req: *uv_udp_send_t, handle: *T, buf_in: &[uv_buf_t],
 
 pub unsafe fn udp_recv_start(server: *uv_udp_t, on_alloc: uv_alloc_cb,
                              on_recv: uv_udp_recv_cb) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_udp_recv_start(server, on_alloc, on_recv);
 }
 
 pub unsafe fn udp_recv_stop(server: *uv_udp_t) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_udp_recv_stop(server);
 }
 
 pub unsafe fn get_udp_handle_from_send_req(send_req: *uv_udp_send_t) -> *uv_udp_t {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_get_udp_handle_from_send_req(send_req);
 }
 
 pub unsafe fn udp_get_sockname(handle: *uv_udp_t, name: *sockaddr_storage) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_udp_getsockname(handle, name);
 }
 
 pub unsafe fn udp_set_membership(handle: *uv_udp_t, multicast_addr: *c_char,
                                  interface_addr: *c_char, membership: uv_membership) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_udp_set_membership(handle, multicast_addr, interface_addr, membership as c_int);
 }
 
 pub unsafe fn udp_set_multicast_loop(handle: *uv_udp_t, on: c_int) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_udp_set_multicast_loop(handle, on);
 }
 
 pub unsafe fn udp_set_multicast_ttl(handle: *uv_udp_t, ttl: c_int) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_udp_set_multicast_ttl(handle, ttl);
 }
 
 pub unsafe fn udp_set_ttl(handle: *uv_udp_t, ttl: c_int) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_udp_set_ttl(handle, ttl);
 }
 
 pub unsafe fn udp_set_broadcast(handle: *uv_udp_t, on: c_int) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_udp_set_broadcast(handle, on);
 }
 
 pub unsafe fn tcp_init(loop_handle: *c_void, handle: *uv_tcp_t) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_tcp_init(loop_handle, handle);
 }
 
 pub unsafe fn tcp_connect(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t,
                           addr_ptr: *sockaddr_in, after_connect_cb: *u8) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_tcp_connect(connect_ptr, tcp_handle_ptr, after_connect_cb, addr_ptr);
 }
 
 pub unsafe fn tcp_connect6(connect_ptr: *uv_connect_t, tcp_handle_ptr: *uv_tcp_t,
                            addr_ptr: *sockaddr_in6, after_connect_cb: *u8) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_tcp_connect6(connect_ptr, tcp_handle_ptr, after_connect_cb, addr_ptr);
 }
 
 pub unsafe fn tcp_bind(tcp_server_ptr: *uv_tcp_t, addr_ptr: *sockaddr_in) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_tcp_bind(tcp_server_ptr, addr_ptr);
 }
 
 pub unsafe fn tcp_bind6(tcp_server_ptr: *uv_tcp_t, addr_ptr: *sockaddr_in6) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_tcp_bind6(tcp_server_ptr, addr_ptr);
 }
 
 pub unsafe fn tcp_getpeername(tcp_handle_ptr: *uv_tcp_t, name: *sockaddr_storage) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_tcp_getpeername(tcp_handle_ptr, name);
 }
 
 pub unsafe fn tcp_getsockname(handle: *uv_tcp_t, name: *sockaddr_storage) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_tcp_getsockname(handle, name);
 }
 
 pub unsafe fn tcp_nodelay(handle: *uv_tcp_t, enable: c_int) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_tcp_nodelay(handle, enable);
 }
 
 pub unsafe fn tcp_keepalive(handle: *uv_tcp_t, enable: c_int, delay: c_uint) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_tcp_keepalive(handle, enable, delay);
 }
 
 pub unsafe fn tcp_simultaneous_accepts(handle: *uv_tcp_t, enable: c_int) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_tcp_simultaneous_accepts(handle, enable);
 }
 
 pub unsafe fn listen<T>(stream: *T, backlog: c_int, cb: *u8) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_listen(stream as *c_void, backlog, cb);
 }
 
 pub unsafe fn accept(server: *c_void, client: *c_void) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_accept(server as *c_void, client as *c_void);
 }
 
 pub unsafe fn write<T>(req: *uv_write_t, stream: *T, buf_in: &[uv_buf_t], cb: *u8) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     let buf_ptr = vec::raw::to_ptr(buf_in);
     let buf_cnt = buf_in.len() as i32;
     return rust_uv_write(req as *c_void, stream as *c_void, buf_ptr, buf_cnt, cb);
 }
 pub unsafe fn read_start(stream: *uv_stream_t, on_alloc: uv_alloc_cb, on_read: *u8) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_read_start(stream as *c_void, on_alloc, on_read);
 }
 
 pub unsafe fn read_stop(stream: *uv_stream_t) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_read_stop(stream as *c_void);
 }
 
 pub unsafe fn last_error(loop_handle: *c_void) -> uv_err_t {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_last_error(loop_handle);
 }
 
 pub unsafe fn strerror(err: *uv_err_t) -> *c_char {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_strerror(err);
 }
 pub unsafe fn err_name(err: *uv_err_t) -> *c_char {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_err_name(err);
 }
 
 pub unsafe fn async_init(loop_handle: *c_void, async_handle: *uv_async_t, cb: *u8) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_async_init(loop_handle, async_handle, cb);
 }
 
 pub unsafe fn async_send(async_handle: *uv_async_t) {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_async_send(async_handle);
 }
 pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t {
+    #[fixed_stack_segment]; #[inline(never)];
+
     let out_buf = uv_buf_t { base: ptr::null(), len: 0 as size_t };
     let out_buf_ptr = ptr::to_unsafe_ptr(&out_buf);
     rust_uv_buf_init(out_buf_ptr, input, len as size_t);
@@ -354,99 +455,149 @@ pub unsafe fn buf_init(input: *u8, len: uint) -> uv_buf_t {
 }
 
 pub unsafe fn timer_init(loop_ptr: *c_void, timer_ptr: *uv_timer_t) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_timer_init(loop_ptr, timer_ptr);
 }
 pub unsafe fn timer_start(timer_ptr: *uv_timer_t, cb: *u8, timeout: u64,
                           repeat: u64) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_timer_start(timer_ptr, cb, timeout, repeat);
 }
 pub unsafe fn timer_stop(timer_ptr: *uv_timer_t) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_timer_stop(timer_ptr);
 }
 
 pub unsafe fn is_ip4_addr(addr: *sockaddr) -> bool {
+    #[fixed_stack_segment]; #[inline(never)];
+
     match rust_uv_is_ipv4_sockaddr(addr) { 0 => false, _ => true }
 }
 
 pub unsafe fn is_ip6_addr(addr: *sockaddr) -> bool {
+    #[fixed_stack_segment]; #[inline(never)];
+
     match rust_uv_is_ipv6_sockaddr(addr) { 0 => false, _ => true }
 }
 
 pub unsafe fn malloc_ip4_addr(ip: &str, port: int) -> *sockaddr_in {
+    #[fixed_stack_segment]; #[inline(never)];
     do ip.with_c_str |ip_buf| {
         rust_uv_ip4_addrp(ip_buf as *u8, port as libc::c_int)
     }
 }
 pub unsafe fn malloc_ip6_addr(ip: &str, port: int) -> *sockaddr_in6 {
+    #[fixed_stack_segment]; #[inline(never)];
     do ip.with_c_str |ip_buf| {
         rust_uv_ip6_addrp(ip_buf as *u8, port as libc::c_int)
     }
 }
 
 pub unsafe fn malloc_sockaddr_storage() -> *sockaddr_storage {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_malloc_sockaddr_storage()
 }
 
 pub unsafe fn free_sockaddr_storage(ss: *sockaddr_storage) {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_free_sockaddr_storage(ss);
 }
 
 pub unsafe fn free_ip4_addr(addr: *sockaddr_in) {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_free_ip4_addr(addr);
 }
 
 pub unsafe fn free_ip6_addr(addr: *sockaddr_in6) {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_free_ip6_addr(addr);
 }
 
 pub unsafe fn ip4_name(addr: *sockaddr_in, dst: *u8, size: size_t) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_ip4_name(addr, dst, size);
 }
 
 pub unsafe fn ip6_name(addr: *sockaddr_in6, dst: *u8, size: size_t) -> c_int {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_ip6_name(addr, dst, size);
 }
 
 pub unsafe fn ip4_port(addr: *sockaddr_in) -> c_uint {
+    #[fixed_stack_segment]; #[inline(never)];
+
    return rust_uv_ip4_port(addr);
 }
 
 pub unsafe fn ip6_port(addr: *sockaddr_in6) -> c_uint {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_ip6_port(addr);
 }
 
 // data access helpers
 pub unsafe fn get_loop_for_uv_handle<T>(handle: *T) -> *c_void {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_get_loop_for_uv_handle(handle as *c_void);
 }
 pub unsafe fn get_stream_handle_from_connect_req(connect: *uv_connect_t) -> *uv_stream_t {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_get_stream_handle_from_connect_req(connect);
 }
 pub unsafe fn get_stream_handle_from_write_req(write_req: *uv_write_t) -> *uv_stream_t {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_get_stream_handle_from_write_req(write_req);
 }
 pub unsafe fn get_data_for_uv_loop(loop_ptr: *c_void) -> *c_void {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_get_data_for_uv_loop(loop_ptr)
 }
 pub unsafe fn set_data_for_uv_loop(loop_ptr: *c_void, data: *c_void) {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_set_data_for_uv_loop(loop_ptr, data);
 }
 pub unsafe fn get_data_for_uv_handle<T>(handle: *T) -> *c_void {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_get_data_for_uv_handle(handle as *c_void);
 }
 pub unsafe fn set_data_for_uv_handle<T, U>(handle: *T, data: *U) {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_set_data_for_uv_handle(handle as *c_void, data as *c_void);
 }
 pub unsafe fn get_data_for_req<T>(req: *T) -> *c_void {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_get_data_for_req(req as *c_void);
 }
 pub unsafe fn set_data_for_req<T, U>(req: *T, data: *U) {
+    #[fixed_stack_segment]; #[inline(never)];
+
     rust_uv_set_data_for_req(req as *c_void, data as *c_void);
 }
 pub unsafe fn get_base_from_buf(buf: uv_buf_t) -> *u8 {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_get_base_from_buf(buf);
 }
 pub unsafe fn get_len_from_buf(buf: uv_buf_t) -> size_t {
+    #[fixed_stack_segment]; #[inline(never)];
+
     return rust_uv_get_len_from_buf(buf);
 }
 pub unsafe fn get_last_err_info(uv_loop: *c_void) -> ~str {