1717
1818use libc:: c_void;
1919use cast;
20+ #[ cfg( stage0) ]
21+ #[ cfg( windows) ]
2022use ptr;
2123use cell:: Cell ;
2224use option:: { Option , Some , None } ;
2325use unstable:: finally:: Finally ;
26+ #[ cfg( stage0) ]
27+ #[ cfg( windows) ]
2428use unstable:: mutex:: { Mutex , MUTEX_INIT } ;
29+ #[ cfg( stage0) ]
30+ #[ cfg( windows) ]
2531use tls = rt:: thread_local_storage;
2632
33+ #[ cfg( not( stage0) , not( windows) , test) ]
34+ #[ thread_local]
35+ pub use realstd:: rt:: shouldnt_be_public:: RT_TLS_PTR ;
36+
37+ #[ cfg( not( stage0) , not( windows) , not( test) ) ]
38+ #[ thread_local]
39+ pub static mut RT_TLS_PTR : * mut c_void = 0 as * mut c_void ;
40+
41+ #[ cfg( stage0) ]
42+ #[ cfg( windows) ]
2743static mut RT_TLS_KEY : tls:: Key = -1 ;
2844
2945/// Initialize the TLS key. Other ops will fail if this isn't executed first.
46+ #[ inline( never) ]
47+ #[ cfg( stage0) ]
48+ #[ cfg( windows) ]
3049pub fn init_tls_key ( ) {
3150 static mut lock: Mutex = MUTEX_INIT ;
3251 static mut initialized: bool = false ;
@@ -41,24 +60,42 @@ pub fn init_tls_key() {
4160 }
4261}
4362
63+ #[ cfg( not( stage0) , not( windows) ) ]
64+ pub fn init_tls_key ( ) { }
65+
4466/// Give a pointer to thread-local storage.
4567///
4668/// # Safety note
4769///
4870/// Does not validate the pointer type.
4971#[ inline]
72+ #[ cfg( stage0) ]
73+ #[ cfg( windows) ]
5074pub unsafe fn put < T > ( sched : ~T ) {
5175 let key = tls_key ( ) ;
5276 let void_ptr: * mut c_void = cast:: transmute ( sched) ;
5377 tls:: set ( key, void_ptr) ;
5478}
5579
80+ /// Give a pointer to thread-local storage.
81+ ///
82+ /// # Safety note
83+ ///
84+ /// Does not validate the pointer type.
85+ #[ inline]
86+ #[ cfg( not( stage0) , not( windows) ) ]
87+ pub unsafe fn put < T > ( sched : ~T ) {
88+ RT_TLS_PTR = cast:: transmute ( sched)
89+ }
90+
5691/// Take ownership of a pointer from thread-local storage.
5792///
5893/// # Safety note
5994///
6095/// Does not validate the pointer type.
6196#[ inline]
97+ #[ cfg( stage0) ]
98+ #[ cfg( windows) ]
6299pub unsafe fn take < T > ( ) -> ~T {
63100 let key = tls_key ( ) ;
64101 let void_ptr: * mut c_void = tls:: get ( key) ;
@@ -70,13 +107,28 @@ pub unsafe fn take<T>() -> ~T {
70107 return ptr;
71108}
72109
110+ /// Take ownership of a pointer from thread-local storage.
111+ ///
112+ /// # Safety note
113+ ///
114+ /// Does not validate the pointer type.
115+ #[ inline]
116+ #[ cfg( not( stage0) , not( windows) ) ]
117+ pub unsafe fn take < T > ( ) -> ~T {
118+ let ptr: ~T = cast:: transmute ( RT_TLS_PTR ) ;
119+ RT_TLS_PTR = cast:: transmute ( 0 ) ; // can't use `as`, due to type not matching with `cfg(test)`
120+ ptr
121+ }
122+
73123/// Take ownership of a pointer from thread-local storage.
74124///
75125/// # Safety note
76126///
77127/// Does not validate the pointer type.
78128/// Leaves the old pointer in TLS for speed.
79129#[ inline]
130+ #[ cfg( stage0) ]
131+ #[ cfg( windows) ]
80132pub unsafe fn unsafe_take < T > ( ) -> ~T {
81133 let key = tls_key ( ) ;
82134 let void_ptr: * mut c_void = tls:: get ( key) ;
@@ -87,7 +139,21 @@ pub unsafe fn unsafe_take<T>() -> ~T {
87139 return ptr;
88140}
89141
142+ /// Take ownership of a pointer from thread-local storage.
143+ ///
144+ /// # Safety note
145+ ///
146+ /// Does not validate the pointer type.
147+ /// Leaves the old pointer in TLS for speed.
148+ #[ inline]
149+ #[ cfg( not( stage0) , not( windows) ) ]
150+ pub unsafe fn unsafe_take < T > ( ) -> ~T {
151+ cast:: transmute ( RT_TLS_PTR )
152+ }
153+
90154/// Check whether there is a thread-local pointer installed.
155+ #[ cfg( stage0) ]
156+ #[ cfg( windows) ]
91157pub fn exists ( ) -> bool {
92158 unsafe {
93159 match maybe_tls_key ( ) {
@@ -97,6 +163,14 @@ pub fn exists() -> bool {
97163 }
98164}
99165
166+ /// Check whether there is a thread-local pointer installed.
167+ #[ cfg( not( stage0) , not( windows) ) ]
168+ pub fn exists ( ) -> bool {
169+ unsafe {
170+ RT_TLS_PTR . is_not_null ( )
171+ }
172+ }
173+
100174/// Borrow the thread-local value from thread-local storage.
101175/// While the value is borrowed it is not available in TLS.
102176///
@@ -119,6 +193,8 @@ pub unsafe fn borrow<T>(f: |&mut T|) {
119193///
120194/// Because this leaves the value in thread-local storage it is possible
121195/// For the Scheduler pointer to be aliased
196+ #[ cfg( stage0) ]
197+ #[ cfg( windows) ]
122198pub unsafe fn unsafe_borrow < T > ( ) -> * mut T {
123199 let key = tls_key ( ) ;
124200 let void_ptr = tls:: get ( key) ;
@@ -128,6 +204,16 @@ pub unsafe fn unsafe_borrow<T>() -> *mut T {
128204 void_ptr as * mut T
129205}
130206
207+ #[ cfg( not( stage0) , not( windows) ) ]
208+ pub unsafe fn unsafe_borrow < T > ( ) -> * mut T {
209+ if RT_TLS_PTR . is_null ( ) {
210+ rtabort ! ( "thread-local pointer is null. bogus!" ) ;
211+ }
212+ RT_TLS_PTR as * mut T
213+ }
214+
215+ #[ cfg( stage0) ]
216+ #[ cfg( windows) ]
131217pub unsafe fn try_unsafe_borrow < T > ( ) -> Option < * mut T > {
132218 match maybe_tls_key ( ) {
133219 Some ( key) => {
@@ -142,7 +228,18 @@ pub unsafe fn try_unsafe_borrow<T>() -> Option<*mut T> {
142228 }
143229}
144230
231+ #[ cfg( not( stage0) , not( windows) ) ]
232+ pub unsafe fn try_unsafe_borrow < T > ( ) -> Option < * mut T > {
233+ if RT_TLS_PTR . is_null ( ) {
234+ None
235+ } else {
236+ Some ( RT_TLS_PTR as * mut T )
237+ }
238+ }
239+
145240#[ inline]
241+ #[ cfg( stage0) ]
242+ #[ cfg( windows) ]
146243fn tls_key ( ) -> tls:: Key {
147244 match maybe_tls_key ( ) {
148245 Some ( key) => key,
@@ -151,7 +248,8 @@ fn tls_key() -> tls::Key {
151248}
152249
153250#[ inline]
154- #[ cfg( not( test) ) ]
251+ #[ cfg( not( test) , stage0) ]
252+ #[ cfg( not( test) , windows) ]
155253pub fn maybe_tls_key ( ) -> Option < tls:: Key > {
156254 unsafe {
157255 // NB: This is a little racy because, while the key is
@@ -172,11 +270,9 @@ pub fn maybe_tls_key() -> Option<tls::Key> {
172270 }
173271}
174272
175- // XXX: The boundary between the running runtime and the testing runtime
176- // seems to be fuzzy at the moment, and trying to use two different keys
177- // results in disaster. This should not be necessary.
178273#[ inline]
179- #[ cfg( test) ]
274+ #[ cfg( test, stage0) ]
275+ #[ cfg( test, windows) ]
180276pub fn maybe_tls_key ( ) -> Option < tls:: Key > {
181277 unsafe { :: cast:: transmute ( :: realstd:: rt:: shouldnt_be_public:: maybe_tls_key ( ) ) }
182278}
0 commit comments