-
Notifications
You must be signed in to change notification settings - Fork 824
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for shared memory in Wasm. #702
Changes from all commits
cca419c
86346d6
7f3837a
f2077c2
aecce46
c837832
0eba153
d66b805
172ef77
0ba73ac
dcf7016
1568084
70d561a
2882c75
08ee2c0
e6ec261
8705fe1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,12 +12,15 @@ use std::{ | |
cell::{Cell, RefCell}, | ||
fmt, mem, | ||
rc::Rc, | ||
sync::Arc, | ||
}; | ||
|
||
pub use self::dynamic::DynamicMemory; | ||
pub use self::static_::{SharedStaticMemory, StaticMemory}; | ||
pub use self::static_::StaticMemory; | ||
pub use self::view::{Atomically, MemoryView}; | ||
|
||
use parking_lot::Mutex; | ||
|
||
mod dynamic; | ||
pub mod ptr; | ||
mod static_; | ||
|
@@ -151,20 +154,10 @@ impl Memory { | |
unsafe { MemoryView::new(base as _, length as u32) } | ||
} | ||
|
||
/// Convert this memory to a shared memory if the shared flag | ||
/// is present in the description used to create it. | ||
pub fn shared(self) -> Option<SharedMemory> { | ||
if self.desc.shared { | ||
Some(SharedMemory { desc: self.desc }) | ||
} else { | ||
None | ||
} | ||
} | ||
|
||
pub(crate) fn vm_local_memory(&self) -> *mut vm::LocalMemory { | ||
match &self.variant { | ||
MemoryVariant::Unshared(unshared_mem) => unshared_mem.vm_local_memory(), | ||
MemoryVariant::Shared(_) => unimplemented!(), | ||
MemoryVariant::Shared(shared_mem) => shared_mem.vm_local_memory(), | ||
} | ||
} | ||
} | ||
|
@@ -241,7 +234,7 @@ impl UnsharedMemory { | |
MemoryType::SharedStatic => panic!("attempting to create shared unshared memory"), | ||
}; | ||
|
||
Ok(UnsharedMemory { | ||
Ok(Self { | ||
internal: Rc::new(UnsharedMemoryInternal { | ||
storage: RefCell::new(storage), | ||
local: Cell::new(local), | ||
|
@@ -289,27 +282,56 @@ impl Clone for UnsharedMemory { | |
} | ||
|
||
pub struct SharedMemory { | ||
#[allow(dead_code)] | ||
desc: MemoryDescriptor, | ||
internal: Arc<SharedMemoryInternal>, | ||
} | ||
|
||
pub struct SharedMemoryInternal { | ||
memory: RefCell<Box<StaticMemory>>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe dumb question: shared memory is always static? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As we've implemented it, yes, but I can't see any reason we couldn't add SharedDynamic if we wanted to. The challenge would be ensuring that the base pointer of the dynamic memory doesn't move while we're forming and using a pointer into that memory. A naive implementation could hold a mutex lock for every memory access in the wasm program. An efficient implementation might implement base changes by temporarily mapping the same pages at two addresses in memory so that old pointers continue to work during the move. Then, remove the old mapping such that the pointers fault. You can't use that memory again until you can prove all old pointers are gone (otherwise you break Wasm security model). For the wasm program's loads and stores, either it would need to reload the base pointer if the access faults (if we unmap the memory early), or you keep the temporary mapping around until no such pointers exist but that means the |
||
local: Cell<vm::LocalMemory>, | ||
lock: Mutex<()>, | ||
} | ||
|
||
impl SharedMemory { | ||
fn new(desc: MemoryDescriptor) -> Result<Self, CreationError> { | ||
Ok(Self { desc }) | ||
let mut local = vm::LocalMemory { | ||
base: std::ptr::null_mut(), | ||
bound: 0, | ||
memory: std::ptr::null_mut(), | ||
}; | ||
|
||
let memory = StaticMemory::new(desc, &mut local)?; | ||
|
||
Ok(Self { | ||
internal: Arc::new(SharedMemoryInternal { | ||
memory: RefCell::new(memory), | ||
local: Cell::new(local), | ||
lock: Mutex::new(()), | ||
}), | ||
}) | ||
} | ||
|
||
pub fn grow(&self, _delta: Pages) -> Result<Pages, GrowError> { | ||
unimplemented!() | ||
pub fn grow(&self, delta: Pages) -> Result<Pages, GrowError> { | ||
let _guard = self.internal.lock.lock(); | ||
let mut local = self.internal.local.get(); | ||
let pages = self.internal.memory.borrow_mut().grow(delta, &mut local); | ||
pages | ||
} | ||
|
||
pub fn size(&self) -> Pages { | ||
unimplemented!() | ||
let _guard = self.internal.lock.lock(); | ||
self.internal.memory.borrow_mut().size() | ||
} | ||
|
||
pub(crate) fn vm_local_memory(&self) -> *mut vm::LocalMemory { | ||
self.internal.local.as_ptr() | ||
} | ||
} | ||
|
||
impl Clone for SharedMemory { | ||
fn clone(&self) -> Self { | ||
unimplemented!() | ||
SharedMemory { | ||
internal: Arc::clone(&self.internal), | ||
} | ||
} | ||
} | ||
|
||
|
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need an internal structure? can we move all the fields from
SharedMemoryInternal
into theSharedMemory
itself?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue is the implementation of Clone for SharedMemory. Mind you, I'm suspicious of the fact that we clone memories to begin with, but I took a look and decided that was a problem for another day. The important part is that the underlying size/grow methods share one lock, which is held by
SharedMemoryInternal
while theSharedMemory
can be cloned to your heart's content.