Multiple changes required to implement the wasmer terminal on the browser

- Split functionality out of WasiEnv so that it can support multi-threading
- Added methods to the VFS File Trait that supporting polling
- Implemented basic time functionality for WASI
- Incorported a yield callback for when WASI processes idle
- Improved the error handling on WASI IO calls
- Reduce the verbose logging on some critical WASI calls (write/read)
- Implemented the missing poll functionality for WASI processes
- Moved the syspoll functionality behind a feature flag to default to WASI method
- Refactored the thread sleeping functionality for WASI processes
- Fixed the files system benchmark which was not compiling
- Modified the file system trait so that it is SYNC and thus can handle multiple threads
- Removed the large mutex around filesystem state and implemented granular locks instead
  (this is needed to fix a deadlock scenario on the terminal)
- Split the inodes object apart from the state to fix the deadlock scenario.
- Few minor fixes to some warnings when not using certain features
- Sleeping will now call a callback that can be used by the runtime operator when
  a WASI thread goes to sleep (for instance to do other work)
- Fixed a bug where paths that exist on the real file system are leaking into VFS
- Timing functions now properly return a time precision on WASI
- Some improved macros for error handling within syscalls (wasi_try_ok!)
- Refactored the remove_directory WASI function which was not working properly
- Refactored the unlink WASI function which was not working properly
- Refactored the poll WASI function which was not working properly
- Updates some of the tests to make them compile again
- Rewrote the OutputCapturer so that it does leak into the internals
This commit is contained in:
Johnathan Sharratt
2021-10-28 12:09:00 +01:00
committed by ptitSeb
parent 9af113ca86
commit 7c532813e7
30 changed files with 2160 additions and 1305 deletions

View File

@@ -237,10 +237,8 @@ impl Memory {
Ok(Pages(new_pages))
}
/// Used by tests
#[doc(hidden)]
pub fn uint8view(&self) -> js_sys::Uint8Array {
self.view.clone()
pub(crate) fn uint8view(&self) -> js_sys::Uint8Array {
js_sys::Uint8Array::new(&self.vm_memory.memory.buffer())
}
pub(crate) fn from_vm_export(store: &Store, vm_memory: VMMemory) -> Self {
@@ -276,16 +274,17 @@ impl Memory {
/// This method is guaranteed to be safe (from the host side) in the face of
/// concurrent writes.
pub fn read(&self, offset: u64, buf: &mut [u8]) -> Result<(), MemoryAccessError> {
let view = self.uint8view();
let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?;
let len: u32 = buf
.len()
.try_into()
.map_err(|_| MemoryAccessError::Overflow)?;
let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?;
if end > self.view.length() {
if end > view.length() {
Err(MemoryAccessError::HeapOutOfBounds)?;
}
self.view.subarray(offset, end).copy_to(buf);
view.subarray(offset, end).copy_to(buf);
Ok(())
}
@@ -304,13 +303,14 @@ impl Memory {
offset: u64,
buf: &'a mut [MaybeUninit<u8>],
) -> Result<&'a mut [u8], MemoryAccessError> {
let view = self.uint8view();
let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?;
let len: u32 = buf
.len()
.try_into()
.map_err(|_| MemoryAccessError::Overflow)?;
let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?;
if end > self.view.length() {
if end > view.length() {
Err(MemoryAccessError::HeapOutOfBounds)?;
}
@@ -321,7 +321,7 @@ impl Memory {
}
let buf = unsafe { slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut u8, buf.len()) };
self.view.subarray(offset, end).copy_to(buf);
view.subarray(offset, end).copy_to(buf);
Ok(buf)
}
@@ -333,16 +333,18 @@ impl Memory {
/// This method is guaranteed to be safe (from the host side) in the face of
/// concurrent reads/writes.
pub fn write(&self, offset: u64, data: &[u8]) -> Result<(), MemoryAccessError> {
let view = self.uint8view();
let offset: u32 = offset.try_into().map_err(|_| MemoryAccessError::Overflow)?;
let len: u32 = data
.len()
.try_into()
.map_err(|_| MemoryAccessError::Overflow)?;
let view = self.uint8view();
let end = offset.checked_add(len).ok_or(MemoryAccessError::Overflow)?;
if end > self.view.length() {
if end > view.length() {
Err(MemoryAccessError::HeapOutOfBounds)?;
}
self.view.subarray(offset, end).copy_from(data);
view.subarray(offset, end).copy_from(data);
Ok(())
}
}

View File

@@ -28,6 +28,7 @@ pub struct TypedFunction<Args = (), Rets = ()> {
}
unsafe impl<Args, Rets> Send for TypedFunction<Args, Rets> {}
unsafe impl<Args, Rets> Sync for TypedFunction<Args, Rets> {}
impl<Args, Rets> TypedFunction<Args, Rets>
where