From 24eb1b445dd878c12ca6503a9fa040179b94e614 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 13 Nov 2013 23:17:18 -0800 Subject: [PATCH 1/3] Implement a native mutex type This mutex is built on top of pthreads for unix and the related windows apis on windows. This is a straight port of the lock_and_signal type from C++ to rust. Almost all operations on the type are unsafe, and it's definitely not recommended for general use. Closes #9105 --- src/libstd/unstable/mod.rs | 1 + src/libstd/unstable/mutex.rs | 336 +++++++++++++++++++++++++++++++++++ src/rt/rust_builtin.cpp | 21 +++ src/rt/rustrt.def.in | 5 +- 4 files changed, 361 insertions(+), 2 deletions(-) create mode 100644 src/libstd/unstable/mutex.rs diff --git a/src/libstd/unstable/mod.rs b/src/libstd/unstable/mod.rs index ea03ea6f551c2..9b8c81979a90e 100644 --- a/src/libstd/unstable/mod.rs +++ b/src/libstd/unstable/mod.rs @@ -24,6 +24,7 @@ pub mod simd; #[cfg(not(test))] pub mod lang; pub mod sync; +pub mod mutex; pub mod atomics; pub mod raw; diff --git a/src/libstd/unstable/mutex.rs b/src/libstd/unstable/mutex.rs new file mode 100644 index 0000000000000..5be9be7bf8a99 --- /dev/null +++ b/src/libstd/unstable/mutex.rs @@ -0,0 +1,336 @@ +// 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. + +//! A native mutex and condition variable type +//! +//! This module contains bindings to the platform's native mutex/condition +//! variable primitives. It provides a single type, `Mutex`, which can be +//! statically initialized via the `MUTEX_INIT` value. This object serves as both a +//! mutex and a condition variable simultaneously. +//! +//! The lock is lazily initialized, but it can only be unsafely destroyed. A +//! statically initialized lock doesn't necessarily have a time at which it can +//! get deallocated. For this reason, there is no `Drop` implementation of the +//! mutex, but rather the `destroy()` method must be invoked manually if +//! destruction of the mutex is desired. +//! +//! It is not recommended to use this type for idiomatic rust use. This type is +//! appropriate where no other options are available, but other rust concurrency +//! primitives should be used before this type. +//! +//! # Example +//! +//! use std::unstable::mutex::{Mutex, MUTEX_INIT}; +//! +//! // Use a statically initialized mutex +//! static mut lock: Mutex = MUTEX_INIT; +//! +//! unsafe { +//! lock.lock(); +//! lock.unlock(); +//! } +//! +//! // Use a normally initialied mutex +//! let mut lock = Mutex::new(); +//! unsafe { +//! lock.lock(); +//! lock.unlock(); +//! lock.destroy(); +//! } + +#[allow(non_camel_case_types)]; + +use libc::c_void; +use unstable::atomics; + +pub struct Mutex { + // pointers for the lock/cond handles, atomically updated + priv lock: atomics::AtomicUint, + priv cond: atomics::AtomicUint, +} + +pub static MUTEX_INIT: Mutex = Mutex { + lock: atomics::INIT_ATOMIC_UINT, + cond: atomics::INIT_ATOMIC_UINT, +}; + +impl Mutex { + /// Creates a new mutex, with the lock/condition variable pre-initialized + pub unsafe fn new() -> Mutex { + Mutex { + lock: atomics::AtomicUint::new(imp::init_lock() as uint), + cond: atomics::AtomicUint::new(imp::init_cond() as uint), + } + } + + /// Creates a new copy of this mutex. This is an unsafe operation because + /// there is no reference counting performed on this type. + /// + /// This function may only be called on mutexes which have had both the + /// internal condition variable and lock initialized. This means that the + /// mutex must have been created via `new`, or usage of it has already + /// initialized the internal handles. + /// + /// This is a dangerous function to call as both this mutex and the returned + /// mutex will share the same handles to the underlying mutex/condition + /// variable. Care must be taken to ensure that deallocation happens + /// accordingly. + pub unsafe fn clone(&self) -> Mutex { + let lock = self.lock.load(atomics::Relaxed); + let cond = self.cond.load(atomics::Relaxed); + assert!(lock != 0); + assert!(cond != 0); + Mutex { + lock: atomics::AtomicUint::new(lock), + cond: atomics::AtomicUint::new(cond), + } + } + + /// Acquires this lock. This assumes that the current thread does not + /// already hold the lock. + pub unsafe fn lock(&mut self) { imp::lock(self.getlock()) } + + /// Attempts to acquire the lock. The value returned is whether the lock was + /// acquired or not + pub unsafe fn trylock(&mut self) -> bool { imp::trylock(self.getlock()) } + + /// Unlocks the lock. This assumes that the current thread already holds the + /// lock. + pub unsafe fn unlock(&mut self) { imp::unlock(self.getlock()) } + + /// Block on the internal condition variable. + /// + /// This function assumes that the lock is already held + pub unsafe fn wait(&mut self) { imp::wait(self.getcond(), self.getlock()) } + + /// Signals a thread in `wait` to wake up + pub unsafe fn signal(&mut self) { imp::signal(self.getcond()) } + + /// This function is especially unsafe because there are no guarantees made + /// that no other thread is currently holding the lock or waiting on the + /// condition variable contained inside. + pub unsafe fn destroy(&mut self) { + imp::free_lock(self.lock.swap(0, atomics::Relaxed)); + imp::free_cond(self.cond.swap(0, atomics::Relaxed)); + } + + unsafe fn getlock(&mut self) -> *c_void { + match self.lock.load(atomics::Relaxed) { + 0 => {} + n => return n as *c_void + } + let lock = imp::init_lock(); + match self.lock.compare_and_swap(0, lock, atomics::SeqCst) { + 0 => return lock as *c_void, + _ => {} + } + imp::free_lock(lock); + return self.lock.load(atomics::Relaxed) as *c_void; + } + + unsafe fn getcond(&mut self) -> *c_void { + match self.cond.load(atomics::Relaxed) { + 0 => {} + n => return n as *c_void + } + let cond = imp::init_cond(); + match self.cond.compare_and_swap(0, cond, atomics::SeqCst) { + 0 => return cond as *c_void, + _ => {} + } + imp::free_cond(cond); + return self.cond.load(atomics::Relaxed) as *c_void; + } +} + +#[cfg(unix)] +mod imp { + use libc::c_void; + use libc; + use ptr; + + type pthread_mutex_t = libc::c_void; + type pthread_mutexattr_t = libc::c_void; + type pthread_cond_t = libc::c_void; + type pthread_condattr_t = libc::c_void; + + pub unsafe fn init_lock() -> uint { + let block = libc::malloc(rust_pthread_mutex_t_size() as libc::size_t); + assert!(!block.is_null()); + let n = pthread_mutex_init(block, ptr::null()); + assert_eq!(n, 0); + return block as uint; + } + + pub unsafe fn init_cond() -> uint { + let block = libc::malloc(rust_pthread_cond_t_size() as libc::size_t); + assert!(!block.is_null()); + let n = pthread_cond_init(block, ptr::null()); + assert_eq!(n, 0); + return block as uint; + } + + pub unsafe fn free_lock(h: uint) { + let block = h as *c_void; + assert_eq!(pthread_mutex_destroy(block), 0); + libc::free(block); + } + + pub unsafe fn free_cond(h: uint) { + let block = h as *c_void; + assert_eq!(pthread_cond_destroy(block), 0); + libc::free(block); + } + + pub unsafe fn lock(l: *pthread_mutex_t) { + assert_eq!(pthread_mutex_lock(l), 0); + } + + pub unsafe fn trylock(l: *c_void) -> bool { + pthread_mutex_trylock(l) == 0 + } + + pub unsafe fn unlock(l: *pthread_mutex_t) { + assert_eq!(pthread_mutex_unlock(l), 0); + } + + pub unsafe fn wait(cond: *pthread_cond_t, m: *pthread_mutex_t) { + assert_eq!(pthread_cond_wait(cond, m), 0); + } + + pub unsafe fn signal(cond: *pthread_cond_t) { + assert_eq!(pthread_cond_signal(cond), 0); + } + + extern { + fn rust_pthread_mutex_t_size() -> libc::c_int; + fn rust_pthread_cond_t_size() -> libc::c_int; + } + + extern { + fn pthread_mutex_init(lock: *pthread_mutex_t, + attr: *pthread_mutexattr_t) -> libc::c_int; + fn pthread_mutex_destroy(lock: *pthread_mutex_t) -> libc::c_int; + fn pthread_cond_init(cond: *pthread_cond_t, + attr: *pthread_condattr_t) -> libc::c_int; + fn pthread_cond_destroy(cond: *pthread_cond_t) -> libc::c_int; + fn pthread_mutex_lock(lock: *pthread_mutex_t) -> libc::c_int; + fn pthread_mutex_trylock(lock: *pthread_mutex_t) -> libc::c_int; + fn pthread_mutex_unlock(lock: *pthread_mutex_t) -> libc::c_int; + + fn pthread_cond_wait(cond: *pthread_cond_t, + lock: *pthread_mutex_t) -> libc::c_int; + fn pthread_cond_signal(cond: *pthread_cond_t) -> libc::c_int; + } +} + +#[cfg(windows)] +mod imp { + use libc; + use libc::{HANDLE, BOOL, LPSECURITY_ATTRIBUTES, c_void, DWORD, LPCSTR}; + use ptr; + type LPCRITICAL_SECTION = *c_void; + static SPIN_COUNT: DWORD = 4000; + + pub unsafe fn init_lock() -> uint { + let block = libc::malloc(rust_crit_section_size() as libc::size_t); + assert!(!block.is_null()); + InitializeCriticalSectionAndSpinCount(block, SPIN_COUNT); + return block as uint; + } + + pub unsafe fn init_cond() -> uint { + return CreateEventA(ptr::mut_null(), libc::FALSE, libc::FALSE, + ptr::null()) as uint; + } + + pub unsafe fn free_lock(h: uint) { + DeleteCriticalSection(h as LPCRITICAL_SECTION); + libc::free(h as *c_void); + } + + pub unsafe fn free_cond(h: uint) { + let block = h as HANDLE; + libc::CloseHandle(block); + } + + pub unsafe fn lock(l: *c_void) { + EnterCriticalSection(l as LPCRITICAL_SECTION) + } + + pub unsafe fn trylock(l: *c_void) -> bool { + TryEnterCriticalSection(l as LPCRITICAL_SECTION) != 0 + } + + pub unsafe fn unlock(l: *c_void) { + LeaveCriticalSection(l as LPCRITICAL_SECTION) + } + + pub unsafe fn wait(cond: *c_void, m: *c_void) { + unlock(m); + WaitForSingleObject(cond as HANDLE, 0); + lock(m); + } + + pub unsafe fn signal(cond: *c_void) { + assert!(SetEvent(cond as HANDLE) != 0); + } + + extern { + fn rust_crit_section_size() -> libc::c_int; + } + + extern "system" { + fn CreateEventA(lpSecurityAttributes: LPSECURITY_ATTRIBUTES, + bManualReset: BOOL, + bInitialState: BOOL, + lpName: LPCSTR) -> HANDLE; + fn InitializeCriticalSectionAndSpinCount( + lpCriticalSection: LPCRITICAL_SECTION, + dwSpinCount: DWORD) -> BOOL; + fn DeleteCriticalSection(lpCriticalSection: LPCRITICAL_SECTION); + fn EnterCriticalSection(lpCriticalSection: LPCRITICAL_SECTION); + fn LeaveCriticalSection(lpCriticalSection: LPCRITICAL_SECTION); + fn TryEnterCriticalSection(lpCriticalSection: LPCRITICAL_SECTION) -> BOOL; + fn SetEvent(hEvent: HANDLE) -> BOOL; + fn WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: DWORD) -> DWORD; + } +} + +#[cfg(test)] +mod test { + use super::{Mutex, MUTEX_INIT}; + use rt::thread::Thread; + + #[test] + fn somke_lock() { + static mut lock: Mutex = MUTEX_INIT; + unsafe { + lock.lock(); + lock.unlock(); + } + } + + #[test] + fn somke_cond() { + static mut lock: Mutex = MUTEX_INIT; + unsafe { + let t = do Thread::start { + lock.lock(); + lock.signal(); + lock.unlock(); + }; + lock.lock(); + lock.wait(); + lock.unlock(); + t.join(); + } + } +} diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 7d75d557bf767..28dd4b51a1313 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -671,6 +671,27 @@ rust_win32_rand_release() { } #endif + +#if defined(__WIN32__) + +extern "C" CDECL int +rust_crit_section_size() { return sizeof(CRITICAL_SECTION); } +extern "C" CDECL int +rust_pthread_mutex_t_size() { return 0; } +extern "C" CDECL int +rust_pthread_cond_t_size() { return 0; } + +#else + +extern "C" CDECL int +rust_crit_section_size() { return 0; } +extern "C" CDECL int +rust_pthread_mutex_t_size() { return sizeof(pthread_mutex_t); } +extern "C" CDECL int +rust_pthread_cond_t_size() { return sizeof(pthread_cond_t); } + +#endif + // // Local Variables: // mode: C++ diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 49b6ebce28400..d78584f33dfd8 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -73,5 +73,6 @@ rust_get_global_args_ptr rust_take_global_args_lock rust_drop_global_args_lock rust_get_test_int -rust_take_dlerror_lock -rust_drop_dlerror_lock +rust_pthread_mutex_t_size +rust_pthread_cond_t_size +rust_crit_section_size From e8bf0788027932a0b547819cc9edd13c40426e36 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 14 Nov 2013 00:21:43 -0800 Subject: [PATCH 2/3] Remove the C++ lock_and_signal type A the same time this purges all runtime support needed for statically initialized mutexes, moving all users over to the new Mutex type instead. --- mk/rt.mk | 1 - src/libstd/os.rs | 12 +- src/libstd/rt/args.rs | 53 ++++---- src/libstd/rt/local_ptr.rs | 12 +- src/libstd/rt/test.rs | 20 +-- src/libstd/task/mod.rs | 34 ++--- src/libstd/unstable/dynamic_lib.rs | 12 +- src/libstd/unstable/sync.rs | 41 +++--- src/rt/rust_builtin.cpp | 107 +-------------- src/rt/rust_test_helpers.cpp | 48 +------ src/rt/rustrt.def.in | 20 --- src/rt/sync/lock_and_signal.cpp | 205 ----------------------------- src/rt/sync/lock_and_signal.h | 63 --------- 13 files changed, 92 insertions(+), 536 deletions(-) delete mode 100644 src/rt/sync/lock_and_signal.cpp delete mode 100644 src/rt/sync/lock_and_signal.h diff --git a/mk/rt.mk b/mk/rt.mk index 39679cbed6961..26e4222e4ebd7 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -90,7 +90,6 @@ endif endif RUNTIME_CXXS_$(1)_$(2) := \ - rt/sync/lock_and_signal.cpp \ rt/rust_builtin.cpp \ rt/rust_upcall.cpp \ rt/miniz.cpp \ diff --git a/src/libstd/os.rs b/src/libstd/os.rs index 213cf5dc07cd5..3ea6e18f9427c 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -138,21 +138,19 @@ Accessing environment variables is not generally threadsafe. Serialize access through a global lock. */ fn with_env_lock(f: &fn() -> T) -> T { + use unstable::mutex::{Mutex, MUTEX_INIT}; use unstable::finally::Finally; + static mut lock: Mutex = MUTEX_INIT; + unsafe { return do (|| { - rust_take_env_lock(); + lock.lock(); f() }).finally { - rust_drop_env_lock(); + lock.unlock(); }; } - - extern { - fn rust_take_env_lock(); - fn rust_drop_env_lock(); - } } /// Returns a vector of (variable, value) pairs for all the environment diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index 48e5887902685..b9238224d6e98 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -21,32 +21,42 @@ //! FIXME #7756: This has a lot of C glue for lack of globals. use option::Option; +#[cfg(test)] use option::{Some, None}; +#[cfg(test)] use realstd; +#[cfg(test)] use realargs = realstd::rt::args; /// One-time global initialization. -pub unsafe fn init(argc: int, argv: **u8) { - imp::init(argc, argv) -} +#[cfg(not(test))] +pub unsafe fn init(argc: int, argv: **u8) { imp::init(argc, argv) } +#[cfg(test)] +pub unsafe fn init(argc: int, argv: **u8) { realargs::init(argc, argv) } /// One-time global cleanup. -pub fn cleanup() { - imp::cleanup() -} +#[cfg(not(test))] pub fn cleanup() { imp::cleanup() } +#[cfg(test)] pub fn cleanup() { realargs::cleanup() } /// Take the global arguments from global storage. -pub fn take() -> Option<~[~str]> { - imp::take() +#[cfg(not(test))] pub fn take() -> Option<~[~str]> { imp::take() } +#[cfg(test)] pub fn take() -> Option<~[~str]> { + match realargs::take() { + realstd::option::Some(a) => Some(a), + realstd::option::None => None, + } } /// Give the global arguments to global storage. /// /// It is an error if the arguments already exist. -pub fn put(args: ~[~str]) { - imp::put(args) -} +#[cfg(not(test))] pub fn put(args: ~[~str]) { imp::put(args) } +#[cfg(test)] pub fn put(args: ~[~str]) { realargs::put(args) } /// Make a clone of the global arguments. -pub fn clone() -> Option<~[~str]> { - imp::clone() +#[cfg(not(test))] pub fn clone() -> Option<~[~str]> { imp::clone() } +#[cfg(test)] pub fn clone() -> Option<~[~str]> { + match realargs::clone() { + realstd::option::Some(a) => Some(a), + realstd::option::None => None, + } } #[cfg(target_os = "linux")] @@ -58,9 +68,12 @@ mod imp { use iter::Iterator; use str; use unstable::finally::Finally; + use unstable::mutex::{Mutex, MUTEX_INIT}; use util; use vec; + static mut global_args_ptr: uint = 0; + pub unsafe fn init(argc: int, argv: **u8) { let args = load_argc_and_argv(argc, argv); put(args); @@ -94,20 +107,22 @@ mod imp { } fn with_lock(f: &fn() -> T) -> T { + static mut lock: Mutex = MUTEX_INIT; + do (|| { unsafe { - rust_take_global_args_lock(); + lock.lock(); f() } }).finally { unsafe { - rust_drop_global_args_lock(); + lock.unlock(); } } } fn get_global_ptr() -> *mut Option<~~[~str]> { - unsafe { rust_get_global_args_ptr() } + unsafe { cast::transmute(&global_args_ptr) } } // Copied from `os`. @@ -117,12 +132,6 @@ mod imp { } } - extern { - fn rust_take_global_args_lock(); - fn rust_drop_global_args_lock(); - fn rust_get_global_args_ptr() -> *mut Option<~~[~str]>; - } - #[cfg(test)] mod tests { use option::{Some, None}; diff --git a/src/libstd/rt/local_ptr.rs b/src/libstd/rt/local_ptr.rs index f35b657d9ddce..d5d1931a21725 100644 --- a/src/libstd/rt/local_ptr.rs +++ b/src/libstd/rt/local_ptr.rs @@ -21,17 +21,23 @@ use ptr; use cell::Cell; use option::{Option, Some, None}; use unstable::finally::Finally; +use unstable::mutex::{Mutex, MUTEX_INIT}; use tls = rt::thread_local_storage; static mut RT_TLS_KEY: tls::Key = -1; /// Initialize the TLS key. Other ops will fail if this isn't executed first. pub fn init_tls_key() { + static mut lock: Mutex = MUTEX_INIT; + static mut initialized: bool = false; + unsafe { - rust_initialize_rt_tls_key(&mut RT_TLS_KEY); - extern { - fn rust_initialize_rt_tls_key(key: *mut tls::Key); + lock.lock(); + if !initialized { + tls::create(&mut RT_TLS_KEY); + initialized = true; } + lock.unlock(); } } diff --git a/src/libstd/rt/test.rs b/src/libstd/rt/test.rs index 19ab36a6ac4d9..c1a7893f5a5c1 100644 --- a/src/libstd/rt/test.rs +++ b/src/libstd/rt/test.rs @@ -14,7 +14,6 @@ use cell::Cell; use clone::Clone; use container::Container; use iter::{Iterator, range}; -use libc; use option::{Some, None}; use os; use path::GenericPath; @@ -361,11 +360,16 @@ pub fn cleanup_task(mut task: ~Task) { /// Get a port number, starting at 9600, for use in tests pub fn next_test_port() -> u16 { + use unstable::mutex::{Mutex, MUTEX_INIT}; + static mut lock: Mutex = MUTEX_INIT; + static mut next_offset: u16 = 0; unsafe { - return rust_dbg_next_port(base_port() as libc::uintptr_t) as u16; - } - extern { - fn rust_dbg_next_port(base: libc::uintptr_t) -> libc::uintptr_t; + let base = base_port(); + lock.lock(); + let ret = base + next_offset; + next_offset += 1; + lock.unlock(); + return ret; } } @@ -395,13 +399,13 @@ The bots run multiple builds at the same time, and these builds all want to use ports. This function figures out which workspace it is running in and assigns a port range based on it. */ -fn base_port() -> uint { +fn base_port() -> u16 { use os; use str::StrSlice; use vec::ImmutableVector; - let base = 9600u; - let range = 1000; + let base = 9600u16; + let range = 1000u16; let bases = [ ("32-opt", base + range * 1), diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs index 51c11b69972fb..5a2251eaa461e 100644 --- a/src/libstd/task/mod.rs +++ b/src/libstd/task/mod.rs @@ -1141,22 +1141,10 @@ fn test_spawn_sched_childs_on_default_sched() { po.recv(); } -#[cfg(test)] -mod testrt { - use libc; - - extern { - pub fn rust_dbg_lock_create() -> *libc::c_void; - pub fn rust_dbg_lock_destroy(lock: *libc::c_void); - pub fn rust_dbg_lock_lock(lock: *libc::c_void); - pub fn rust_dbg_lock_unlock(lock: *libc::c_void); - pub fn rust_dbg_lock_wait(lock: *libc::c_void); - pub fn rust_dbg_lock_signal(lock: *libc::c_void); - } -} - #[test] fn test_spawn_sched_blocking() { + use unstable::mutex::Mutex; + unsafe { // Testing that a task in one scheduler can block in foreign code @@ -1165,16 +1153,18 @@ fn test_spawn_sched_blocking() { let (start_po, start_ch) = stream(); let (fin_po, fin_ch) = stream(); - let lock = testrt::rust_dbg_lock_create(); + let mut lock = Mutex::new(); + let lock2 = Cell::new(lock.clone()); do spawn_sched(SingleThreaded) { - testrt::rust_dbg_lock_lock(lock); + let mut lock = lock2.take(); + lock.lock(); start_ch.send(()); // Block the scheduler thread - testrt::rust_dbg_lock_wait(lock); - testrt::rust_dbg_lock_unlock(lock); + lock.wait(); + lock.unlock(); fin_ch.send(()); }; @@ -1201,11 +1191,11 @@ fn test_spawn_sched_blocking() { let child_ch = setup_po.recv(); child_ch.send(20); pingpong(&parent_po, &child_ch); - testrt::rust_dbg_lock_lock(lock); - testrt::rust_dbg_lock_signal(lock); - testrt::rust_dbg_lock_unlock(lock); + lock.lock(); + lock.signal(); + lock.unlock(); fin_po.recv(); - testrt::rust_dbg_lock_destroy(lock); + lock.destroy(); } } } diff --git a/src/libstd/unstable/dynamic_lib.rs b/src/libstd/unstable/dynamic_lib.rs index 1ce228250c971..e0d284a32df1e 100644 --- a/src/libstd/unstable/dynamic_lib.rs +++ b/src/libstd/unstable/dynamic_lib.rs @@ -154,6 +154,9 @@ pub mod dl { } pub fn check_for_errors_in(f: &fn()->T) -> Result { + use unstable::mutex::{Mutex, MUTEX_INIT}; + static mut lock: Mutex = MUTEX_INIT; + unsafe { // dlerror isn't thread safe, so we need to lock around this entire // sequence. `atomically` asserts that we don't do anything that @@ -161,7 +164,7 @@ pub mod dl { // the scheduler if it happens while the lock is held. // FIXME #9105 use a Rust mutex instead of C++ mutexes. do atomically { - rust_take_dlerror_lock(); + lock.lock(); let _old_error = dlerror(); let result = f(); @@ -172,7 +175,7 @@ pub mod dl { } else { Err(str::raw::from_c_str(last_error)) }; - rust_drop_dlerror_lock(); + lock.unlock(); ret } } @@ -192,11 +195,6 @@ pub mod dl { Local = 0, } - extern { - fn rust_take_dlerror_lock(); - fn rust_drop_dlerror_lock(); - } - #[link_name = "dl"] extern { fn dlopen(filename: *libc::c_char, flag: libc::c_int) -> *libc::c_void; diff --git a/src/libstd/unstable/sync.rs b/src/libstd/unstable/sync.rs index 0e1f5fc1bdcfc..3423b995fda78 100644 --- a/src/libstd/unstable/sync.rs +++ b/src/libstd/unstable/sync.rs @@ -11,12 +11,12 @@ use cast; use cell::Cell; use comm; -use libc; use ptr; use option::{Option,Some,None}; use task; use unstable::atomics::{AtomicOption,AtomicUint,Acquire,Release,Relaxed,SeqCst}; use unstable::finally::Finally; +use unstable::mutex::Mutex; use ops::Drop; use clone::Clone; use kinds::Send; @@ -319,17 +319,14 @@ pub unsafe fn atomically(f: &fn() -> U) -> U { } } -#[allow(non_camel_case_types)] // runtime type -type rust_little_lock = *libc::c_void; - pub struct LittleLock { - priv l: rust_little_lock, + priv l: Mutex, } impl Drop for LittleLock { fn drop(&mut self) { unsafe { - rust_destroy_little_lock(self.l); + self.l.destroy(); } } } @@ -338,29 +335,31 @@ impl LittleLock { pub fn new() -> LittleLock { unsafe { LittleLock { - l: rust_create_little_lock() + l: Mutex::new() } } } pub unsafe fn lock(&self, f: &fn() -> T) -> T { + let this = cast::transmute_mut(self); do atomically { - rust_lock_little_lock(self.l); + this.l.lock(); do (|| { f() }).finally { - rust_unlock_little_lock(self.l); + this.l.unlock(); } } } pub unsafe fn try_lock(&self, f: &fn() -> T) -> Option { + let this = cast::transmute_mut(self); do atomically { - if rust_trylock_little_lock(self.l) { + if this.l.trylock() { Some(do (|| { f() }).finally { - rust_unlock_little_lock(self.l); + this.l.unlock(); }) } else { None @@ -369,18 +368,20 @@ impl LittleLock { } pub unsafe fn signal(&self) { - rust_signal_little_lock(self.l); + let this = cast::transmute_mut(self); + this.l.signal(); } pub unsafe fn lock_and_wait(&self, f: &fn() -> bool) { + let this = cast::transmute_mut(self); do atomically { - rust_lock_little_lock(self.l); + this.l.lock(); do (|| { if f() { - rust_wait_little_lock(self.l); + this.l.wait(); } }).finally { - rust_unlock_little_lock(self.l); + this.l.unlock(); } } } @@ -489,16 +490,6 @@ impl Exclusive { } } -extern { - fn rust_create_little_lock() -> rust_little_lock; - fn rust_destroy_little_lock(lock: rust_little_lock); - fn rust_trylock_little_lock(lock: rust_little_lock) -> bool; - fn rust_lock_little_lock(lock: rust_little_lock); - fn rust_unlock_little_lock(lock: rust_little_lock); - fn rust_signal_little_lock(lock: rust_little_lock); - fn rust_wait_little_lock(lock: rust_little_lock); -} - #[cfg(test)] mod tests { use cell::Cell; diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 28dd4b51a1313..31ab96f91b9cf 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -10,7 +10,7 @@ /* Foreign builtins. */ -#include "sync/lock_and_signal.h" +#include "rust_globals.h" #include "vg/valgrind.h" #include @@ -379,41 +379,6 @@ rust_mktime(rust_tm* timeptr) { return mktime(&t); } -extern "C" lock_and_signal* -rust_create_little_lock() { - return new lock_and_signal(); -} - -extern "C" void -rust_destroy_little_lock(lock_and_signal *lock) { - delete lock; -} - -extern "C" void -rust_lock_little_lock(lock_and_signal *lock) { - lock->lock(); -} - -extern "C" bool -rust_trylock_little_lock(lock_and_signal *lock) { - return lock->try_lock(); -} - -extern "C" void -rust_unlock_little_lock(lock_and_signal *lock) { - lock->unlock(); -} - -extern "C" void -rust_wait_little_lock(lock_and_signal *lock) { - lock->wait(); -} - -extern "C" void -rust_signal_little_lock(lock_and_signal *lock) { - lock->signal(); -} - #ifndef _WIN32 #include #include @@ -440,34 +405,6 @@ rust_readdir() { #endif -#ifndef _WIN32 -typedef pthread_key_t tls_key; -#else -typedef DWORD tls_key; -#endif - -// Initialize the TLS key used by the new scheduler -extern "C" CDECL void -rust_initialize_rt_tls_key(tls_key *key) { - - static lock_and_signal init_lock; - static bool initialized = false; - - scoped_lock with(init_lock); - - if (!initialized) { - -#ifndef _WIN32 - assert(!pthread_key_create(key, NULL)); -#else - *key = TlsAlloc(); - assert(*key != TLS_OUT_OF_INDEXES); -#endif - - initialized = true; - } -} - typedef void *(rust_try_fn)(void*, void*); extern "C" CDECL uintptr_t @@ -538,48 +475,6 @@ rust_get_num_cpus() { return get_num_cpus(); } -static lock_and_signal global_args_lock; -static uintptr_t global_args_ptr = 0; - -extern "C" CDECL void -rust_take_global_args_lock() { - global_args_lock.lock(); -} - -extern "C" CDECL void -rust_drop_global_args_lock() { - global_args_lock.unlock(); -} - -extern "C" CDECL uintptr_t* -rust_get_global_args_ptr() { - return &global_args_ptr; -} - -static lock_and_signal env_lock; - -extern "C" CDECL void -rust_take_env_lock() { - env_lock.lock(); -} - -extern "C" CDECL void -rust_drop_env_lock() { - env_lock.unlock(); -} - -static lock_and_signal dlerror_lock; - -extern "C" CDECL void -rust_take_dlerror_lock() { - dlerror_lock.lock(); -} - -extern "C" CDECL void -rust_drop_dlerror_lock() { - dlerror_lock.unlock(); -} - extern "C" CDECL unsigned int rust_valgrind_stack_register(void *start, void *end) { return VALGRIND_STACK_REGISTER(start, end); diff --git a/src/rt/rust_test_helpers.cpp b/src/rt/rust_test_helpers.cpp index 631745e656a3c..bf5fb059e7673 100644 --- a/src/rt/rust_test_helpers.cpp +++ b/src/rt/rust_test_helpers.cpp @@ -10,7 +10,7 @@ // Helper functions used only in tests -#include "sync/lock_and_signal.h" +#include "rust_globals.h" // These functions are used in the unit tests for C ABI calls. @@ -34,41 +34,6 @@ rust_dbg_extern_identity_u8(char u) { return u; } -extern "C" CDECL lock_and_signal * -rust_dbg_lock_create() { - return new lock_and_signal(); -} - -extern "C" CDECL void -rust_dbg_lock_destroy(lock_and_signal *lock) { - assert(lock); - delete lock; -} - -extern "C" CDECL void -rust_dbg_lock_lock(lock_and_signal *lock) { - assert(lock); - lock->lock(); -} - -extern "C" CDECL void -rust_dbg_lock_unlock(lock_and_signal *lock) { - assert(lock); - lock->unlock(); -} - -extern "C" CDECL void -rust_dbg_lock_wait(lock_and_signal *lock) { - assert(lock); - lock->wait(); -} - -extern "C" CDECL void -rust_dbg_lock_signal(lock_and_signal *lock) { - assert(lock); - lock->signal(); -} - typedef void *(*dbg_callback)(void*); extern "C" CDECL void * @@ -160,17 +125,6 @@ rust_dbg_extern_identity_TwoDoubles(TwoDoubles u) { return u; } -// Generates increasing port numbers for network testing -extern "C" CDECL uintptr_t -rust_dbg_next_port(uintptr_t base_port) { - static lock_and_signal dbg_port_lock; - static uintptr_t next_offset = 0; - scoped_lock with(dbg_port_lock); - uintptr_t this_port = base_port + next_offset; - next_offset += 1; - return this_port; -} - extern "C" CDECL intptr_t rust_get_test_int() { return 1; diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index d78584f33dfd8..c5b5e7f2c467a 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -26,21 +26,8 @@ rust_win32_rand_gen rust_win32_rand_release upcall_rust_personality upcall_reset_stack_limit -rust_dbg_lock_create -rust_dbg_lock_destroy -rust_dbg_lock_lock -rust_dbg_lock_unlock -rust_dbg_lock_wait -rust_dbg_lock_signal rust_dbg_call rust_dbg_do_nothing -rust_create_little_lock -rust_destroy_little_lock -rust_lock_little_lock -rust_trylock_little_lock -rust_unlock_little_lock -rust_signal_little_lock -rust_wait_little_lock tdefl_compress_mem_to_heap tinfl_decompress_mem_to_heap rust_swap_registers @@ -59,19 +46,12 @@ rust_dbg_extern_return_TwoU32s rust_dbg_extern_return_TwoU64s rust_dbg_extern_identity_double rust_dbg_extern_identity_u8 -rust_initialize_rt_tls_key -rust_dbg_next_port rust_try rust_begin_unwind rust_valgrind_stack_register rust_valgrind_stack_deregister -rust_take_env_lock -rust_drop_env_lock rust_running_on_valgrind rust_get_num_cpus -rust_get_global_args_ptr -rust_take_global_args_lock -rust_drop_global_args_lock rust_get_test_int rust_pthread_mutex_t_size rust_pthread_cond_t_size diff --git a/src/rt/sync/lock_and_signal.cpp b/src/rt/sync/lock_and_signal.cpp deleted file mode 100644 index fcf8ab5d88b39..0000000000000 --- a/src/rt/sync/lock_and_signal.cpp +++ /dev/null @@ -1,205 +0,0 @@ -// Copyright 2012 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. - - -#include "../rust_globals.h" -#include "lock_and_signal.h" - -/* - * A "lock-and-signal" pair. These are necessarily coupled on pthreads - * systems, and artificially coupled (by this file) on win32. Put - * together here to minimize ifdefs elsewhere; you must use them as - * if you're using a pthreads cvar+mutex pair. - */ - -// FIXME (#2683): This is not a portable way of specifying an invalid -// pthread_t -#define INVALID_THREAD 0 - - -#if defined(__WIN32__) -lock_and_signal::lock_and_signal() -#if defined(DEBUG_LOCKS) - : _holding_thread(INVALID_THREAD) -#endif -{ - _event = CreateEvent(NULL, FALSE, FALSE, NULL); - - // If a CRITICAL_SECTION is not initialized with a spin count, it will - // default to 0, even on multi-processor systems. MSDN suggests using - // 4000. On single-processor systems, the spin count parameter is ignored - // and the critical section's spin count defaults to 0. - const DWORD SPIN_COUNT = 4000; - CHECKED(!InitializeCriticalSectionAndSpinCount(&_cs, SPIN_COUNT)); - - // FIXME #2893 Consider checking - // GetProcAddress("InitializeCriticalSectionEx") - // so Windows >= Vista we can use CRITICAL_SECTION_NO_DEBUG_INFO to avoid - // allocating CRITICAL_SECTION debug info that is never released. See: - // http://stackoverflow.com/questions/804848/ - // critical-sections-leaking-memory-on-vista-win2008#889853 -} - -#else -lock_and_signal::lock_and_signal() -#if defined(DEBUG_LOCKS) - : _holding_thread(INVALID_THREAD) -#endif -{ - CHECKED(pthread_cond_init(&_cond, NULL)); - CHECKED(pthread_mutex_init(&_mutex, NULL)); -} -#endif - -lock_and_signal::~lock_and_signal() { -#if defined(__WIN32__) - CloseHandle(_event); - DeleteCriticalSection(&_cs); -#else - CHECKED(pthread_cond_destroy(&_cond)); - CHECKED(pthread_mutex_destroy(&_mutex)); -#endif -} - -void lock_and_signal::lock() { - must_not_have_lock(); -#if defined(__WIN32__) - EnterCriticalSection(&_cs); -#if defined(DEBUG_LOCKS) - _holding_thread = GetCurrentThreadId(); -#endif -#else - CHECKED(pthread_mutex_lock(&_mutex)); -#if defined(DEBUG_LOCKS) - _holding_thread = pthread_self(); -#endif -#endif -} - -bool lock_and_signal::try_lock() { - must_not_have_lock(); -#if defined(__WIN32__) - if (TryEnterCriticalSection(&_cs)) { -#if defined(DEBUG_LOCKS) - _holding_thread = GetCurrentThreadId(); -#endif - return true; - } -#else // non-windows - int trylock = pthread_mutex_trylock(&_mutex); - if (trylock == 0) { -#if defined(DEBUG_LOCKS) - _holding_thread = pthread_self(); -#endif - return true; - } else if (trylock == EBUSY) { - // EBUSY means lock was already held by someone else - return false; - } - // abort on all other errors - CHECKED(trylock); -#endif - return false; -} - -void lock_and_signal::unlock() { - must_have_lock(); -#if defined(DEBUG_LOCKS) - _holding_thread = INVALID_THREAD; -#endif -#if defined(__WIN32__) - LeaveCriticalSection(&_cs); -#else - CHECKED(pthread_mutex_unlock(&_mutex)); -#endif -} - -/** - * Wait indefinitely until condition is signaled. - */ -void lock_and_signal::wait() { - must_have_lock(); -#if defined(DEBUG_LOCKS) - _holding_thread = INVALID_THREAD; -#endif -#if defined(__WIN32__) - LeaveCriticalSection(&_cs); - WaitForSingleObject(_event, INFINITE); - EnterCriticalSection(&_cs); - must_not_be_locked(); -#if defined(DEBUG_LOCKS) - _holding_thread = GetCurrentThreadId(); -#endif -#else - CHECKED(pthread_cond_wait(&_cond, &_mutex)); - must_not_be_locked(); -#if defined(DEBUG_LOCKS) - _holding_thread = pthread_self(); -#endif -#endif -} - -/** - * Signal condition, and resume the waiting thread. - */ -void lock_and_signal::signal() { -#if defined(__WIN32__) - SetEvent(_event); -#else - CHECKED(pthread_cond_signal(&_cond)); -#endif -} - -#if defined(DEBUG_LOCKS) -bool lock_and_signal::lock_held_by_current_thread() -{ -#if defined(__WIN32__) - return _holding_thread == GetCurrentThreadId(); -#else - return pthread_equal(_holding_thread, pthread_self()); -#endif -} -#endif - -#if defined(DEBUG_LOCKS) -void lock_and_signal::must_have_lock() { - assert(lock_held_by_current_thread() && "must have lock"); -} -void lock_and_signal::must_not_have_lock() { - assert(!lock_held_by_current_thread() && "must not have lock"); -} -void lock_and_signal::must_not_be_locked() { -} -#else -void lock_and_signal::must_have_lock() { } -void lock_and_signal::must_not_have_lock() { } -void lock_and_signal::must_not_be_locked() { } -#endif - -scoped_lock::scoped_lock(lock_and_signal &lock) - : lock(lock) -{ - lock.lock(); -} - -scoped_lock::~scoped_lock() -{ - lock.unlock(); -} - -// -// Local Variables: -// mode: C++ -// fill-column: 78; -// indent-tabs-mode: nil -// c-basic-offset: 4 -// buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; -// End: diff --git a/src/rt/sync/lock_and_signal.h b/src/rt/sync/lock_and_signal.h deleted file mode 100644 index 45e1f7198516c..0000000000000 --- a/src/rt/sync/lock_and_signal.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2012 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. - -#ifndef LOCK_AND_SIGNAL_H -#define LOCK_AND_SIGNAL_H - -#include "rust_globals.h" - -#ifndef RUST_NDEBUG -#define DEBUG_LOCKS -#endif - -class lock_and_signal { -#if defined(__WIN32__) - HANDLE _event; - CRITICAL_SECTION _cs; -#if defined(DEBUG_LOCKS) - DWORD _holding_thread; -#endif -#else - pthread_cond_t _cond; - pthread_mutex_t _mutex; -#if defined(DEBUG_LOCKS) - pthread_t _holding_thread; -#endif -#endif - -#if defined(DEBUG_LOCKS) - bool lock_held_by_current_thread(); -#endif - - void must_not_be_locked(); - -public: - lock_and_signal(); - virtual ~lock_and_signal(); - - void lock(); - bool try_lock(); - void unlock(); - void wait(); - void signal(); - - void must_have_lock(); - void must_not_have_lock(); -}; - -class scoped_lock { - lock_and_signal &lock; - -public: - scoped_lock(lock_and_signal &lock); - ~scoped_lock(); -}; - -#endif /* LOCK_AND_SIGNAL_H */ From 508b7b996e5d557ec1c49e1d11563ecf4fc9d287 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 14 Nov 2013 10:04:55 -0800 Subject: [PATCH 3/3] Move runtime files to C instead of C++ Explicitly have the only C++ portion of the runtime be one file with exception handling. All other runtime files must now live in C and be fully defined in C. --- mk/clean.mk | 48 ++++--- mk/platform.mk | 4 +- mk/rt.mk | 27 ++-- src/libstd/rt/args.rs | 1 + src/rt/{miniz.cpp => miniz.c} | 0 ...android_dummy.cpp => rust_android_dummy.c} | 38 ++--- src/rt/{rust_builtin.cpp => rust_builtin.c} | 135 ++++++++---------- src/rt/rust_cxx_glue.cpp | 31 ++++ src/rt/rust_globals.h | 8 ++ ...t_test_helpers.cpp => rust_test_helpers.c} | 68 ++++----- src/rt/{rust_upcall.cpp => rust_upcall.c} | 28 ++-- src/rt/{rust_uv.cpp => rust_uv.c} | 68 ++++----- 12 files changed, 248 insertions(+), 208 deletions(-) rename src/rt/{miniz.cpp => miniz.c} (100%) rename src/rt/{rust_android_dummy.cpp => rust_android_dummy.c} (59%) rename src/rt/{rust_builtin.cpp => rust_builtin.c} (87%) create mode 100644 src/rt/rust_cxx_glue.cpp rename src/rt/{rust_test_helpers.cpp => rust_test_helpers.c} (70%) rename src/rt/{rust_upcall.cpp => rust_upcall.c} (78%) rename src/rt/{rust_uv.cpp => rust_uv.c} (87%) diff --git a/mk/clean.mk b/mk/clean.mk index d2f17fd52c8a9..dc2aefeb86534 100644 --- a/mk/clean.mk +++ b/mk/clean.mk @@ -12,13 +12,19 @@ # Cleanup ###################################################################### -CLEAN_STAGE_RULES = \ - $(foreach stage, $(STAGES), \ - $(foreach host, $(CFG_HOST), \ +CLEAN_STAGE_RULES := \ + $(foreach stage, $(STAGES), \ + $(foreach host, $(CFG_HOST), \ clean$(stage)_H_$(host) \ - $(foreach target, $(CFG_TARGET), \ + $(foreach target, $(CFG_TARGET), \ clean$(stage)_T_$(target)_H_$(host)))) +CLEAN_STAGE_RULES := $(CLEAN_STAGE_RULES) \ + $(foreach host, $(CFG_HOST), clean-generic-H-$(host)) + +CLEAN_STAGE_RULES := $(CLEAN_STAGE_RULES) \ + $(foreach host, $(CFG_TARGET), clean-generic-T-$(host)) + CLEAN_LLVM_RULES = \ $(foreach target, $(CFG_HOST), \ clean-llvm$(target)) @@ -33,19 +39,6 @@ clean: clean-misc $(CLEAN_STAGE_RULES) clean-misc: @$(call E, cleaning) - $(Q)find $(CFG_BUILD)/rustllvm \ - $(CFG_BUILD)/rt \ - $(CFG_BUILD)/test \ - -name '*.[odasS]' -o \ - -name '*.so' -o \ - -name '*.dylib' -o \ - -name '*.dll' -o \ - -name '*.def' -o \ - -name '*.bc' \ - | xargs rm -f - $(Q)find $(CFG_BUILD)\ - -name '*.dSYM' \ - | xargs rm -Rf $(Q)rm -f $(RUNTIME_OBJS) $(RUNTIME_DEF) $(Q)rm -f $(RUSTLLVM_LIB_OBJS) $(RUSTLLVM_OBJS_OBJS) $(RUSTLLVM_DEF) $(Q)rm -Rf $(DOCS) @@ -60,6 +53,27 @@ clean-misc: $(Q)rm -Rf $(foreach sub, index styles files search javascript, \ $(wildcard doc/*/$(sub))) +define CLEAN_GENERIC + +clean-generic-$(2)-$(1): + $(Q)find $(1)/rustllvm \ + $(1)/rt \ + $(1)/test \ + -name '*.[odasS]' -o \ + -name '*.so' -o \ + -name '*.dylib' -o \ + -name '*.dll' -o \ + -name '*.def' -o \ + -name '*.bc' \ + | xargs rm -f + $(Q)find $(1)\ + -name '*.dSYM' \ + | xargs rm -Rf +endef + +$(foreach host, $(CFG_HOST), $(eval $(call CLEAN_GENERIC,$(host),H))) +$(foreach targ, $(CFG_TARGET), $(eval $(call CLEAN_GENERIC,$(targ),T))) + define CLEAN_HOST_STAGE_N clean$(1)_H_$(2): diff --git a/mk/platform.mk b/mk/platform.mk index d9df4d42f5796..622f85302d3c0 100644 --- a/mk/platform.mk +++ b/mk/platform.mk @@ -206,7 +206,7 @@ CFG_LIB_GLOB_arm-apple-darwin = lib$(1)-*.dylib CFG_LIB_DSYM_GLOB_arm-apple-darwin = lib$(1)-*.dylib.dSYM CFG_GCCISH_CFLAGS_arm-apple-darwin := -Wall -Werror -g -fPIC $(CFG_IOS_FLAGS) CFG_GCCISH_CXXFLAGS_arm-apple-darwin := -fno-rtti $(CFG_IOS_FLAGS) -CFG_GCCISH_LINK_FLAGS_arm-apple-darwin := -dynamiclib -lpthread -framework CoreServices -Wl,-no_compact_unwind +CFG_GCCISH_LINK_FLAGS_arm-apple-darwin := -dynamiclib -lpthread -framework CoreServices -Wl,-no_compact_unwind CFG_GCCISH_DEF_FLAG_arm-apple-darwin := -Wl,-exported_symbols_list, CFG_GCCISH_PRE_LIB_FLAGS_arm-apple-darwin := CFG_GCCISH_POST_LIB_FLAGS_arm-apple-darwin := @@ -506,7 +506,7 @@ define CFG_MAKE_TOOLCHAIN -c -o $$(1) $$(2) CFG_LINK_C_$(1) = $$(CC_$(1)) \ $$(CFG_GCCISH_LINK_FLAGS) -o $$(1) \ - $$(CFG_GCCISH_LINK_FLAGS_$(1))) \ + $$(CFG_GCCISH_LINK_FLAGS_$(1)) \ $$(CFG_GCCISH_DEF_FLAG_$(1))$$(3) $$(2) \ $$(call CFG_INSTALL_NAME_$(1),$$(4)) CFG_COMPILE_CXX_$(1) = $$(CXX_$(1)) \ diff --git a/mk/rt.mk b/mk/rt.mk index 26e4222e4ebd7..94de05d0eaf11 100644 --- a/mk/rt.mk +++ b/mk/rt.mk @@ -90,13 +90,18 @@ endif endif RUNTIME_CXXS_$(1)_$(2) := \ - rt/rust_builtin.cpp \ - rt/rust_upcall.cpp \ - rt/miniz.cpp \ - rt/rust_android_dummy.cpp \ - rt/rust_test_helpers.cpp + rt/rust_cxx_glue.cpp -RUNTIME_CS_$(1)_$(2) := +RUNTIME_CS_$(1)_$(2) := \ + rt/rust_builtin.c \ + rt/rust_upcall.c \ + rt/miniz.c \ + rt/rust_android_dummy.c \ + rt/rust_test_helpers.c + +# stage0 remove this after the next snapshot +%.cpp: + @touch tmp/foo.o RUNTIME_S_$(1)_$(2) := rt/arch/$$(HOST_$(1))/_context.S \ rt/arch/$$(HOST_$(1))/record_sp.S @@ -114,7 +119,7 @@ ALL_OBJ_FILES += $$(RUNTIME_OBJS_$(1)_$(2)) MORESTACK_OBJS_$(1)_$(2) := $$(RT_BUILD_DIR_$(1)_$(2))/arch/$$(HOST_$(1))/morestack.o ALL_OBJ_FILES += $$(MORESTACK_OBJS_$(1)_$(2)) -$$(RT_BUILD_DIR_$(1)_$(2))/%.o: rt/%.cpp $$(MKFILE_DEPS) +$$(RT_BUILD_DIR_$(1)_$(2))/rust_cxx_glue.o: rt/rust_cxx_glue.cpp $$(MKFILE_DEPS) @$$(call E, compile: $$@) $$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@, $$(RUNTIME_INCS_$(1)_$(2)) \ $$(SNAP_DEFINES) $$(RUNTIME_CXXFLAGS_$(1)_$(2))) $$< @@ -241,13 +246,13 @@ endif UV_SUPPORT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),uv_support) UV_SUPPORT_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/uv_support UV_SUPPORT_LIB_$(1) := $$(UV_SUPPORT_DIR_$(1))/$$(UV_SUPPORT_NAME_$(1)) -UV_SUPPORT_CS_$(1) := rt/rust_uv.cpp -UV_SUPPORT_OBJS_$(1) := $$(UV_SUPPORT_CS_$(1):rt/%.cpp=$$(UV_SUPPORT_DIR_$(1))/%.o) +UV_SUPPORT_CS_$(1) := rt/rust_uv.c +UV_SUPPORT_OBJS_$(1) := $$(UV_SUPPORT_CS_$(1):rt/%.c=$$(UV_SUPPORT_DIR_$(1))/%.o) -$$(UV_SUPPORT_DIR_$(1))/%.o: rt/%.cpp +$$(UV_SUPPORT_DIR_$(1))/%.o: rt/%.c @$$(call E, compile: $$@) @mkdir -p $$(@D) - $$(Q)$$(call CFG_COMPILE_CXX_$(1), $$@, \ + $$(Q)$$(call CFG_COMPILE_C_$(1), $$@, \ -I $$(S)src/libuv/include \ $$(RUNTIME_CFLAGS_$(1))) $$< diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index b9238224d6e98..0d32d2d7dbae0 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -63,6 +63,7 @@ pub unsafe fn init(argc: int, argv: **u8) { realargs::init(argc, argv) } #[cfg(target_os = "android")] #[cfg(target_os = "freebsd")] mod imp { + use cast; use libc; use option::{Option, Some, None}; use iter::Iterator; diff --git a/src/rt/miniz.cpp b/src/rt/miniz.c similarity index 100% rename from src/rt/miniz.cpp rename to src/rt/miniz.c diff --git a/src/rt/rust_android_dummy.cpp b/src/rt/rust_android_dummy.c similarity index 59% rename from src/rt/rust_android_dummy.cpp rename to src/rt/rust_android_dummy.c index 05869c010af04..9d91b99507336 100644 --- a/src/rt/rust_android_dummy.cpp +++ b/src/rt/rust_android_dummy.c @@ -14,53 +14,53 @@ char **backtrace_symbols(void *const *array, int size) { return 0; } void backtrace_symbols_fd (void *const *array, int size, int fd) {} -extern "C" volatile int* __errno_location() { +volatile int* __errno_location() { return &errno; } -extern "C" float log2f(float f) +float log2f(float f) { return logf( f ) / logf( 2 ); } -extern "C" double log2( double n ) +double log2( double n ) { return log( n ) / log( 2 ); } -extern "C" void telldir() +void telldir() { } -extern "C" void seekdir() +void seekdir() { } -extern "C" void mkfifo() +void mkfifo() { } -extern "C" void abs() +void abs() { } -extern "C" void labs() +void labs() { } -extern "C" void rand() +void rand() { } -extern "C" void srand() +void srand() { } -extern "C" void atof() +void atof() { } -extern "C" int glob(const char *pattern, +int glob(const char *pattern, int flags, int (*errfunc) (const char *epath, int eerrno), glob_t *pglob) @@ -68,38 +68,38 @@ extern "C" int glob(const char *pattern, return 0; } -extern "C" void globfree(glob_t *pglob) +void globfree(glob_t *pglob) { } -extern "C" int pthread_atfork(void (*prefork)(void), +int pthread_atfork(void (*prefork)(void), void (*postfork_parent)(void), void (*postfork_child)(void)) { return 0; } -extern "C" int mlockall(int flags) +int mlockall(int flags) { return 0; } -extern "C" int munlockall(void) +int munlockall(void) { return 0; } -extern "C" int shm_open(const char *name, int oflag, mode_t mode) +int shm_open(const char *name, int oflag, mode_t mode) { return 0; } -extern "C" int shm_unlink(const char *name) +int shm_unlink(const char *name) { return 0; } -extern "C" int posix_madvise(void *addr, size_t len, int advice) +int posix_madvise(void *addr, size_t len, int advice) { return 0; } diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.c similarity index 87% rename from src/rt/rust_builtin.cpp rename to src/rt/rust_builtin.c index 31ab96f91b9cf..c8ed61bfc41a9 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.c @@ -58,12 +58,12 @@ timegm(struct tm *tm) #endif #if defined(__WIN32__) -extern "C" CDECL char** +char** rust_env_pairs() { return 0; } #else -extern "C" CDECL char** +char** rust_env_pairs() { #if defined(__APPLE__) && !(TARGET_OS_IPHONE) char **environ = *_NSGetEnviron(); @@ -72,18 +72,18 @@ rust_env_pairs() { } #endif -extern "C" CDECL char* +char* #if defined(__WIN32__) rust_list_dir_val(WIN32_FIND_DATA* entry_ptr) { return entry_ptr->cFileName; } #else -rust_list_dir_val(dirent* entry_ptr) { +rust_list_dir_val(struct dirent* entry_ptr) { return entry_ptr->d_name; } #endif -extern "C" CDECL size_t +size_t #if defined(__WIN32__) rust_list_dir_wfd_size() { return sizeof(WIN32_FIND_DATAW); @@ -94,7 +94,7 @@ rust_list_dir_wfd_size() { } #endif -extern "C" CDECL void* +void* #if defined(__WIN32__) rust_list_dir_wfd_fp_buf(WIN32_FIND_DATAW* wfd) { if(wfd == NULL) { @@ -110,7 +110,7 @@ rust_list_dir_wfd_fp_buf(void* wfd) { } #endif -extern "C" CDECL int +int rust_path_is_dir(const char *path) { struct stat buf; if (stat(path, &buf)) { @@ -119,7 +119,7 @@ rust_path_is_dir(const char *path) { return S_ISDIR(buf.st_mode); } -extern "C" CDECL int +int #if defined(__WIN32__) rust_path_is_dir_u16(const wchar_t *path) { struct _stat buf; @@ -137,7 +137,7 @@ rust_path_is_dir_u16(const void *path) { } #endif -extern "C" CDECL int +int rust_path_exists(const char *path) { struct stat buf; if (stat(path, &buf)) { @@ -146,7 +146,7 @@ rust_path_exists(const char *path) { return 1; } -extern "C" CDECL int +int #if defined(__WIN32__) rust_path_exists_u16(const wchar_t *path) { struct _stat buf; @@ -162,12 +162,12 @@ rust_path_exists_u16(const void *path) { } #endif -extern "C" CDECL FILE* rust_get_stdin() {return stdin;} -extern "C" CDECL FILE* rust_get_stdout() {return stdout;} -extern "C" CDECL FILE* rust_get_stderr() {return stderr;} +FILE* rust_get_stdin() {return stdin;} +FILE* rust_get_stdout() {return stdout;} +FILE* rust_get_stderr() {return stderr;} #if defined(__WIN32__) -extern "C" CDECL void +void rust_get_time(int64_t *sec, int32_t *nsec) { FILETIME fileTime; GetSystemTimeAsFileTime(&fileTime); @@ -186,7 +186,7 @@ rust_get_time(int64_t *sec, int32_t *nsec) { *nsec = (ns_since_1970 % 1000000) * 1000; } #else -extern "C" CDECL void +void rust_get_time(int64_t *sec, int32_t *nsec) { #ifdef __APPLE__ struct timeval tv; @@ -194,7 +194,7 @@ rust_get_time(int64_t *sec, int32_t *nsec) { *sec = tv.tv_sec; *nsec = tv.tv_usec * 1000; #else - timespec ts; + struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); *sec = ts.tv_sec; *nsec = ts.tv_nsec; @@ -204,7 +204,7 @@ rust_get_time(int64_t *sec, int32_t *nsec) { const int64_t ns_per_s = 1000000000LL; -extern "C" CDECL void +void rust_precise_time_ns(uint64_t *ns) { #ifdef __APPLE__ @@ -227,23 +227,22 @@ rust_precise_time_ns(uint64_t *ns) { assert(query_result); *ns = (uint64_t)((ticks.QuadPart * ns_per_s) / ticks_per_s.QuadPart); #else - timespec ts; + struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); *ns = (uint64_t)(ts.tv_sec * ns_per_s + ts.tv_nsec); #endif } -struct -rust_vec +typedef struct { size_t fill; // in bytes; if zero, heapified size_t alloc; // in bytes uint8_t data[0]; -}; +} rust_vec; typedef rust_vec rust_str; -struct rust_tm { +typedef struct { int32_t tm_sec; int32_t tm_min; int32_t tm_hour; @@ -256,10 +255,10 @@ struct rust_tm { int32_t tm_gmtoff; rust_str *tm_zone; int32_t tm_nsec; -}; +} rust_tm; -void rust_tm_to_tm(rust_tm* in_tm, tm* out_tm) { - memset(out_tm, 0, sizeof(tm)); +void rust_tm_to_tm(rust_tm* in_tm, struct tm* out_tm) { + memset(out_tm, 0, sizeof(struct tm)); out_tm->tm_sec = in_tm->tm_sec; out_tm->tm_min = in_tm->tm_min; out_tm->tm_hour = in_tm->tm_hour; @@ -271,7 +270,7 @@ void rust_tm_to_tm(rust_tm* in_tm, tm* out_tm) { out_tm->tm_isdst = in_tm->tm_isdst; } -void tm_to_rust_tm(tm* in_tm, rust_tm* out_tm, int32_t gmtoff, +void tm_to_rust_tm(struct tm* in_tm, rust_tm* out_tm, int32_t gmtoff, const char *zone, int32_t nsec) { out_tm->tm_sec = in_tm->tm_sec; out_tm->tm_min = in_tm->tm_min; @@ -300,13 +299,13 @@ void tm_to_rust_tm(tm* in_tm, rust_tm* out_tm, int32_t gmtoff, #define LOCALTIME(clock, result) localtime_s((result), (clock)) #define TIMEGM(result) _mkgmtime64(result) #else -struct tm* GMTIME(const time_t *clock, tm *result) { +struct tm* GMTIME(const time_t *clock, struct tm *result) { struct tm* t = gmtime(clock); if (t == NULL || result == NULL) { return NULL; } *result = *t; return result; } -struct tm* LOCALTIME(const time_t *clock, tm *result) { +struct tm* LOCALTIME(const time_t *clock, struct tm *result) { struct tm* t = localtime(clock); if (t == NULL || result == NULL) { return NULL; } *result = *t; @@ -321,23 +320,23 @@ struct tm* LOCALTIME(const time_t *clock, tm *result) { #define TIMEGM(result) timegm(result) #endif -extern "C" CDECL void +void rust_tzset() { TZSET(); } -extern "C" CDECL void +void rust_gmtime(int64_t sec, int32_t nsec, rust_tm *timeptr) { - tm tm; + struct tm tm; time_t s = sec; GMTIME(&s, &tm); tm_to_rust_tm(&tm, timeptr, 0, "UTC", nsec); } -extern "C" CDECL void +void rust_localtime(int64_t sec, int32_t nsec, rust_tm *timeptr) { - tm tm; + struct tm tm; time_t s = sec; LOCALTIME(&s, &tm); @@ -365,16 +364,16 @@ rust_localtime(int64_t sec, int32_t nsec, rust_tm *timeptr) { tm_to_rust_tm(&tm, timeptr, gmtoff, zone, nsec); } -extern "C" CDECL int64_t +int64_t rust_timegm(rust_tm* timeptr) { - tm t; + struct tm t; rust_tm_to_tm(timeptr, &t); return TIMEGM(&t); } -extern "C" CDECL int64_t +int64_t rust_mktime(rust_tm* timeptr) { - tm t; + struct tm t; rust_tm_to_tm(timeptr, &t); return mktime(&t); } @@ -383,47 +382,29 @@ rust_mktime(rust_tm* timeptr) { #include #include -extern "C" DIR* +DIR* rust_opendir(char *dirname) { return opendir(dirname); } -extern "C" dirent* +struct dirent* rust_readdir(DIR *dirp) { return readdir(dirp); } #else -extern "C" void +void rust_opendir() { } -extern "C" void +void rust_readdir() { } #endif -typedef void *(rust_try_fn)(void*, void*); - -extern "C" CDECL uintptr_t -rust_try(rust_try_fn f, void *fptr, void *env) { - try { - f(fptr, env); - } catch (uintptr_t token) { - assert(token != 0); - return token; - } - return 0; -} - -extern "C" CDECL void -rust_begin_unwind(uintptr_t token) { - throw token; -} - -extern "C" CDECL uintptr_t +uintptr_t rust_running_on_valgrind() { return RUNNING_ON_VALGRIND; } @@ -470,24 +451,24 @@ get_num_cpus() { } #endif -extern "C" CDECL uintptr_t +uintptr_t rust_get_num_cpus() { return get_num_cpus(); } -extern "C" CDECL unsigned int +unsigned int rust_valgrind_stack_register(void *start, void *end) { return VALGRIND_STACK_REGISTER(start, end); } -extern "C" CDECL void +void rust_valgrind_stack_deregister(unsigned int id) { VALGRIND_STACK_DEREGISTER(id); } #if defined(__WIN32__) -extern "C" CDECL void +void rust_unset_sigprocmask() { // empty stub for windows to keep linker happy } @@ -497,7 +478,7 @@ rust_unset_sigprocmask() { #include #include -extern "C" CDECL void +void rust_unset_sigprocmask() { // this can't be safely converted to rust code because the // representation of sigset_t is platform-dependent @@ -526,7 +507,7 @@ win32_require(LPCTSTR fn, BOOL ok) { } } -extern "C" CDECL void +void rust_win32_rand_acquire(HCRYPTPROV* phProv) { win32_require (_T("CryptAcquireContext"), @@ -536,12 +517,12 @@ rust_win32_rand_acquire(HCRYPTPROV* phProv) { CRYPT_VERIFYCONTEXT|CRYPT_SILENT)); } -extern "C" CDECL void +void rust_win32_rand_gen(HCRYPTPROV hProv, DWORD dwLen, BYTE* pbBuffer) { win32_require (_T("CryptGenRandom"), CryptGenRandom(hProv, dwLen, pbBuffer)); } -extern "C" CDECL void +void rust_win32_rand_release(HCRYPTPROV hProv) { win32_require (_T("CryptReleaseContext"), CryptReleaseContext(hProv, 0)); @@ -552,15 +533,15 @@ rust_win32_rand_release(HCRYPTPROV hProv) { // these symbols are listed in rustrt.def.in, so they need to exist; but they // should never be called. -extern "C" CDECL void +void rust_win32_rand_acquire() { abort(); } -extern "C" CDECL void +void rust_win32_rand_gen() { abort(); } -extern "C" CDECL void +void rust_win32_rand_release() { abort(); } @@ -569,20 +550,20 @@ rust_win32_rand_release() { #if defined(__WIN32__) -extern "C" CDECL int +int rust_crit_section_size() { return sizeof(CRITICAL_SECTION); } -extern "C" CDECL int +int rust_pthread_mutex_t_size() { return 0; } -extern "C" CDECL int +int rust_pthread_cond_t_size() { return 0; } #else -extern "C" CDECL int +int rust_crit_section_size() { return 0; } -extern "C" CDECL int +int rust_pthread_mutex_t_size() { return sizeof(pthread_mutex_t); } -extern "C" CDECL int +int rust_pthread_cond_t_size() { return sizeof(pthread_cond_t); } #endif diff --git a/src/rt/rust_cxx_glue.cpp b/src/rt/rust_cxx_glue.cpp new file mode 100644 index 0000000000000..b44d29642c4b7 --- /dev/null +++ b/src/rt/rust_cxx_glue.cpp @@ -0,0 +1,31 @@ +// 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. + +/* Foreign builtins which require C++ */ + +#include "rust_globals.h" + +typedef void *(rust_try_fn)(void*, void*); + +extern "C" CDECL uintptr_t +rust_try(rust_try_fn f, void *fptr, void *env) { + try { + f(fptr, env); + } catch (uintptr_t token) { + assert(token != 0); + return token; + } + return 0; +} + +extern "C" CDECL void +rust_begin_unwind(uintptr_t token) { + throw token; +} diff --git a/src/rt/rust_globals.h b/src/rt/rust_globals.h index b6191fb4bd12c..317f8af237fa1 100644 --- a/src/rt/rust_globals.h +++ b/src/rt/rust_globals.h @@ -39,6 +39,10 @@ #define __STDC_FORMAT_MACROS 1 #endif +#ifndef _GNU_SOURCE +#define _GNU_SOURCE 1 +#endif + #define ERROR 0 #include @@ -62,11 +66,15 @@ #ifndef NOMINMAX #define NOMINMAX #endif +#if defined(__cplusplus) extern "C" { +#endif #include #include #include +#if defined(__cplusplus) } +#endif #elif defined(__GNUC__) #include #include diff --git a/src/rt/rust_test_helpers.cpp b/src/rt/rust_test_helpers.c similarity index 70% rename from src/rt/rust_test_helpers.cpp rename to src/rt/rust_test_helpers.c index bf5fb059e7673..d2b69337e7251 100644 --- a/src/rt/rust_test_helpers.cpp +++ b/src/rt/rust_test_helpers.c @@ -14,41 +14,41 @@ // These functions are used in the unit tests for C ABI calls. -extern "C" CDECL uint32_t +uint32_t rust_dbg_extern_identity_u32(uint32_t u) { return u; } -extern "C" CDECL uint64_t +uint64_t rust_dbg_extern_identity_u64(uint64_t u) { return u; } -extern "C" CDECL double +double rust_dbg_extern_identity_double(double u) { return u; } -extern "C" CDECL char +char rust_dbg_extern_identity_u8(char u) { return u; } typedef void *(*dbg_callback)(void*); -extern "C" CDECL void * +void * rust_dbg_call(dbg_callback cb, void *data) { return cb(data); } -extern "C" CDECL void rust_dbg_do_nothing() { } +void rust_dbg_do_nothing() { } struct TwoU8s { uint8_t one; uint8_t two; }; -extern "C" CDECL TwoU8s +struct TwoU8s rust_dbg_extern_return_TwoU8s() { struct TwoU8s s; s.one = 10; @@ -56,8 +56,8 @@ rust_dbg_extern_return_TwoU8s() { return s; } -extern "C" CDECL TwoU8s -rust_dbg_extern_identity_TwoU8s(TwoU8s u) { +struct TwoU8s +rust_dbg_extern_identity_TwoU8s(struct TwoU8s u) { return u; } @@ -66,7 +66,7 @@ struct TwoU16s { uint16_t two; }; -extern "C" CDECL TwoU16s +struct TwoU16s rust_dbg_extern_return_TwoU16s() { struct TwoU16s s; s.one = 10; @@ -74,8 +74,8 @@ rust_dbg_extern_return_TwoU16s() { return s; } -extern "C" CDECL TwoU16s -rust_dbg_extern_identity_TwoU16s(TwoU16s u) { +struct TwoU16s +rust_dbg_extern_identity_TwoU16s(struct TwoU16s u) { return u; } @@ -84,7 +84,7 @@ struct TwoU32s { uint32_t two; }; -extern "C" CDECL TwoU32s +struct TwoU32s rust_dbg_extern_return_TwoU32s() { struct TwoU32s s; s.one = 10; @@ -92,8 +92,8 @@ rust_dbg_extern_return_TwoU32s() { return s; } -extern "C" CDECL TwoU32s -rust_dbg_extern_identity_TwoU32s(TwoU32s u) { +struct TwoU32s +rust_dbg_extern_identity_TwoU32s(struct TwoU32s u) { return u; } @@ -102,7 +102,7 @@ struct TwoU64s { uint64_t two; }; -extern "C" CDECL TwoU64s +struct TwoU64s rust_dbg_extern_return_TwoU64s() { struct TwoU64s s; s.one = 10; @@ -110,8 +110,8 @@ rust_dbg_extern_return_TwoU64s() { return s; } -extern "C" CDECL TwoU64s -rust_dbg_extern_identity_TwoU64s(TwoU64s u) { +struct TwoU64s +rust_dbg_extern_identity_TwoU64s(struct TwoU64s u) { return u; } @@ -120,12 +120,12 @@ struct TwoDoubles { double two; }; -extern "C" CDECL TwoDoubles -rust_dbg_extern_identity_TwoDoubles(TwoDoubles u) { +struct TwoDoubles +rust_dbg_extern_identity_TwoDoubles(struct TwoDoubles u) { return u; } -extern "C" CDECL intptr_t +intptr_t rust_get_test_int() { return 1; } @@ -149,29 +149,29 @@ struct floats { double c; }; -extern "C" quad -rust_dbg_abi_1(quad q) { - quad qq = { q.c + 1, - q.d - 1, - q.a + 1, - q.b - 1 }; +struct quad +rust_dbg_abi_1(struct quad q) { + struct quad qq = { q.c + 1, + q.d - 1, + q.a + 1, + q.b - 1 }; return qq; } -extern "C" floats -rust_dbg_abi_2(floats f) { - floats ff = { f.c + 1.0, - 0xff, - f.a - 1.0 }; +struct floats +rust_dbg_abi_2(struct floats f) { + struct floats ff = { f.c + 1.0, + 0xff, + f.a - 1.0 }; return ff; } -extern "C" int +int rust_dbg_static_mut; int rust_dbg_static_mut = 3; -extern "C" void +void rust_dbg_static_mut_check_four() { assert(rust_dbg_static_mut == 4); } diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.c similarity index 78% rename from src/rt/rust_upcall.cpp rename to src/rt/rust_upcall.c index 95f4bec02e95c..16621d29d4a38 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.c @@ -35,24 +35,24 @@ struct _Unwind_Exception; # endif #endif -extern "C" _Unwind_Reason_Code +_Unwind_Reason_Code PERSONALITY_FUNC(int version, _Unwind_Action actions, uint64_t exception_class, - _Unwind_Exception *ue_header, - _Unwind_Context *context); + struct _Unwind_Exception *ue_header, + struct _Unwind_Context *context); struct s_rust_personality_args { _Unwind_Reason_Code retval; int version; _Unwind_Action actions; uint64_t exception_class; - _Unwind_Exception *ue_header; - _Unwind_Context *context; + struct _Unwind_Exception *ue_header; + struct _Unwind_Context *context; }; -extern "C" void -upcall_s_rust_personality(s_rust_personality_args *args) { +void +upcall_s_rust_personality(struct s_rust_personality_args *args) { args->retval = PERSONALITY_FUNC(args->version, args->actions, args->exception_class, @@ -65,15 +65,15 @@ upcall_s_rust_personality(s_rust_personality_args *args) { out what to do with each landing pad. Just a stack-switching wrapper around the C++ personality function. */ -extern "C" _Unwind_Reason_Code +_Unwind_Reason_Code upcall_rust_personality(int version, _Unwind_Action actions, uint64_t exception_class, - _Unwind_Exception *ue_header, - _Unwind_Context *context) { - s_rust_personality_args args = {(_Unwind_Reason_Code)0, - version, actions, exception_class, - ue_header, context}; + struct _Unwind_Exception *ue_header, + struct _Unwind_Context *context) { + struct s_rust_personality_args args = {(_Unwind_Reason_Code)0, + version, actions, exception_class, + ue_header, context}; upcall_s_rust_personality(&args); return args.retval; } @@ -82,7 +82,7 @@ upcall_rust_personality(int version, // correct limit into TLS. // NB: This must run on the Rust stack because it // needs to acquire the value of the stack pointer -extern "C" CDECL void +void upcall_reset_stack_limit() { } diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.c similarity index 87% rename from src/rt/rust_uv.cpp rename to src/rt/rust_uv.c index f3be486a25ab2..9c9f7d14e5a30 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.c @@ -22,7 +22,7 @@ #include "rust_globals.h" -extern "C" void* +void* rust_uv_loop_new() { // XXX libuv doesn't always ignore SIGPIPE even though we don't need it. #ifndef __WIN32__ @@ -31,67 +31,67 @@ rust_uv_loop_new() { return (void*)uv_loop_new(); } -extern "C" void +void rust_uv_loop_set_data(uv_loop_t* loop, void* data) { loop->data = data; } -extern "C" uv_udp_t* +uv_udp_t* rust_uv_get_udp_handle_from_send_req(uv_udp_send_t* send_req) { return send_req->handle; } -extern "C" uv_stream_t* +uv_stream_t* rust_uv_get_stream_handle_from_connect_req(uv_connect_t* connect) { return connect->handle; } -extern "C" uv_stream_t* +uv_stream_t* rust_uv_get_stream_handle_from_write_req(uv_write_t* write_req) { return write_req->handle; } -extern "C" uv_loop_t* +uv_loop_t* rust_uv_get_loop_for_uv_handle(uv_handle_t* handle) { return handle->loop; } -extern "C" void* +void* rust_uv_get_data_for_uv_loop(uv_loop_t* loop) { return loop->data; } -extern "C" void +void rust_uv_set_data_for_uv_loop(uv_loop_t* loop, void* data) { loop->data = data; } -extern "C" void* +void* rust_uv_get_data_for_uv_handle(uv_handle_t* handle) { return handle->data; } -extern "C" void +void rust_uv_set_data_for_uv_handle(uv_handle_t* handle, void* data) { handle->data = data; } -extern "C" void* +void* rust_uv_get_data_for_req(uv_req_t* req) { return req->data; } -extern "C" void +void rust_uv_set_data_for_req(uv_req_t* req, void* data) { req->data = data; } -extern "C" int +int rust_sockaddr_size() { return sizeof(struct sockaddr_storage); } -extern "C" struct sockaddr* +struct sockaddr* rust_malloc_ip4_addr(char *name, int port) { struct sockaddr_in *addr = (struct sockaddr_in*) calloc(1, rust_sockaddr_size()); assert(addr != NULL); @@ -101,7 +101,7 @@ rust_malloc_ip4_addr(char *name, int port) { return (struct sockaddr*) addr; } -extern "C" struct sockaddr* +struct sockaddr* rust_malloc_ip6_addr(char *name, int port) { struct sockaddr_in6 *addr = (struct sockaddr_in6*) calloc(1, rust_sockaddr_size()); assert(addr != NULL); @@ -111,58 +111,58 @@ rust_malloc_ip6_addr(char *name, int port) { return (struct sockaddr*) addr; } -extern "C" unsigned int +unsigned int rust_ip4_port(struct sockaddr_in* src) { return ntohs(src->sin_port); } -extern "C" unsigned int +unsigned int rust_ip6_port(struct sockaddr_in6* src) { return ntohs(src->sin6_port); } -extern "C" int -rust_is_ipv4_sockaddr(sockaddr* addr) { +int +rust_is_ipv4_sockaddr(struct sockaddr* addr) { return addr->sa_family == AF_INET; } -extern "C" int -rust_is_ipv6_sockaddr(sockaddr* addr) { +int +rust_is_ipv6_sockaddr(struct sockaddr* addr) { return addr->sa_family == AF_INET6; } -extern "C" uintptr_t +uintptr_t rust_uv_handle_type_max() { return UV_HANDLE_TYPE_MAX; } -extern "C" uintptr_t +uintptr_t rust_uv_req_type_max() { return UV_REQ_TYPE_MAX; } -extern "C" int +int rust_uv_get_result_from_fs_req(uv_fs_t* req) { return req->result; } -extern "C" const char* +const char* rust_uv_get_path_from_fs_req(uv_fs_t* req) { return req->path; } -extern "C" void* +void* rust_uv_get_ptr_from_fs_req(uv_fs_t* req) { return req->ptr; } -extern "C" uv_loop_t* +uv_loop_t* rust_uv_get_loop_from_fs_req(uv_fs_t* req) { return req->loop; } -extern "C" uv_loop_t* +uv_loop_t* rust_uv_get_loop_from_getaddrinfo_req(uv_getaddrinfo_t* req) { return req->loop; } -extern "C" void +void rust_uv_populate_uv_stat(uv_fs_t* req_in, uv_stat_t* stat_out) { stat_out->st_dev = req_in->statbuf.st_dev; stat_out->st_mode = req_in->statbuf.st_mode; @@ -186,27 +186,27 @@ rust_uv_populate_uv_stat(uv_fs_t* req_in, uv_stat_t* stat_out) { stat_out->st_birthtim.tv_nsec = req_in->statbuf.st_birthtim.tv_nsec; } -extern "C" void +void rust_set_stdio_container_flags(uv_stdio_container_t *c, int flags) { c->flags = (uv_stdio_flags) flags; } -extern "C" void +void rust_set_stdio_container_fd(uv_stdio_container_t *c, int fd) { c->data.fd = fd; } -extern "C" void +void rust_set_stdio_container_stream(uv_stdio_container_t *c, uv_stream_t *stream) { c->data.stream = stream; } -extern "C" int +int rust_uv_process_pid(uv_process_t* p) { return p->pid; } -extern "C" int +int rust_uv_guess_handle(int fd) { return uv_guess_handle(fd); }