about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2013-03-15 18:35:33 -0700
committerBrian Anderson <banderson@mozilla.com>2013-03-18 17:00:35 -0700
commit5af5766512b0e90a3a076a09b35286aca332e48e (patch)
treed4fbefe51efa5acb6b27f1060e672706758da3e2
parent044703435ba7e1338456f7a83393eb2c6fecf238 (diff)
downloadrust-5af5766512b0e90a3a076a09b35286aca332e48e.tar.gz
rust-5af5766512b0e90a3a076a09b35286aca332e48e.zip
core: Initialize global state lazily in the Scheduler ctor
I don't want any global one-time initalization functions because
that will make embedding harder.
-rw-r--r--src/libcore/rt/mod.rs10
-rw-r--r--src/libcore/rt/sched.rs7
-rw-r--r--src/rt/rust_builtin.cpp17
3 files changed, 20 insertions, 14 deletions
diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs
index f900747c996..04891a1673c 100644
--- a/src/libcore/rt/mod.rs
+++ b/src/libcore/rt/mod.rs
@@ -46,20 +46,10 @@ mod context;
 mod thread;
 pub mod env;
 
-pub fn initialize() {
-    unsafe { rust_initialize_global_state(); }
-    extern {
-        fn rust_initialize_global_state();
-    }
-}
-
 pub fn start(main: *u8, _argc: int, _argv: *c_char, _crate_map: *u8) -> int {
     use self::sched::{Scheduler, Task};
     use self::uvio::UvEventLoop;
 
-    // XXX: Would rather do this lazily in Scheduler
-    initialize();
-
     let loop_ = ~UvEventLoop::new();
     let mut sched = ~Scheduler::new(loop_);
     let main_task = ~do Task::new(&mut sched.stack_pool) {
diff --git a/src/libcore/rt/sched.rs b/src/libcore/rt/sched.rs
index f47f86fd5fd..312c6655f55 100644
--- a/src/libcore/rt/sched.rs
+++ b/src/libcore/rt/sched.rs
@@ -71,6 +71,13 @@ enum CleanupJob {
 pub impl Scheduler {
 
     static fn new(event_loop: ~EventLoopObject) -> Scheduler {
+
+        // Lazily initialize the global state, currently the scheduler TLS key
+        unsafe { rust_initialize_global_state(); }
+        extern {
+            fn rust_initialize_global_state();
+        }
+
         Scheduler {
             event_loop: event_loop,
             task_queue: WorkQueue::new(),
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index 9349db17d56..f586e05772b 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -889,7 +889,6 @@ rust_call_nullary_fn(nullary_fn f) {
     f();
 }
 
-
 #ifndef _WIN32
 pthread_key_t sched_key;
 #else
@@ -901,16 +900,26 @@ rust_get_sched_tls_key() {
     return &sched_key;
 }
 
+// Initialize the global state required by the new scheduler
 extern "C" CDECL void
 rust_initialize_global_state() {
 
+    static lock_and_signal init_lock;
+    static bool initialized = false;
+
+    scoped_lock with(init_lock);
+
+    if (!initialized) {
+
 #ifndef _WIN32
-    assert(!pthread_key_create(&sched_key, NULL));
+        assert(!pthread_key_create(&sched_key, NULL));
 #else
-    sched_key = TlsAlloc();
-    assert(sched_key != TLS_OUT_OF_INDEXES);
+        sched_key = TlsAlloc();
+        assert(sched_key != TLS_OUT_OF_INDEXES);
 #endif
 
+        initialized = true;
+    }
 }
 
 //