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
///
@@ -123,6 +197,8 @@ pub unsafe fn borrow<T>(f: |&mut T|) {
123
197
///
124
198
/// Because this leaves the value in thread-local storage it is possible
125
199
/// For the Scheduler pointer to be aliased
200
+ #[ cfg( stage0) ]
201
+ #[ cfg( windows) ]
126
202
pub unsafe fn unsafe_borrow < T > ( ) -> * mut T {
127
203
let key = tls_key ( ) ;
128
204
let void_ptr = tls:: get ( key) ;
@@ -132,6 +208,16 @@ pub unsafe fn unsafe_borrow<T>() -> *mut T {
132
208
void_ptr as * mut T
133
209
}
134
210
211
+ #[ cfg( not( stage0) , not( windows) ) ]
212
+ pub unsafe fn unsafe_borrow < T > ( ) -> * mut T {
213
+ if RT_TLS_PTR . is_null ( ) {
214
+ rtabort ! ( "thread-local pointer is null. bogus!" ) ;
215
+ }
216
+ RT_TLS_PTR as * mut T
217
+ }
218
+
219
+ #[ cfg( stage0) ]
220
+ #[ cfg( windows) ]
135
221
pub unsafe fn try_unsafe_borrow < T > ( ) -> Option < * mut T > {
136
222
match maybe_tls_key ( ) {
137
223
Some ( key) => {
@@ -146,7 +232,18 @@ pub unsafe fn try_unsafe_borrow<T>() -> Option<*mut T> {
146
232
}
147
233
}
148
234
235
+ #[ cfg( not( stage0) , not( windows) ) ]
236
+ pub unsafe fn try_unsafe_borrow < T > ( ) -> Option < * mut T > {
237
+ if RT_TLS_PTR . is_null ( ) {
238
+ None
239
+ } else {
240
+ Some ( RT_TLS_PTR as * mut T )
241
+ }
242
+ }
243
+
149
244
#[ inline]
245
+ #[ cfg( stage0) ]
246
+ #[ cfg( windows) ]
150
247
fn tls_key ( ) -> tls:: Key {
151
248
match maybe_tls_key ( ) {
152
249
Some ( key) => key,
@@ -155,7 +252,8 @@ fn tls_key() -> tls::Key {
155
252
}
156
253
157
254
#[ inline]
158
- #[ cfg( not( test) ) ]
255
+ #[ cfg( not( test) , stage0) ]
256
+ #[ cfg( not( test) , windows) ]
159
257
pub fn maybe_tls_key ( ) -> Option < tls:: Key > {
160
258
unsafe {
161
259
// NB: This is a little racy because, while the key is
@@ -176,11 +274,9 @@ pub fn maybe_tls_key() -> Option<tls::Key> {
176
274
}
177
275
}
178
276
179
- // XXX: The boundary between the running runtime and the testing runtime
180
- // seems to be fuzzy at the moment, and trying to use two different keys
181
- // results in disaster. This should not be necessary.
182
277
#[ inline]
183
- #[ cfg( test) ]
278
+ #[ cfg( test, stage0) ]
279
+ #[ cfg( test, windows) ]
184
280
pub fn maybe_tls_key ( ) -> Option < tls:: Key > {
185
281
unsafe { :: cast:: transmute ( :: realstd:: rt:: shouldnt_be_public:: maybe_tls_key ( ) ) }
186
282
}
0 commit comments