10
10
11
11
use std:: rt:: env:: max_cached_stacks;
12
12
use std:: os:: { errno, page_size, MemoryMap , MapReadable , MapWritable ,
13
- MapNonStandardFlags , MapVirtual } ;
14
- #[ cfg( not( windows) ) ]
15
- use std:: libc:: { MAP_STACK , MAP_PRIVATE , MAP_ANON } ;
16
- use std:: libc:: { c_uint, c_int, c_void, uintptr_t} ;
13
+ MapNonStandardFlags , MapVirtual } ;
14
+ use std:: libc;
17
15
18
16
/// A task's stack. The name "Stack" is a vestige of segmented stacks.
19
17
pub struct Stack {
20
18
priv buf: MemoryMap ,
21
19
priv min_size : uint ,
22
- priv valgrind_id : c_uint ,
20
+ priv valgrind_id : libc :: c_uint ,
23
21
}
24
22
25
23
// Try to use MAP_STACK on platforms that support it (it's what we're doing
26
24
// anyway), but some platforms don't support it at all. For example, it appears
27
25
// that there's a bug in freebsd that MAP_STACK implies MAP_FIXED (so it always
28
26
// fails): http://lists.freebsd.org/pipermail/freebsd-bugs/2011-July/044840.html
29
27
#[ cfg( not( windows) , not( target_os = "freebsd" ) ) ]
30
- static STACK_FLAGS : c_int = MAP_STACK | MAP_PRIVATE | MAP_ANON ;
28
+ static STACK_FLAGS : libc:: c_int = libc:: MAP_STACK | libc:: MAP_PRIVATE |
29
+ libc:: MAP_ANON ;
31
30
#[ cfg( target_os = "freebsd" ) ]
32
- static STACK_FLAGS : c_int = MAP_PRIVATE | MAP_ANON ;
31
+ static STACK_FLAGS : libc :: c_int = libc :: MAP_PRIVATE | libc :: MAP_ANON ;
33
32
#[ cfg( windows) ]
34
- static STACK_FLAGS : c_int = 0 ;
33
+ static STACK_FLAGS : libc :: c_int = 0 ;
35
34
36
35
impl Stack {
37
36
/// Allocate a new stack of `size`. If size = 0, this will fail. Use
38
37
/// `dummy_stack` if you want a zero-sized stack.
39
38
pub fn new ( size : uint ) -> Stack {
40
- // Map in a stack. Eventually we might be able to handle stack allocation failure, which
41
- // would fail to spawn the task. But there's not many sensible things to do on OOM.
42
- // Failure seems fine (and is what the old stack allocation did).
39
+ // Map in a stack. Eventually we might be able to handle stack
40
+ // allocation failure, which would fail to spawn the task. But there's
41
+ // not many sensible things to do on OOM. Failure seems fine (and is
42
+ // what the old stack allocation did).
43
43
let stack = match MemoryMap :: new ( size, [ MapReadable , MapWritable ,
44
44
MapNonStandardFlags ( STACK_FLAGS ) ] ) {
45
45
Ok ( map) => map,
46
- Err ( e) => fail ! ( "Creating memory map for stack of size {} failed: {}" , size, e)
46
+ Err ( e) => fail ! ( "mmap for stack of size {} failed: {}" , size, e)
47
47
} ;
48
48
49
- // Change the last page to be inaccessible. This is to provide safety; when an FFI
50
- // function overflows it will (hopefully) hit this guard page. It isn't guaranteed, but
51
- // that's why FFI is unsafe. buf.data is guaranteed to be aligned properly.
49
+ // Change the last page to be inaccessible. This is to provide safety;
50
+ // when an FFI function overflows it will (hopefully) hit this guard
51
+ // page. It isn't guaranteed, but that's why FFI is unsafe. buf.data is
52
+ // guaranteed to be aligned properly.
52
53
if !protect_last_page ( & stack) {
53
54
fail ! ( "Could not memory-protect guard page. stack={:?}, errno={}" ,
54
55
stack, errno( ) ) ;
@@ -61,7 +62,9 @@ impl Stack {
61
62
} ;
62
63
63
64
// XXX: Using the FFI to call a C macro. Slow
64
- stk. valgrind_id = unsafe { rust_valgrind_stack_register ( stk. start ( ) , stk. end ( ) ) } ;
65
+ stk. valgrind_id = unsafe {
66
+ rust_valgrind_stack_register ( stk. start ( ) , stk. end ( ) )
67
+ } ;
65
68
return stk;
66
69
}
67
70
@@ -87,30 +90,27 @@ impl Stack {
87
90
}
88
91
}
89
92
90
- // These use ToPrimitive so that we never need to worry about the sizes of whatever types these
91
- // (which we would with scalar casts). It's either a wrapper for a scalar cast or failure: fast, or
92
- // will fail during compilation.
93
93
#[ cfg( unix) ]
94
94
fn protect_last_page ( stack : & MemoryMap ) -> bool {
95
- use std:: libc:: { mprotect, PROT_NONE , size_t} ;
96
95
unsafe {
97
- // This may seem backwards: the start of the segment is the last page? Yes! The stack grows
98
- // from higher addresses (the end of the allocated block) to lower addresses (the start of
99
- // the allocated block).
100
- let last_page = stack. data as * c_void ;
101
- mprotect ( last_page, page_size ( ) as size_t , PROT_NONE ) != -1
96
+ // This may seem backwards: the start of the segment is the last page?
97
+ // Yes! The stack grows from higher addresses (the end of the allocated
98
+ // block) to lower addresses (the start of the allocated block).
99
+ let last_page = stack. data as * libc:: c_void ;
100
+ libc:: mprotect ( last_page, page_size ( ) as libc:: size_t ,
101
+ libc:: PROT_NONE ) != -1
102
102
}
103
103
}
104
104
105
105
#[ cfg( windows) ]
106
106
fn protect_last_page ( stack : & MemoryMap ) -> bool {
107
- use std:: libc:: { VirtualProtect , PAGE_NOACCESS , SIZE_T , LPDWORD , DWORD } ;
108
107
unsafe {
109
108
// see above
110
- let last_page = stack. data as * mut c_void ;
111
- let mut old_prot: DWORD = 0 ;
112
- VirtualProtect ( last_page, page_size ( ) as SIZE_T , PAGE_NOACCESS ,
113
- & mut old_prot as LPDWORD ) != 0
109
+ let last_page = stack. data as * mut libc:: c_void ;
110
+ let mut old_prot: libc:: DWORD = 0 ;
111
+ libc:: VirtualProtect ( last_page, page_size ( ) as libc:: SIZE_T ,
112
+ libc:: PAGE_NOACCESS ,
113
+ & mut old_prot as libc:: LPDWORD ) != 0
114
114
}
115
115
}
116
116
@@ -124,7 +124,8 @@ impl Drop for Stack {
124
124
}
125
125
126
126
pub struct StackPool {
127
- // Ideally this would be some datastructure that preserved ordering on Stack.min_size.
127
+ // Ideally this would be some datastructure that preserved ordering on
128
+ // Stack.min_size.
128
129
priv stacks : ~[ Stack ] ,
129
130
}
130
131
@@ -151,6 +152,7 @@ impl StackPool {
151
152
}
152
153
153
154
extern {
154
- fn rust_valgrind_stack_register ( start : * uintptr_t , end : * uintptr_t ) -> c_uint ;
155
- fn rust_valgrind_stack_deregister ( id : c_uint ) ;
155
+ fn rust_valgrind_stack_register ( start : * libc:: uintptr_t ,
156
+ end : * libc:: uintptr_t ) -> libc:: c_uint ;
157
+ fn rust_valgrind_stack_deregister ( id : libc:: c_uint ) ;
156
158
}
0 commit comments