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 
empty_mmap() -> SendSyncPtr<[u8]>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