about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-03-06 00:41:48 -0800
committerbors <bors@rust-lang.org>2014-03-06 00:41:48 -0800
commit2fba2fea121b616793287f33aa3ee05e8d8893b0 (patch)
tree7b6d2bd1a7449d81b9b6acb7c1099eca91df414d /src/libstd
parent2153293ae434861c72469d41fc7c9dfe9b90b1c4 (diff)
parent9668ab58f338b27d8f53357c7fd4ea3d3f06305e (diff)
downloadrust-2fba2fea121b616793287f33aa3ee05e8d8893b0.tar.gz
rust-2fba2fea121b616793287f33aa3ee05e8d8893b0.zip
auto merge of #12705 : alexcrichton/rust/issue-12692, r=brson
Details are in the commit messages, but this closes a few issues seen with `libnative` recently.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/libc.rs11
-rw-r--r--src/libstd/rt/bookkeeping.rs52
-rw-r--r--src/libstd/rt/mod.rs4
3 files changed, 64 insertions, 3 deletions
diff --git a/src/libstd/libc.rs b/src/libstd/libc.rs
index 0ef8570ce30..afd524e9d7a 100644
--- a/src/libstd/libc.rs
+++ b/src/libstd/libc.rs
@@ -3658,13 +3658,16 @@ pub mod funcs {
             pub unsafe fn opendir(dirname: *c_char) -> *DIR {
                 rust_opendir(dirname)
             }
-            pub unsafe fn readdir(dirp: *DIR) -> *dirent_t {
-                rust_readdir(dirp)
+            pub unsafe fn readdir_r(dirp: *DIR,
+                                    entry: *mut dirent_t,
+                                    result: *mut *mut dirent_t) -> c_int {
+                rust_readdir_r(dirp, entry, result)
             }
 
             extern {
                 fn rust_opendir(dirname: *c_char) -> *DIR;
-                fn rust_readdir(dirp: *DIR) -> *dirent_t;
+                fn rust_readdir_r(dirp: *DIR, entry: *mut dirent_t,
+                                  result: *mut *mut dirent_t) -> c_int;
             }
 
             extern {
@@ -3680,6 +3683,7 @@ pub mod funcs {
             use libc::types::common::c95::c_void;
             use libc::types::os::arch::c95::{c_char, c_int, c_long, c_uint};
             use libc::types::os::arch::c95::{size_t};
+            use libc::types::os::common::posix01::timespec;
             use libc::types::os::arch::posix01::utimbuf;
             use libc::types::os::arch::posix88::{gid_t, off_t, pid_t};
             use libc::types::os::arch::posix88::{ssize_t, uid_t};
@@ -3729,6 +3733,7 @@ pub mod funcs {
                 pub fn setuid(uid: uid_t) -> c_int;
                 pub fn sleep(secs: c_uint) -> c_uint;
                 pub fn usleep(secs: c_uint) -> c_int;
+                pub fn nanosleep(rqtp: *timespec, rmtp: *mut timespec) -> c_int;
                 pub fn sysconf(name: c_int) -> c_long;
                 pub fn tcgetpgrp(fd: c_int) -> pid_t;
                 pub fn ttyname(fd: c_int) -> *c_char;
diff --git a/src/libstd/rt/bookkeeping.rs b/src/libstd/rt/bookkeeping.rs
new file mode 100644
index 00000000000..5851a6a39c6
--- /dev/null
+++ b/src/libstd/rt/bookkeeping.rs
@@ -0,0 +1,52 @@
+// Copyright 2013-2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Task bookkeeping
+//!
+//! This module keeps track of the number of running tasks so that entry points
+//! with libnative know when it's possible to exit the program (once all tasks
+//! have exited).
+//!
+//! The green counterpart for this is bookkeeping on sched pools, and it's up to
+//! each respective runtime to make sure that they call increment() and
+//! decrement() manually.
+
+#[experimental]; // this is a massive code smell
+#[doc(hidden)];
+
+use sync::atomics;
+use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
+
+static mut TASK_COUNT: atomics::AtomicUint = atomics::INIT_ATOMIC_UINT;
+static mut TASK_LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
+
+pub fn increment() {
+    let _ = unsafe { TASK_COUNT.fetch_add(1, atomics::SeqCst) };
+}
+
+pub fn decrement() {
+    unsafe {
+        if TASK_COUNT.fetch_sub(1, atomics::SeqCst) == 1 {
+            let mut guard = TASK_LOCK.lock();
+            guard.signal();
+        }
+    }
+}
+
+/// Waits for all other native tasks in the system to exit. This is only used by
+/// the entry points of native programs
+pub fn wait_for_other_tasks() {
+    unsafe {
+        let mut guard = TASK_LOCK.lock();
+        while TASK_COUNT.load(atomics::SeqCst) > 0 {
+            guard.wait();
+        }
+    }
+}
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index 2f1a6989092..459bc061c56 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -128,6 +128,9 @@ pub mod args;
 // Support for running procedures when a program has exited.
 mod at_exit_imp;
 
+// Bookkeeping for task counts
+pub mod bookkeeping;
+
 // Stack overflow protection
 pub mod stack;
 
@@ -207,6 +210,7 @@ pub fn at_exit(f: proc()) {
 /// Invoking cleanup while portions of the runtime are still in use may cause
 /// undefined behavior.
 pub unsafe fn cleanup() {
+    bookkeeping::wait_for_other_tasks();
     at_exit_imp::run();
     args::cleanup();
     local_ptr::cleanup();