Use rsix to make system calls in Wasmtime. (#3355)

* Use rsix to make system calls in Wasmtime.

`rsix` is a system call wrapper crate that we use in `wasi-common`,
which can provide the following advantages in the rest of Wasmtime:

 - It eliminates some `unsafe` blocks in Wasmtime's code. There's
   still an `unsafe` block in the library, but this way, the `unsafe`
   is factored out and clearly scoped.

 - And, it makes error handling more consistent, factoring out code for
   checking return values and `io::Error::last_os_error()`, and code that
   does `errno::set_errno(0)`.

This doesn't cover *all* system calls; `rsix` doesn't implement
signal-handling APIs, and this doesn't cover calls made through `std` or
crates like `userfaultfd`, `rand`, and `region`.
This commit is contained in:
Dan Gohman
2021-09-17 15:28:56 -07:00
committed by GitHub
parent 6a98fe2104
commit 47490b4383
25 changed files with 174 additions and 234 deletions

View File

@@ -3,13 +3,9 @@ mod not_for_windows {
use wasmtime::*;
use wasmtime_environ::{WASM32_MAX_PAGES, WASM_PAGE_SIZE};
use libc::MAP_FAILED;
use libc::{mmap, mprotect, munmap};
use libc::{sysconf, _SC_PAGESIZE};
use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE};
use rsix::io::{mmap_anonymous, mprotect, munmap, MapFlags, MprotectFlags, ProtFlags};
use std::convert::TryFrom;
use std::io::Error;
use std::ptr::null_mut;
use std::sync::{Arc, Mutex};
@@ -23,16 +19,16 @@ mod not_for_windows {
impl CustomMemory {
unsafe fn new(minimum: usize, maximum: usize, glob_counter: Arc<Mutex<usize>>) -> Self {
let page_size = sysconf(_SC_PAGESIZE) as usize;
let page_size = rsix::process::page_size();
let guard_size = page_size;
let size = maximum + guard_size;
assert_eq!(size % page_size, 0); // we rely on WASM_PAGE_SIZE being multiple of host page size
let mem = mmap(null_mut(), size, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
assert_ne!(mem, MAP_FAILED, "mmap failed: {}", Error::last_os_error());
let mem = mmap_anonymous(null_mut(), size, ProtFlags::NONE, MapFlags::PRIVATE)
.expect("mmap failed");
let r = mprotect(mem, minimum, PROT_READ | PROT_WRITE);
assert_eq!(r, 0, "mprotect failed: {}", Error::last_os_error());
mprotect(mem, minimum, MprotectFlags::READ | MprotectFlags::WRITE)
.expect("mprotect failed");
*glob_counter.lock().unwrap() += minimum;
Self {
@@ -48,8 +44,7 @@ mod not_for_windows {
impl Drop for CustomMemory {
fn drop(&mut self) {
*self.glob_bytes_counter.lock().unwrap() -= self.used_wasm_bytes;
let r = unsafe { munmap(self.mem as *mut _, self.size) };
assert_eq!(r, 0, "munmap failed: {}", Error::last_os_error());
unsafe { munmap(self.mem as *mut _, self.size).expect("munmap failed") };
}
}
@@ -67,8 +62,8 @@ mod not_for_windows {
let delta = new_size - self.used_wasm_bytes;
unsafe {
let start = (self.mem as *mut u8).add(self.used_wasm_bytes) as _;
let r = mprotect(start, delta, PROT_READ | PROT_WRITE);
assert_eq!(r, 0, "mprotect failed: {}", Error::last_os_error());
mprotect(start, delta, MprotectFlags::READ | MprotectFlags::WRITE)
.expect("mprotect failed");
}
*self.glob_bytes_counter.lock().unwrap() += delta;