8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- //! Access to a single thread-local pointer
11
+ //! Access to a single thread-local pointer.
12
+ //!
13
+ //! The runtime will use this for storing ~Task.
14
+ //!
15
+ //! XXX: Add runtime checks for usage of inconsistent pointer types.
16
+ //! and for overwriting an existing pointer.
12
17
13
18
use libc:: c_void;
14
19
use cast;
20
+ use ptr;
21
+ use cell:: Cell ;
15
22
use option:: { Option , Some , None } ;
23
+ use unstable:: finally:: Finally ;
16
24
use tls = rt:: thread_local_storage;
17
25
18
26
/// Initialize the TLS key. Other ops will fail if this isn't executed first.
@@ -25,14 +33,87 @@ pub fn init_tls_key() {
25
33
}
26
34
}
27
35
28
- pub fn tls_key ( ) -> tls:: Key {
36
+ /// Give a pointer to thread-local storage.
37
+ ///
38
+ /// # Safety note
39
+ ///
40
+ /// Does not validate the pointer type.
41
+ pub unsafe fn put < T > ( sched : ~T ) {
42
+ let key = tls_key ( ) ;
43
+ let void_ptr: * mut c_void = cast:: transmute ( sched) ;
44
+ tls:: set ( key, void_ptr) ;
45
+ }
46
+
47
+ /// Take ownership of a pointer from thread-local storage.
48
+ ///
49
+ /// # Safety note
50
+ ///
51
+ /// Does not validate the pointer type.
52
+ pub unsafe fn take < T > ( ) -> ~T {
53
+ let key = tls_key ( ) ;
54
+ let void_ptr: * mut c_void = tls:: get ( key) ;
55
+ rtassert ! ( void_ptr. is_not_null( ) ) ;
56
+ let ptr: ~T = cast:: transmute ( void_ptr) ;
57
+ tls:: set ( key, ptr:: mut_null ( ) ) ;
58
+ return ptr;
59
+ }
60
+
61
+ /// Check whether there is a thread-local pointer installed.
62
+ pub fn exists ( ) -> bool {
63
+ unsafe {
64
+ match maybe_tls_key ( ) {
65
+ Some ( key) => tls:: get ( key) . is_not_null ( ) ,
66
+ None => false
67
+ }
68
+ }
69
+ }
70
+
71
+ /// Borrow the thread-local scheduler from thread-local storage.
72
+ /// While the scheduler is borrowed it is not available in TLS.
73
+ ///
74
+ /// # Safety note
75
+ ///
76
+ /// Does not validate the pointer type.
77
+ pub unsafe fn borrow < T > ( f : & fn ( & mut T ) ) {
78
+ let mut value = take ( ) ;
79
+
80
+ // XXX: Need a different abstraction from 'finally' here to avoid unsafety
81
+ let unsafe_ptr = cast:: transmute_mut_region ( & mut * value) ;
82
+ let value_cell = Cell ( value) ;
83
+
84
+ do ( || {
85
+ f ( unsafe_ptr) ;
86
+ } ) . finally {
87
+ put ( value_cell. take ( ) ) ;
88
+ }
89
+ }
90
+
91
+ /// Borrow a mutable reference to the thread-local Scheduler
92
+ ///
93
+ /// # Safety Note
94
+ ///
95
+ /// Because this leaves the Scheduler in thread-local storage it is possible
96
+ /// For the Scheduler pointer to be aliased
97
+ pub unsafe fn unsafe_borrow < T > ( ) -> * mut T {
98
+ let key = tls_key ( ) ;
99
+ let mut void_sched: * mut c_void = tls:: get ( key) ;
100
+ rtassert ! ( void_sched. is_not_null( ) ) ;
101
+ {
102
+ let sched: * mut * mut c_void = & mut void_sched;
103
+ let sched: * mut ~T = sched as * mut ~T ;
104
+ let sched: * mut T = & mut * * sched;
105
+ return sched;
106
+ }
107
+ }
108
+
109
+ fn tls_key ( ) -> tls:: Key {
29
110
match maybe_tls_key ( ) {
30
111
Some ( key) => key,
31
112
None => abort ! ( "runtime tls key not initialized" )
32
113
}
33
114
}
34
115
35
- pub fn maybe_tls_key ( ) -> Option < tls:: Key > {
116
+ fn maybe_tls_key ( ) -> Option < tls:: Key > {
36
117
unsafe {
37
118
let key: * mut c_void = rust_get_rt_tls_key ( ) ;
38
119
let key: & mut tls:: Key = cast:: transmute ( key) ;
@@ -55,9 +136,10 @@ pub fn maybe_tls_key() -> Option<tls::Key> {
55
136
return None ;
56
137
}
57
138
}
58
- }
59
139
60
- extern {
61
- #[ fast_ffi]
62
- fn rust_get_rt_tls_key ( ) -> * mut c_void ;
140
+ extern {
141
+ #[ fast_ffi]
142
+ fn rust_get_rt_tls_key ( ) -> * mut c_void ;
143
+ }
144
+
63
145
}
0 commit comments