17
17
18
18
use libc:: c_void;
19
19
use cast;
20
+ #[ cfg( stage0) ]
21
+ #[ cfg( windows) ]
20
22
use ptr;
21
23
use cell:: Cell ;
22
24
use option:: { Option , Some , None } ;
23
25
use unstable:: finally:: Finally ;
26
+ #[ cfg( stage0) ]
27
+ #[ cfg( windows) ]
24
28
use unstable:: mutex:: { Mutex , MUTEX_INIT } ;
29
+ #[ cfg( stage0) ]
30
+ #[ cfg( windows) ]
25
31
use tls = rt:: thread_local_storage;
26
32
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) ]
27
43
static mut RT_TLS_KEY : tls:: Key = -1 ;
28
44
29
45
/// Initialize the TLS key. Other ops will fail if this isn't executed first.
46
+ #[ inline( never) ]
47
+ #[ cfg( stage0) ]
48
+ #[ cfg( windows) ]
30
49
pub fn init_tls_key ( ) {
31
50
static mut lock: Mutex = MUTEX_INIT ;
32
51
static mut initialized: bool = false ;
@@ -41,24 +60,42 @@ pub fn init_tls_key() {
41
60
}
42
61
}
43
62
63
+ #[ cfg( not( stage0) , not( windows) ) ]
64
+ pub fn init_tls_key ( ) { }
65
+
44
66
/// Give a pointer to thread-local storage.
45
67
///
46
68
/// # Safety note
47
69
///
48
70
/// Does not validate the pointer type.
49
71
#[ inline]
72
+ #[ cfg( stage0) ]
73
+ #[ cfg( windows) ]
50
74
pub unsafe fn put < T > ( sched : ~T ) {
51
75
let key = tls_key ( ) ;
52
76
let void_ptr: * mut c_void = cast:: transmute ( sched) ;
53
77
tls:: set ( key, void_ptr) ;
54
78
}
55
79
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
+
56
91
/// Take ownership of a pointer from thread-local storage.
57
92
///
58
93
/// # Safety note
59
94
///
60
95
/// Does not validate the pointer type.
61
96
#[ inline]
97
+ #[ cfg( stage0) ]
98
+ #[ cfg( windows) ]
62
99
pub unsafe fn take < T > ( ) -> ~T {
63
100
let key = tls_key ( ) ;
64
101
let void_ptr: * mut c_void = tls:: get ( key) ;
@@ -70,13 +107,28 @@ pub unsafe fn take<T>() -> ~T {
70
107
return ptr;
71
108
}
72
109
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
+
73
123
/// Take ownership of a pointer from thread-local storage.
74
124
///
75
125
/// # Safety note
76
126
///
77
127
/// Does not validate the pointer type.
78
128
/// Leaves the old pointer in TLS for speed.
79
129
#[ inline]
130
+ #[ cfg( stage0) ]
131
+ #[ cfg( windows) ]
80
132
pub unsafe fn unsafe_take < T > ( ) -> ~T {
81
133
let key = tls_key ( ) ;
82
134
let void_ptr: * mut c_void = tls:: get ( key) ;
@@ -87,7 +139,21 @@ pub unsafe fn unsafe_take<T>() -> ~T {
87
139
return ptr;
88
140
}
89
141
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
+
90
154
/// Check whether there is a thread-local pointer installed.
155
+ #[ cfg( stage0) ]
156
+ #[ cfg( windows) ]
91
157
pub fn exists ( ) -> bool {
92
158
unsafe {
93
159
match maybe_tls_key ( ) {
@@ -97,6 +163,14 @@ pub fn exists() -> bool {
97
163
}
98
164
}
99
165
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
+
100
174
/// Borrow the thread-local value from thread-local storage.
101
175
/// While the value is borrowed it is not available in TLS.
102
176
///
@@ -119,6 +193,8 @@ pub unsafe fn borrow<T>(f: |&mut T|) {
119
193
///
120
194
/// Because this leaves the value in thread-local storage it is possible
121
195
/// For the Scheduler pointer to be aliased
196
+ #[ cfg( stage0) ]
197
+ #[ cfg( windows) ]
122
198
pub unsafe fn unsafe_borrow < T > ( ) -> * mut T {
123
199
let key = tls_key ( ) ;
124
200
let void_ptr = tls:: get ( key) ;
@@ -128,6 +204,16 @@ pub unsafe fn unsafe_borrow<T>() -> *mut T {
128
204
void_ptr as * mut T
129
205
}
130
206
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) ]
131
217
pub unsafe fn try_unsafe_borrow < T > ( ) -> Option < * mut T > {
132
218
match maybe_tls_key ( ) {
133
219
Some ( key) => {
@@ -142,7 +228,18 @@ pub unsafe fn try_unsafe_borrow<T>() -> Option<*mut T> {
142
228
}
143
229
}
144
230
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
+
145
240
#[ inline]
241
+ #[ cfg( stage0) ]
242
+ #[ cfg( windows) ]
146
243
fn tls_key ( ) -> tls:: Key {
147
244
match maybe_tls_key ( ) {
148
245
Some ( key) => key,
@@ -151,7 +248,8 @@ fn tls_key() -> tls::Key {
151
248
}
152
249
153
250
#[ inline]
154
- #[ cfg( not( test) ) ]
251
+ #[ cfg( not( test) , stage0) ]
252
+ #[ cfg( not( test) , windows) ]
155
253
pub fn maybe_tls_key ( ) -> Option < tls:: Key > {
156
254
unsafe {
157
255
// NB: This is a little racy because, while the key is
@@ -172,11 +270,9 @@ pub fn maybe_tls_key() -> Option<tls::Key> {
172
270
}
173
271
}
174
272
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.
178
273
#[ inline]
179
- #[ cfg( test) ]
274
+ #[ cfg( test, stage0) ]
275
+ #[ cfg( test, windows) ]
180
276
pub fn maybe_tls_key ( ) -> Option < tls:: Key > {
181
277
unsafe { :: cast:: transmute ( :: realstd:: rt:: shouldnt_be_public:: maybe_tls_key ( ) ) }
182
278
}
0 commit comments