1 //! OS-related abstractions required by Wasmtime. 2 //! 3 //! This module is intended to house all logic that's specific to either Unix 4 //! or Windows, for example. The goal of this module is to be the "single 5 //! module" to edit if Wasmtime is ported to a new platform. Ideally all that's 6 //! needed is an extra block below and a new platform should be good to go after 7 //! filling out the implementation. 8 9 #![allow( 10 clippy::cast_sign_loss, 11 reason = "platforms too fiddly to worry about this" 12 )] 13 14 use crate::runtime::vm::SendSyncPtr; 15 use core::ptr::{self, NonNull}; 16 17 /// What happens to a mapping after it is decommitted? 18 #[derive(Clone, Copy, PartialEq, Eq, Debug)] 19 pub enum DecommitBehavior { 20 /// The mapping is zeroed. 21 Zero, 22 /// The original mapping is restored. If it was zero, then it is zero again; 23 /// if it was a CoW mapping, then the original CoW mapping is restored; 24 /// etc... 25 RestoreOriginalMapping, 26 } 27 28 fn empty_mmap() -> SendSyncPtr<[u8]> { 29 // Callers of this API assume that `.as_ptr()` below returns something 30 // page-aligned and non-null. This is because the pointer returned from 31 // that location is casted to other types which reside at a higher 32 // alignment than a byte for example. Despite the length being zero we 33 // still need to ensure that the pointer is suitably aligned. 34 // 35 // To handle that do a bit of trickery here to get the compiler to 36 // generate an empty array to a high-alignment type (here 4k which is 37 // the min page size we work with today). Then use this empty array as 38 // the source pointer for an empty byte slice. It's a bit wonky but this 39 // makes it such that the returned length is always zero (so this is 40 // safe) but the pointer is always 4096 or suitably aligned. 41 #[repr(C, align(4096))] 42 struct PageAligned; 43 let empty_page_alloc: &mut [PageAligned] = &mut []; 44 let empty = NonNull::new(ptr::slice_from_raw_parts_mut( 45 empty_page_alloc.as_mut_ptr().cast(), 46 0, 47 )) 48 .unwrap(); 49 SendSyncPtr::from(empty) 50 } 51 52 cfg_if::cfg_if! { 53 if #[cfg(miri)] { 54 mod miri; 55 pub use miri::*; 56 } else if #[cfg(not(feature = "std"))] { 57 mod custom; 58 pub use custom::*; 59 } else if #[cfg(windows)] { 60 mod windows; 61 pub use windows::*; 62 } else if #[cfg(unix)] { 63 mod unix; 64 pub use unix::*; 65 } else { 66 mod custom; 67 pub use custom::*; 68 } 69 } 70