@@ -34,11 +34,11 @@ use std::cell::Cell;
3434use std:: io;
3535use std:: ptr;
3636
37- pub struct Fiber {
38- // Description of the mmap region we own. This should be abstracted
39- // eventually so we aren't personally mmap-ing this region.
40- mmap : * mut libc :: c_void ,
41- mmap_len : usize ,
37+ pub struct RawFiber {
38+ // The top of the stack; for stacks allocated by the fiber implementation itself,
39+ // the base address of the allocation will be `top.sub(alloc_len.unwrap())`
40+ top_of_stack : * mut u8 ,
41+ alloc_len : Option < usize > ,
4242}
4343
4444pub struct Suspend {
@@ -65,28 +65,37 @@ where
6565 }
6666}
6767
68- impl Fiber {
69- pub fn new < F , A , B , C > ( stack_size : usize , func : F ) -> io:: Result < Fiber >
68+ impl RawFiber {
69+ pub fn new ( stack_size : usize ) -> io:: Result < Self > {
70+ Self :: alloc_with_stack ( stack_size)
71+ }
72+
73+ pub fn from_stack ( top : * mut u8 ) -> Self {
74+ Self {
75+ top_of_stack : top,
76+ alloc_len : None ,
77+ }
78+ }
79+
80+ pub ( crate ) fn init < F , A , B , C > ( & self , func : F )
7081 where
7182 F : FnOnce ( A , & super :: Suspend < A , B , C > ) -> C ,
7283 {
73- let fiber = Fiber :: alloc_with_stack ( stack_size) ?;
7484 unsafe {
75- // Initialize the top of the stack to be resumed from
76- let top_of_stack = fiber. top_of_stack ( ) ;
7785 let data = Box :: into_raw ( Box :: new ( func) ) . cast ( ) ;
78- wasmtime_fiber_init ( top_of_stack, fiber_start :: < F , A , B , C > , data) ;
79- Ok ( fiber)
86+ wasmtime_fiber_init ( self . top_of_stack , fiber_start :: < F , A , B , C > , data) ;
8087 }
8188 }
8289
83- fn alloc_with_stack ( stack_size : usize ) -> io:: Result < Fiber > {
90+ fn alloc_with_stack ( stack_size : usize ) -> io:: Result < Self > {
8491 unsafe {
8592 // Round up our stack size request to the nearest multiple of the
8693 // page size.
8794 let page_size = libc:: sysconf ( libc:: _SC_PAGESIZE) as usize ;
8895 let stack_size = if stack_size == 0 {
89- page_size
96+ // Default to an 8 MB stack size (common default for 64-bit Linux and macOS)
97+ // TODO: respect stack rlimit
98+ 8 * 1024 * 1024
9099 } else {
91100 ( stack_size + ( page_size - 1 ) ) & ( !( page_size - 1 ) )
92101 } ;
@@ -104,7 +113,10 @@ impl Fiber {
104113 if mmap == libc:: MAP_FAILED {
105114 return Err ( io:: Error :: last_os_error ( ) ) ;
106115 }
107- let ret = Fiber { mmap, mmap_len } ;
116+ let ret = Self {
117+ top_of_stack : mmap. cast :: < u8 > ( ) . add ( mmap_len) ,
118+ alloc_len : Some ( mmap_len) ,
119+ } ;
108120 let res = libc:: mprotect (
109121 mmap. cast :: < u8 > ( ) . add ( page_size) . cast ( ) ,
110122 stack_size,
@@ -124,27 +136,24 @@ impl Fiber {
124136 // stack, otherwise known as our reserved slot for this information.
125137 //
126138 // In the diagram above this is updating address 0xAff8
127- let top_of_stack = self . top_of_stack ( ) ;
128- let addr = top_of_stack. cast :: < usize > ( ) . offset ( -1 ) ;
139+ let addr = self . top_of_stack . cast :: < usize > ( ) . offset ( -1 ) ;
129140 addr. write ( result as * const _ as usize ) ;
130141
131- wasmtime_fiber_switch ( top_of_stack) ;
142+ wasmtime_fiber_switch ( self . top_of_stack ) ;
132143
133144 // null this out to help catch use-after-free
134145 addr. write ( 0 ) ;
135146 }
136147 }
137-
138- unsafe fn top_of_stack ( & self ) -> * mut u8 {
139- self . mmap . cast :: < u8 > ( ) . add ( self . mmap_len )
140- }
141148}
142149
143- impl Drop for Fiber {
150+ impl Drop for RawFiber {
144151 fn drop ( & mut self ) {
145152 unsafe {
146- let ret = libc:: munmap ( self . mmap , self . mmap_len ) ;
147- debug_assert ! ( ret == 0 ) ;
153+ if let Some ( alloc_len) = self . alloc_len {
154+ let ret = libc:: munmap ( self . top_of_stack . sub ( alloc_len) as _ , alloc_len) ;
155+ debug_assert ! ( ret == 0 ) ;
156+ }
148157 }
149158 }
150159}
0 commit comments