diff --git a/examples/http-server/src/main.rs b/examples/http-server/src/main.rs index 22727cd6e..5d1125e93 100644 --- a/examples/http-server/src/main.rs +++ b/examples/http-server/src/main.rs @@ -1,6 +1,6 @@ #![feature(wasi_ext)] -use kwasm_net::{Epoll, Tcp4Listener, TcpStream, schedule}; +use kwasm_net::{schedule, Epoll, Tcp4Listener, TcpStream}; use std::sync::Arc; fn serve(stream: Arc, mut all: Vec) { @@ -55,16 +55,14 @@ fn main() { let epoll = Arc::new(Epoll::new()); let listener = Arc::new(Tcp4Listener::new("0.0.0.0", 2011, 128).unwrap()); - listener.accept_async(epoll.clone(), |stream| { - match stream { - Ok(stream) => { - serve(stream, vec![]); - Ok(()) - }, - Err(code) => { - println!("failed to accept; code = {}", code); - Err(()) - } + listener.accept_async(epoll.clone(), |stream| match stream { + Ok(stream) => { + serve(stream, vec![]); + Ok(()) + } + Err(code) => { + println!("failed to accept; code = {}", code); + Err(()) } }); println!("start epoll"); diff --git a/examples/wasi-networking/src/main.rs b/examples/wasi-networking/src/main.rs index d73f7961e..65504bde8 100644 --- a/examples/wasi-networking/src/main.rs +++ b/examples/wasi-networking/src/main.rs @@ -1,33 +1,29 @@ #![feature(wasi_ext)] -use kwasm_net::{Epoll, Tcp4Listener, TcpStream, schedule}; +use kwasm_net::{schedule, Epoll, Tcp4Listener, TcpStream}; use std::sync::Arc; fn do_echo(stream: Arc, buf: Vec) { let stream2 = stream.clone(); - stream.read_async(buf, move |result| { - match result { - Ok(buf) => { - if buf.len() == 0 { - return; - } - let stream = stream2.clone(); - stream2.write_all_async(buf, move |result| { - match result { - Ok(buf) => { - schedule(|| { - do_echo(stream, buf); - }); - }, - Err(code) => { - println!("failed to write; code = {}", code); - } - } - }); - }, - Err(code) => { - println!("failed to read; code = {}", code); + stream.read_async(buf, move |result| match result { + Ok(buf) => { + if buf.len() == 0 { + return; } + let stream = stream2.clone(); + stream2.write_all_async(buf, move |result| match result { + Ok(buf) => { + schedule(|| { + do_echo(stream, buf); + }); + } + Err(code) => { + println!("failed to write; code = {}", code); + } + }); + } + Err(code) => { + println!("failed to read; code = {}", code); } }); } @@ -36,16 +32,14 @@ fn main() { let epoll = Arc::new(Epoll::new()); let listener = Arc::new(Tcp4Listener::new("0.0.0.0", 2001, 128).unwrap()); - listener.accept_async(epoll.clone(), |stream| { - match stream { - Ok(stream) => { - do_echo(stream, Vec::with_capacity(16384)); - Ok(()) - }, - Err(code) => { - println!("failed to accept; code = {}", code); - Err(()) - } + listener.accept_async(epoll.clone(), |stream| match stream { + Ok(stream) => { + do_echo(stream, Vec::with_capacity(16384)); + Ok(()) + } + Err(code) => { + println!("failed to accept; code = {}", code); + Err(()) } }); println!("start epoll"); diff --git a/lib/kwasm-loader/src/lib.rs b/lib/kwasm-loader/src/lib.rs index 5d5489805..d9b51f2e3 100644 --- a/lib/kwasm-loader/src/lib.rs +++ b/lib/kwasm-loader/src/lib.rs @@ -1,14 +1,17 @@ pub mod service; +use service::{ImportInfo, LoadProfile, RunProfile, ServiceContext, TableEntryRequest}; use wasmer_runtime_core::{ - loader::{self, Loader, Instance}, backend::RunnableModule, - vm::{Ctx, LocalGlobal, SigId, Anyfunc}, + loader::{self, Instance, Loader}, module::ModuleInfo, - types::{Value, LocalMemoryIndex, LocalTableIndex, ImportedMemoryIndex, ImportedTableIndex, FuncIndex}, structures::TypedIndex, + types::{ + FuncIndex, ImportedMemoryIndex, ImportedTableIndex, LocalMemoryIndex, LocalTableIndex, + Value, + }, + vm::{Anyfunc, Ctx, LocalGlobal, SigId}, }; -use service::{ServiceContext, LoadProfile, RunProfile, TableEntryRequest, ImportInfo}; pub struct KernelLoader; @@ -16,7 +19,12 @@ impl Loader for KernelLoader { type Instance = KernelInstance; type Error = String; - fn load(&self, rm: &dyn RunnableModule, module: &ModuleInfo, full_ctx: &Ctx) -> Result { + fn load( + &self, + rm: &dyn RunnableModule, + module: &ModuleInfo, + full_ctx: &Ctx, + ) -> Result { let ctx = &full_ctx.internal; let code = rm.get_code().unwrap(); let memory = if let Some(_) = module.memories.get(LocalMemoryIndex::new(0)) { @@ -28,54 +36,76 @@ impl Loader for KernelLoader { } else { None }; - let table: Option> = if let Some(_) = module.tables.get(LocalTableIndex::new(0)) { - Some(unsafe { - let table = &**ctx.tables; - let elements: &[Anyfunc] = ::std::slice::from_raw_parts(table.base as *const Anyfunc, table.count); - let base_addr = code.as_ptr() as usize; - let end_addr = base_addr + code.len(); - elements.iter().map(|x| { - let func_addr = x.func as usize; - TableEntryRequest { - offset: if x.func.is_null() || func_addr < base_addr || func_addr >= end_addr { - ::std::usize::MAX - } else { - x.func as usize - base_addr - }, - sig_id: x.sig_id.0, - } - }).collect() - }) - } else if let Some(_) = module.imported_tables.get(ImportedTableIndex::new(0)) { - return Err("imported table is not supported".into()); - } else { - None - }; + let table: Option> = + if let Some(_) = module.tables.get(LocalTableIndex::new(0)) { + Some(unsafe { + let table = &**ctx.tables; + let elements: &[Anyfunc] = + ::std::slice::from_raw_parts(table.base as *const Anyfunc, table.count); + let base_addr = code.as_ptr() as usize; + let end_addr = base_addr + code.len(); + elements + .iter() + .map(|x| { + let func_addr = x.func as usize; + TableEntryRequest { + offset: if x.func.is_null() + || func_addr < base_addr + || func_addr >= end_addr + { + ::std::usize::MAX + } else { + x.func as usize - base_addr + }, + sig_id: x.sig_id.0, + } + }) + .collect() + }) + } else if let Some(_) = module.imported_tables.get(ImportedTableIndex::new(0)) { + return Err("imported table is not supported".into()); + } else { + None + }; if module.imported_globals.len() > 0 { return Err("imported globals are not supported".into()); } let globals: Vec = unsafe { - let globals: &[*mut LocalGlobal] = ::std::slice::from_raw_parts(ctx.globals, module.globals.len()); + let globals: &[*mut LocalGlobal] = + ::std::slice::from_raw_parts(ctx.globals, module.globals.len()); globals.iter().map(|x| (**x).data).collect() }; let mut import_names: Vec = vec![]; for (idx, import) in &module.imported_functions { - let name = format!("{}##{}", module.namespace_table.get(import.namespace_index), module.name_table.get(import.name_index)); - let sig = module.signatures.get( - *module.func_assoc.get(FuncIndex::new(idx.index())).unwrap() - ).unwrap(); + let name = format!( + "{}##{}", + module.namespace_table.get(import.namespace_index), + module.name_table.get(import.name_index) + ); + let sig = module + .signatures + .get(*module.func_assoc.get(FuncIndex::new(idx.index())).unwrap()) + .unwrap(); import_names.push(ImportInfo { name: name, param_count: sig.params().len(), }); } let dynamic_sigindices: &[u32] = unsafe { - ::std::mem::transmute::<&[SigId], &[u32]>( - ::std::slice::from_raw_parts(ctx.dynamic_sigindices, full_ctx.dynamic_sigindice_count()) - ) + ::std::mem::transmute::<&[SigId], &[u32]>(::std::slice::from_raw_parts( + ctx.dynamic_sigindices, + full_ctx.dynamic_sigindice_count(), + )) }; let param_counts: Vec = (0..module.func_assoc.len()) - .map(|x| module.signatures.get(*module.func_assoc.get(FuncIndex::new(x)).unwrap()).unwrap().params().len()) + .map(|x| { + module + .signatures + .get(*module.func_assoc.get(FuncIndex::new(x)).unwrap()) + .unwrap() + .params() + .len() + }) .collect(); let profile = LoadProfile { code: code, @@ -109,18 +139,25 @@ impl Instance for KernelInstance { } let args: Vec = args.iter().map(|x| x.to_u64()).collect(); - let ret = self.context.run_code(RunProfile { - entry_offset: self.offsets[id] as u32, - params: &args, - }).map_err(|x| format!("{:?}", x))?; + let ret = self + .context + .run_code(RunProfile { + entry_offset: self.offsets[id] as u32, + params: &args, + }) + .map_err(|x| format!("{:?}", x))?; Ok(ret) } fn read_memory(&mut self, offset: u32, len: u32) -> Result, String> { - self.context.read_memory(offset, len).map_err(|x| format!("{:?}", x)) + self.context + .read_memory(offset, len) + .map_err(|x| format!("{:?}", x)) } fn write_memory(&mut self, offset: u32, len: u32, buf: &[u8]) -> Result<(), String> { - self.context.write_memory(offset, len, buf).map_err(|x| format!("{:?}", x)) + self.context + .write_memory(offset, len, buf) + .map_err(|x| format!("{:?}", x)) } -} \ No newline at end of file +} diff --git a/lib/kwasm-loader/src/service.rs b/lib/kwasm-loader/src/service.rs index 7be3370b9..45ccdd869 100644 --- a/lib/kwasm-loader/src/service.rs +++ b/lib/kwasm-loader/src/service.rs @@ -1,6 +1,6 @@ +use std::error::Error; use std::fs::File; use std::io; -use std::error::Error; use std::os::unix::io::AsRawFd; macro_rules! impl_debug_display { @@ -10,7 +10,7 @@ macro_rules! impl_debug_display { ::fmt(self, f) } } - } + }; } #[repr(i32)] @@ -26,7 +26,7 @@ pub enum ServiceError { Io(io::Error), Code(i32), InvalidInput, - Rejected + Rejected, } pub type ServiceResult = Result; @@ -125,29 +125,36 @@ pub struct RunProfile<'a> { } pub struct ServiceContext { - dev: File + dev: File, } impl ServiceContext { pub fn new(load: LoadProfile) -> ServiceResult { let dev = File::open("/dev/wasmctl")?; - let imports: Vec = load.imports.iter().map(|x| { - let mut req = ImportRequest { - name: [0u8; 64], - param_count: x.param_count as u32, - }; - let name = x.name.as_bytes(); - let mut count = req.name.len() - 1; - if name.len() < count { - count = name.len(); - } - req.name[..count].copy_from_slice(&name[..count]); - req - }).collect(); + let imports: Vec = load + .imports + .iter() + .map(|x| { + let mut req = ImportRequest { + name: [0u8; 64], + param_count: x.param_count as u32, + }; + let name = x.name.as_bytes(); + let mut count = req.name.len() - 1; + if name.len() < count { + count = name.len(); + } + req.name[..count].copy_from_slice(&name[..count]); + req + }) + .collect(); let req = LoadCodeRequest { code: load.code.as_ptr(), code_len: load.code.len() as u32, - memory: load.memory.map(|x| x.as_ptr()).unwrap_or(::std::ptr::null()), + memory: load + .memory + .map(|x| x.as_ptr()) + .unwrap_or(::std::ptr::null()), memory_len: load.memory.map(|x| x.len() as u32).unwrap_or(0), memory_max: load.memory_max as u32, table: load.table.map(|x| x.as_ptr()).unwrap_or(::std::ptr::null()), @@ -164,15 +171,13 @@ impl ServiceContext { ::libc::ioctl( fd, Command::LoadCode as i32 as ::libc::c_ulong, - &req as *const _ as ::libc::c_ulong + &req as *const _ as ::libc::c_ulong, ) }; if ret != 0 { Err(ServiceError::Code(ret)) } else { - Ok(ServiceContext { - dev: dev, - }) + Ok(ServiceContext { dev: dev }) } } @@ -189,7 +194,7 @@ impl ServiceContext { ::libc::ioctl( fd, Command::RunCode as i32 as ::libc::c_ulong, - &mut req as *mut _ as ::libc::c_ulong + &mut req as *mut _ as ::libc::c_ulong, ) }; if err < 0 { @@ -217,7 +222,7 @@ impl ServiceContext { ::libc::ioctl( fd, Command::ReadMemory as i32 as ::libc::c_ulong, - &req as *const _ as ::libc::c_ulong + &req as *const _ as ::libc::c_ulong, ) }; if err < 0 { @@ -238,7 +243,7 @@ impl ServiceContext { ::libc::ioctl( fd, Command::WriteMemory as i32 as ::libc::c_ulong, - &req as *const _ as ::libc::c_ulong + &req as *const _ as ::libc::c_ulong, ) }; if err < 0 { diff --git a/lib/kwasm-net/src/lib.rs b/lib/kwasm-net/src/lib.rs index 2cfce8624..fd4108162 100644 --- a/lib/kwasm-net/src/lib.rs +++ b/lib/kwasm-net/src/lib.rs @@ -1,10 +1,10 @@ #![feature(wasi_ext)] -use std::fs::File; -use std::os::wasi::io::FromRawFd; -use std::net::{Ipv4Addr, AddrParseError}; -use std::sync::{Arc, Mutex}; use std::cell::RefCell; +use std::fs::File; +use std::net::{AddrParseError, Ipv4Addr}; +use std::os::wasi::io::FromRawFd; +use std::sync::{Arc, Mutex}; const AF_INET: i32 = 2; const SOCK_STREAM: i32 = 1; @@ -26,27 +26,27 @@ extern "C" { fn _bind(fd: i32, sa: *const SockaddrIn, sa_len: usize) -> i32; fn _listen(fd: i32, backlog: i32) -> i32; fn _accept4(fd: i32, sa: *mut SockaddrIn, sa_len: *mut usize, flags: u32) -> i32; - fn _sendto(fd: i32, buf: *const u8, buf_len: usize, flags: u32, addr: *const SockaddrIn, addr_len: usize) -> i32; - fn _recvfrom(fd: i32, buf: *mut u8, buf_len: usize, flags: u32, addr: *mut SockaddrIn, addr_len: *mut usize) -> i32; + fn _sendto( + fd: i32, + buf: *const u8, + buf_len: usize, + flags: u32, + addr: *const SockaddrIn, + addr_len: usize, + ) -> i32; + fn _recvfrom( + fd: i32, + buf: *mut u8, + buf_len: usize, + flags: u32, + addr: *mut SockaddrIn, + addr_len: *mut usize, + ) -> i32; fn _eventfd_sem(initial: u32) -> i32; fn _epoll_create() -> i32; - fn _epoll_ctl( - epfd: i32, - op: i32, - fd: i32, - event: *const EpollEvent, - ) -> i32; - fn _epoll_wait( - epfd: i32, - events: *mut EpollEvent, - maxevents: usize, - timeout: i32, - ) -> i32; - fn _fcntl( - fd: i32, - cmd: i32, - arg: u32, - ) -> i32; + fn _epoll_ctl(epfd: i32, op: i32, fd: i32, event: *const EpollEvent) -> i32; + fn _epoll_wait(epfd: i32, events: *mut EpollEvent, maxevents: usize, timeout: i32) -> i32; + fn _fcntl(fd: i32, cmd: i32, arg: u32) -> i32; } thread_local! { @@ -67,9 +67,7 @@ pub struct Epoll { impl Epoll { pub fn new() -> Epoll { - let fd = unsafe { - _epoll_create() - }; + let fd = unsafe { _epoll_create() }; assert!(fd >= 0); Epoll { fd: fd, @@ -85,10 +83,11 @@ impl Epoll { GLOBAL_EPOLL.with(|x| { *x.borrow_mut() = Some(self.clone()); }); - let mut events: Vec = vec! [ EpollEvent::default(); 32 ]; + let mut events: Vec = vec![EpollEvent::default(); 32]; loop { loop { - let imm_queue = ::std::mem::replace(&mut *self.imm_queue.lock().unwrap(), Vec::new()); + let imm_queue = + ::std::mem::replace(&mut *self.imm_queue.lock().unwrap(), Vec::new()); if imm_queue.len() == 0 { break; } @@ -108,7 +107,7 @@ impl Epoll { let mut state = Box::from_raw(ev.data as usize as *mut AsyncState); (state.callback.take().unwrap())(); put_async_state(state); - //println!("After callback"); + //println!("After callback"); } else { println!("unknown event(s): 0x{:x}", ev.events); } @@ -128,11 +127,15 @@ impl Drop for Epoll { #[derive(Copy, Clone, Debug)] pub enum EpollDirection { In, - Out + Out, } fn get_async_state() -> Box { - ASYNC_STATE_POOL.with(|pool| pool.borrow_mut().pop().unwrap_or_else(|| Box::new(AsyncState::default()))) + ASYNC_STATE_POOL.with(|pool| { + pool.borrow_mut() + .pop() + .unwrap_or_else(|| Box::new(AsyncState::default())) + }) } fn put_async_state(mut x: Box) { @@ -147,7 +150,11 @@ pub fn schedule(f: F) { epoll.schedule(f); } -fn get_async_io_payload Result + 'static, F: FnOnce(Result) + 'static>( +fn get_async_io_payload< + T: 'static, + P: FnMut(i32) -> Result + 'static, + F: FnOnce(Result) + 'static, +>( epoll: Arc, fd: i32, direction: EpollDirection, @@ -157,7 +164,11 @@ fn get_async_io_payload Result + 'static, F __get_async_io_payload(epoll, fd, direction, poll_action, on_ready, false) } -fn __get_async_io_payload Result + 'static, F: FnOnce(Result) + 'static>( +fn __get_async_io_payload< + T: 'static, + P: FnMut(i32) -> Result + 'static, + F: FnOnce(Result) + 'static, +>( epoll: Arc, fd: i32, direction: EpollDirection, @@ -173,7 +184,14 @@ fn __get_async_io_payload Result + 'static, match ret { Err(x) if x == -EAGAIN || x == -EWOULDBLOCK => { let mut state = get_async_state(); - state.callback = Some(__get_async_io_payload(epoll.clone(), fd, direction, poll_action, on_ready, true)); + state.callback = Some(__get_async_io_payload( + epoll.clone(), + fd, + direction, + poll_action, + on_ready, + true, + )); state._epoll = Some(epoll); let direction_flag = match direction { EpollDirection::In => EPOLLIN, @@ -184,22 +202,14 @@ fn __get_async_io_payload Result + 'static, data: Box::into_raw(state) as usize as _, }; //println!("Alloc event {:?}", ev.data as usize as *mut AsyncState); - let ret = unsafe { _epoll_ctl( - epfd, - EPOLL_CTL_ADD, - fd, - &ev - ) }; + let ret = unsafe { _epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) }; assert!(ret >= 0); - }, + } x => { if registered { - assert!(unsafe { _epoll_ctl( - epfd, - EPOLL_CTL_DEL, - fd, - ::std::ptr::null(), - ) } >= 0); + assert!( + unsafe { _epoll_ctl(epfd, EPOLL_CTL_DEL, fd, ::std::ptr::null(),) } >= 0 + ); } on_ready(x); // fast path } @@ -210,8 +220,8 @@ fn __get_async_io_payload Result + 'static, #[repr(C)] #[derive(Copy, Clone)] struct SockaddrIn { - sin_family: u16, // e.g. AF_INET - sin_port: u16, // e.g. htons(3490) + sin_family: u16, // e.g. AF_INET + sin_port: u16, // e.g. htons(3490) sin_addr: InAddr, sin_zero: [u8; 8], } @@ -264,23 +274,19 @@ impl Tcp4Listener { let sa = SockaddrIn { sin_family: AF_INET as _, sin_port: invert_byteorder_u16(port), - sin_addr: InAddr { s_addr: unsafe { ::std::mem::transmute(addr.octets()) } }, + sin_addr: InAddr { + s_addr: unsafe { ::std::mem::transmute(addr.octets()) }, + }, sin_zero: [0; 8], }; - let fd = unsafe { - _socket(AF_INET, SOCK_STREAM, 0) - }; + let fd = unsafe { _socket(AF_INET, SOCK_STREAM, 0) }; if fd < 0 { return Err(SocketError::SocketCreate); } - if unsafe { - _bind(fd, &sa, ::std::mem::size_of::()) - } < 0 { + if unsafe { _bind(fd, &sa, ::std::mem::size_of::()) } < 0 { return Err(SocketError::Bind); } - if unsafe { - _listen(fd, backlog as _) - } < 0 { + if unsafe { _listen(fd, backlog as _) } < 0 { return Err(SocketError::Listen); } @@ -297,34 +303,42 @@ impl Tcp4Listener { }) } - pub fn accept_async, i32>) -> Result<(), ()> + 'static>(self: Arc, ep: Arc, cb: F) { + pub fn accept_async, i32>) -> Result<(), ()> + 'static>( + self: Arc, + ep: Arc, + cb: F, + ) { let ep2 = ep.clone(); - (get_async_io_payload(ep.clone(), self.fd, EpollDirection::In, move |fd| -> Result, i32> { - let mut incoming_sa: SockaddrIn = unsafe { ::std::mem::uninitialized() }; - let mut real_len: usize = ::std::mem::size_of::(); - let conn = unsafe { - _accept4(fd, &mut incoming_sa, &mut real_len, O_NONBLOCK) - }; - if conn >= 0 { - unsafe { - let mut socket_flags = _fcntl(conn, F_GETFL, 0) as u32; - socket_flags |= O_NONBLOCK; - assert!(_fcntl(conn, F_SETFL, socket_flags) >= 0); + (get_async_io_payload( + ep.clone(), + self.fd, + EpollDirection::In, + move |fd| -> Result, i32> { + let mut incoming_sa: SockaddrIn = unsafe { ::std::mem::uninitialized() }; + let mut real_len: usize = ::std::mem::size_of::(); + let conn = unsafe { _accept4(fd, &mut incoming_sa, &mut real_len, O_NONBLOCK) }; + if conn >= 0 { + unsafe { + let mut socket_flags = _fcntl(conn, F_GETFL, 0) as u32; + socket_flags |= O_NONBLOCK; + assert!(_fcntl(conn, F_SETFL, socket_flags) >= 0); + } + Ok(Arc::new(TcpStream { + fd: conn, + epoll: ep.clone(), + })) + } else { + Err(conn) } - Ok(Arc::new(TcpStream { - fd: conn, - epoll: ep.clone(), - })) - } else { - Err(conn) - } - }, move |x| { - schedule(|| { - if let Ok(()) = cb(x) { - self.accept_async(ep2, cb); - } - }); - }))(); + }, + move |x| { + schedule(|| { + if let Ok(()) = cb(x) { + self.accept_async(ep2, cb); + } + }); + }, + ))(); } } @@ -334,7 +348,12 @@ pub struct TcpStream { } impl TcpStream { - pub fn __write_async(self: Arc, data: Vec, offset: usize, cb: impl FnOnce(Result<(usize, Vec), i32>) + 'static) { + pub fn __write_async( + self: Arc, + data: Vec, + offset: usize, + cb: impl FnOnce(Result<(usize, Vec), i32>) + 'static, + ) { let mut data = Some(data); (get_async_io_payload( @@ -344,9 +363,8 @@ impl TcpStream { move |fd| -> Result<(usize, Vec), i32> { let _data = data.as_ref().unwrap(); let _data = &_data[offset..]; - let ret = unsafe { - _sendto(fd, _data.as_ptr(), _data.len(), 0, ::std::ptr::null(), 0) - }; + let ret = + unsafe { _sendto(fd, _data.as_ptr(), _data.len(), 0, ::std::ptr::null(), 0) }; if ret >= 0 { Ok((ret as usize, data.take().unwrap())) } else { @@ -356,37 +374,52 @@ impl TcpStream { move |x| { drop(self); cb(x); - } + }, ))(); } - pub fn write_async(self: Arc, data: Vec, cb: impl FnOnce(Result<(usize, Vec), i32>) + 'static) { + pub fn write_async( + self: Arc, + data: Vec, + cb: impl FnOnce(Result<(usize, Vec), i32>) + 'static, + ) { self.__write_async(data, 0, cb) } - pub fn write_all_async(self: Arc, data: Vec, cb: impl FnOnce(Result, i32>) + 'static) { - fn inner(me: Arc, data: Vec, offset: usize, cb: impl FnOnce(Result, i32>) + 'static) { + pub fn write_all_async( + self: Arc, + data: Vec, + cb: impl FnOnce(Result, i32>) + 'static, + ) { + fn inner( + me: Arc, + data: Vec, + offset: usize, + cb: impl FnOnce(Result, i32>) + 'static, + ) { let me2 = me.clone(); - me.__write_async(data, offset, move |result| { - match result { - Ok((len, data)) => { - let new_offset = offset + len; - if new_offset == data.len() { - cb(Ok(data)); - } else { - inner(me2, data, new_offset, cb); - } - } - Err(code) => { - cb(Err(code)); + me.__write_async(data, offset, move |result| match result { + Ok((len, data)) => { + let new_offset = offset + len; + if new_offset == data.len() { + cb(Ok(data)); + } else { + inner(me2, data, new_offset, cb); } } + Err(code) => { + cb(Err(code)); + } }) } inner(self, data, 0, cb); } - pub fn read_async(self: Arc, out: Vec, cb: impl FnOnce(Result, i32>) + 'static) { + pub fn read_async( + self: Arc, + out: Vec, + cb: impl FnOnce(Result, i32>) + 'static, + ) { let mut out = Some(out); (get_async_io_payload( self.epoll.clone(), @@ -396,7 +429,14 @@ impl TcpStream { let _out = out.as_mut().unwrap(); let out_cap = _out.capacity(); let ret = unsafe { - _recvfrom(fd, _out.as_mut_ptr(), out_cap, 0, ::std::ptr::null_mut(), ::std::ptr::null_mut()) + _recvfrom( + fd, + _out.as_mut_ptr(), + out_cap, + 0, + ::std::ptr::null_mut(), + ::std::ptr::null_mut(), + ) }; if ret >= 0 { assert!(ret as usize <= out_cap); @@ -411,7 +451,7 @@ impl TcpStream { move |x| { drop(self); cb(x); - } + }, ))(); } } diff --git a/lib/runtime-core/src/backend.rs b/lib/runtime-core/src/backend.rs index c86c9569d..51d27f964 100644 --- a/lib/runtime-core/src/backend.rs +++ b/lib/runtime-core/src/backend.rs @@ -91,8 +91,12 @@ pub trait RunnableModule: Send + Sync { unsafe fn do_early_trap(&self, data: Box) -> !; - fn get_code(&self) -> Option<&[u8]> { None } - fn get_offsets(&self) -> Option> { None } + fn get_code(&self) -> Option<&[u8]> { + None + } + fn get_offsets(&self) -> Option> { + None + } } pub trait CacheGen: Send + Sync { diff --git a/lib/runtime-core/src/codegen.rs b/lib/runtime-core/src/codegen.rs index 2f7c2d900..f941fc882 100644 --- a/lib/runtime-core/src/codegen.rs +++ b/lib/runtime-core/src/codegen.rs @@ -57,7 +57,9 @@ pub trait ModuleCodeGenerator, RM: RunnableModule, /// Adds an import function. fn feed_import_function(&mut self) -> Result<(), E>; - fn feed_compiler_config(&mut self, _config: &CompilerConfig) -> Result<(), E> { Ok(()) } + fn feed_compiler_config(&mut self, _config: &CompilerConfig) -> Result<(), E> { + Ok(()) + } unsafe fn from_cache(cache: Artifact, _: Token) -> Result; } diff --git a/lib/runtime-core/src/instance.rs b/lib/runtime-core/src/instance.rs index 347ec37f0..69a8884c3 100644 --- a/lib/runtime-core/src/instance.rs +++ b/lib/runtime-core/src/instance.rs @@ -5,15 +5,15 @@ use crate::{ export::{Context, Export, ExportIter, FuncPointer}, global::Global, import::{ImportObject, LikeNamespace}, + loader::Loader, memory::Memory, module::{ExportIndex, Module, ModuleInfo, ModuleInner}, sig_registry::SigRegistry, + structures::TypedIndex, table::Table, typed_func::{Func, Wasm, WasmTrapInfo, WasmTypeList}, types::{FuncIndex, FuncSig, GlobalIndex, LocalOrImport, MemoryIndex, TableIndex, Type, Value}, vm, - loader::Loader, - structures::TypedIndex, }; use smallvec::{smallvec, SmallVec}; use std::{mem, ptr::NonNull, sync::Arc}; @@ -130,7 +130,9 @@ impl Instance { } pub fn load(&self, loader: T) -> ::std::result::Result { - loader.load(&*self.module.runnable_module, &self.module.info, unsafe { &*self.inner.vmctx }) + loader.load(&*self.module.runnable_module, &self.module.info, unsafe { + &*self.inner.vmctx + }) } /// Through generic magic and the awe-inspiring power of traits, we bring you... diff --git a/lib/runtime-core/src/lib.rs b/lib/runtime-core/src/lib.rs index 26d153d12..20708c17a 100644 --- a/lib/runtime-core/src/lib.rs +++ b/lib/runtime-core/src/lib.rs @@ -21,6 +21,7 @@ pub mod export; pub mod global; pub mod import; pub mod instance; +pub mod loader; pub mod memory; pub mod module; pub mod parse; @@ -34,7 +35,6 @@ pub mod units; pub mod vm; #[doc(hidden)] pub mod vmcalls; -pub mod loader; use self::error::CompileResult; #[doc(inline)] diff --git a/lib/runtime-core/src/loader.rs b/lib/runtime-core/src/loader.rs index 6b970aa95..5ef127ec7 100644 --- a/lib/runtime-core/src/loader.rs +++ b/lib/runtime-core/src/loader.rs @@ -1,24 +1,21 @@ +use crate::{backend::RunnableModule, module::ModuleInfo, types::Value, vm::Ctx}; +#[cfg(unix)] +use libc::{mmap, mprotect, munmap, MAP_ANON, MAP_PRIVATE, PROT_EXEC, PROT_READ, PROT_WRITE}; use std::{ fmt::Debug, ops::{Deref, DerefMut}, }; -use crate::{ - backend::RunnableModule, - vm::Ctx, - module::ModuleInfo, - types::Value, -}; -#[cfg(unix)] -use libc::{ - mmap, mprotect, munmap, MAP_ANON, MAP_PRIVATE, PROT_EXEC, PROT_READ, - PROT_WRITE, -}; pub trait Loader { type Instance: Instance; type Error: Debug; - fn load(&self, rm: &dyn RunnableModule, module: &ModuleInfo, ctx: &Ctx) -> Result; + fn load( + &self, + rm: &dyn RunnableModule, + module: &ModuleInfo, + ctx: &Ctx, + ) -> Result; } pub trait Instance { @@ -39,7 +36,12 @@ impl Loader for LocalLoader { type Instance = LocalInstance; type Error = String; - fn load(&self, rm: &dyn RunnableModule, _module: &ModuleInfo, _ctx: &Ctx) -> Result { + fn load( + &self, + rm: &dyn RunnableModule, + _module: &ModuleInfo, + _ctx: &Ctx, + ) -> Result { let code = rm.get_code().unwrap(); let mut code_mem = CodeMemory::new(code.len()); code_mem[..code.len()].copy_from_slice(code); @@ -67,11 +69,29 @@ impl Instance for LocalInstance { match args.len() { 0 => (transmute::<_, extern "C" fn() -> u64>(addr))(), 1 => (transmute::<_, extern "C" fn(u64) -> u64>(addr))(args[0].to_u64()), - 2 => (transmute::<_, extern "C" fn(u64, u64) -> u64>(addr))(args[0].to_u64(), args[1].to_u64()), - 3 => (transmute::<_, extern "C" fn(u64, u64, u64) -> u64>(addr))(args[0].to_u64(), args[1].to_u64(), args[2].to_u64()), - 4 => (transmute::<_, extern "C" fn(u64, u64, u64, u64) -> u64>(addr))(args[0].to_u64(), args[1].to_u64(), args[2].to_u64(), args[3].to_u64()), - 5 => (transmute::<_, extern "C" fn(u64, u64, u64, u64, u64) -> u64>(addr))(args[0].to_u64(), args[1].to_u64(), args[2].to_u64(), args[3].to_u64(), args[4].to_u64()), - _ => return Err("too many arguments".into()) + 2 => (transmute::<_, extern "C" fn(u64, u64) -> u64>(addr))( + args[0].to_u64(), + args[1].to_u64(), + ), + 3 => (transmute::<_, extern "C" fn(u64, u64, u64) -> u64>(addr))( + args[0].to_u64(), + args[1].to_u64(), + args[2].to_u64(), + ), + 4 => (transmute::<_, extern "C" fn(u64, u64, u64, u64) -> u64>(addr))( + args[0].to_u64(), + args[1].to_u64(), + args[2].to_u64(), + args[3].to_u64(), + ), + 5 => (transmute::<_, extern "C" fn(u64, u64, u64, u64, u64) -> u64>(addr))( + args[0].to_u64(), + args[1].to_u64(), + args[2].to_u64(), + args[3].to_u64(), + args[4].to_u64(), + ), + _ => return Err("too many arguments".into()), } }) } @@ -129,23 +149,21 @@ impl CodeMemory { #[cfg(unix)] impl Drop for CodeMemory { fn drop(&mut self) { - unsafe { munmap(self.ptr as _, self.size); } + unsafe { + munmap(self.ptr as _, self.size); + } } } impl Deref for CodeMemory { type Target = [u8]; fn deref(&self) -> &[u8] { - unsafe { - ::std::slice::from_raw_parts(self.ptr, self.size) - } + unsafe { ::std::slice::from_raw_parts(self.ptr, self.size) } } } impl DerefMut for CodeMemory { fn deref_mut(&mut self) -> &mut [u8] { - unsafe { - ::std::slice::from_raw_parts_mut(self.ptr, self.size) - } + unsafe { ::std::slice::from_raw_parts_mut(self.ptr, self.size) } } -} \ No newline at end of file +} diff --git a/lib/runtime-core/src/vm.rs b/lib/runtime-core/src/vm.rs index 3562169ad..8e3ad4be8 100644 --- a/lib/runtime-core/src/vm.rs +++ b/lib/runtime-core/src/vm.rs @@ -300,9 +300,7 @@ impl Ctx { /// Returns the number of dynamic sigindices. pub fn dynamic_sigindice_count(&self) -> usize { - unsafe { - (*self.local_backing).dynamic_sigindices.len() - } + unsafe { (*self.local_backing).dynamic_sigindices.len() } } } diff --git a/lib/singlepass-backend/src/codegen_x64.rs b/lib/singlepass-backend/src/codegen_x64.rs index c67dde3f5..7d4d0de5c 100644 --- a/lib/singlepass-backend/src/codegen_x64.rs +++ b/lib/singlepass-backend/src/codegen_x64.rs @@ -10,7 +10,9 @@ use smallvec::SmallVec; use std::ptr::NonNull; use std::{any::Any, collections::HashMap, sync::Arc}; use wasmer_runtime_core::{ - backend::{sys::Memory, Backend, CacheGen, Token, RunnableModule, CompilerConfig, MemoryBoundCheckMode}, + backend::{ + sys::Memory, Backend, CacheGen, CompilerConfig, MemoryBoundCheckMode, RunnableModule, Token, + }, cache::{Artifact, Error as CacheError}, codegen::*, memory::MemoryType, @@ -318,19 +320,18 @@ impl ModuleCodeGenerator } fn next_function(&mut self) -> Result<&mut X64FunctionCode, CodegenError> { - let (mut assembler, mut function_labels, breakpoints) = - match self.functions.last_mut() { - Some(x) => ( - x.assembler.take().unwrap(), - x.function_labels.take().unwrap(), - x.breakpoints.take().unwrap(), - ), - None => ( - self.assembler.take().unwrap(), - self.function_labels.take().unwrap(), - HashMap::new(), - ), - }; + let (mut assembler, mut function_labels, breakpoints) = match self.functions.last_mut() { + Some(x) => ( + x.assembler.take().unwrap(), + x.function_labels.take().unwrap(), + x.breakpoints.take().unwrap(), + ), + None => ( + self.assembler.take().unwrap(), + self.function_labels.take().unwrap(), + HashMap::new(), + ), + }; let begin_offset = assembler.offset(); let begin_label_info = function_labels .entry(self.functions.len() + self.func_import_count) @@ -365,12 +366,12 @@ impl ModuleCodeGenerator Ok(self.functions.last_mut().unwrap()) } - fn finalize(mut self, _: &ModuleInfo) -> Result<(X64ExecutionContext, Box), CodegenError> { + fn finalize( + mut self, + _: &ModuleInfo, + ) -> Result<(X64ExecutionContext, Box), CodegenError> { let (assembler, breakpoints) = match self.functions.last_mut() { - Some(x) => ( - x.assembler.take().unwrap(), - x.breakpoints.take().unwrap(), - ), + Some(x) => (x.assembler.take().unwrap(), x.breakpoints.take().unwrap()), None => { return Err(CodegenError { message: "no function", @@ -1232,7 +1233,7 @@ impl X64FunctionCode { MemoryBoundCheckMode::Enable => true, MemoryBoundCheckMode::Disable => false, }; - + let tmp_addr = m.acquire_temp_gpr().unwrap(); let tmp_base = m.acquire_temp_gpr().unwrap(); let tmp_bound = m.acquire_temp_gpr().unwrap(); @@ -1429,7 +1430,7 @@ impl FunctionCodeGenerator for X64FunctionCode { GPR::RDI, // first parameter is vmctx vm::Ctx::offset_stack_lower_bound() as i32, ), - Location::GPR(GPR::RSP) + Location::GPR(GPR::RSP), ); a.emit_conditional_trap(Condition::Below); } @@ -3329,13 +3330,16 @@ impl FunctionCodeGenerator for X64FunctionCode { let memory_index = MemoryIndex::new(reserved as usize); a.emit_mov( Size::S64, - Location::Memory(Machine::get_vmctx_reg(), vm::Ctx::offset_intrinsics() as i32), - Location::GPR(GPR::RAX) + Location::Memory( + Machine::get_vmctx_reg(), + vm::Ctx::offset_intrinsics() as i32, + ), + Location::GPR(GPR::RAX), ); a.emit_mov( Size::S64, Location::Memory(GPR::RAX, vm::Intrinsics::offset_memory_size() as i32), - Location::GPR(GPR::RAX) + Location::GPR(GPR::RAX), ); Self::emit_call_sysv( a, @@ -3359,13 +3363,16 @@ impl FunctionCodeGenerator for X64FunctionCode { a.emit_mov( Size::S64, - Location::Memory(Machine::get_vmctx_reg(), vm::Ctx::offset_intrinsics() as i32), - Location::GPR(GPR::RAX) + Location::Memory( + Machine::get_vmctx_reg(), + vm::Ctx::offset_intrinsics() as i32, + ), + Location::GPR(GPR::RAX), ); a.emit_mov( Size::S64, Location::Memory(GPR::RAX, vm::Intrinsics::offset_memory_grow() as i32), - Location::GPR(GPR::RAX) + Location::GPR(GPR::RAX), ); Self::emit_call_sysv( @@ -4091,10 +4098,7 @@ impl FunctionCodeGenerator for X64FunctionCode { ); a.emit_jmp(Condition::AboveEqual, default_br); - a.emit_lea_label( - table_label, - Location::GPR(GPR::RCX), - ); + a.emit_lea_label(table_label, Location::GPR(GPR::RCX)); a.emit_mov(Size::S32, cond, Location::GPR(GPR::RDX)); a.emit_imul_imm32_gpr64(5, GPR::RDX); a.emit_add(Size::S64, Location::GPR(GPR::RCX), Location::GPR(GPR::RDX)); diff --git a/src/bin/kwasmd.rs b/src/bin/kwasmd.rs index 509167008..b4a425061 100644 --- a/src/bin/kwasmd.rs +++ b/src/bin/kwasmd.rs @@ -1,21 +1,19 @@ -extern crate structopt; extern crate byteorder; +extern crate structopt; use std::thread; use structopt::StructOpt; use wasmer::*; -use wasmer_runtime::{ - Value, -}; +use wasmer_runtime::Value; use wasmer_runtime_core::{ self, backend::{CompilerConfig, MemoryBoundCheckMode}, - loader::{Instance as LoadedInstance}, + loader::Instance as LoadedInstance, }; use wasmer_singlepass_backend::SinglePassCompiler; -use std::os::unix::net::{UnixStream, UnixListener}; use std::io::prelude::*; +use std::os::unix::net::{UnixListener, UnixStream}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; @@ -54,7 +52,8 @@ fn handle_client(mut stream: UnixStream) { enforce_stack_check: true, }, &SinglePassCompiler::new(), - ).unwrap(); + ) + .unwrap(); let mut import_object = wasmer_runtime_core::import::ImportObject::new(); import_object.allow_missing_functions = true; // Import initialization might be left to the loader. @@ -90,13 +89,13 @@ fn handle_client(mut stream: UnixStream) { Ok(x) => { stream.write_u32::(1).unwrap(); stream.write_u64::(x).unwrap(); - }, + } Err(e) => { println!("Execution error: {:?}", e); stream.write_u32::(0).unwrap(); - }, + } } - }, + } CMD_READ_MEMORY => { let offset = stream.read_u32::().unwrap(); let len = stream.read_u32::().unwrap(); @@ -106,7 +105,7 @@ fn handle_client(mut stream: UnixStream) { } let buf = ins.read_memory(offset, len).unwrap(); stream.write_all(&buf).unwrap(); - }, + } CMD_WRITE_MEMORY => { let offset = stream.read_u32::().unwrap(); let len = stream.read_u32::().unwrap(); @@ -118,7 +117,7 @@ fn handle_client(mut stream: UnixStream) { unsafe { buf.set_len(len as usize) }; stream.read_exact(&mut buf).unwrap(); ins.write_memory(offset, len, &buf).unwrap(); - }, + } _ => { println!("Unknown command"); return; @@ -137,7 +136,7 @@ fn run_listen(opts: Listen) { match ::std::panic::catch_unwind(::std::panic::AssertUnwindSafe(|| { handle_client(stream); })) { - Ok(()) => {}, + Ok(()) => {} Err(_) => {} } }); @@ -162,4 +161,4 @@ fn main() { #[cfg(not(feature = "loader:kwasm"))] fn main() { panic!("Kwasm loader is not enabled during compilation."); -} \ No newline at end of file +} diff --git a/src/bin/wasmer.rs b/src/bin/wasmer.rs index e5c50e22c..1fa00afd2 100644 --- a/src/bin/wasmer.rs +++ b/src/bin/wasmer.rs @@ -315,7 +315,8 @@ fn execute_wasm(options: &Run) -> Result<(), String> { enforce_stack_check: true, }, &*compiler, - ).map_err(|e| format!("Can't compile module: {:?}", e))? + ) + .map_err(|e| format!("Can't compile module: {:?}", e))? } else if disable_cache { webassembly::compile_with_config_with( &wasm_binary[..], @@ -324,7 +325,8 @@ fn execute_wasm(options: &Run) -> Result<(), String> { ..Default::default() }, &*compiler, - ).map_err(|e| format!("Can't compile module: {:?}", e))? + ) + .map_err(|e| format!("Can't compile module: {:?}", e))? } else { // If we have cache enabled @@ -388,7 +390,7 @@ fn execute_wasm(options: &Run) -> Result<(), String> { LoaderName::Kernel => Box::new(instance.load(::kwasm_loader::KernelLoader).unwrap()), }; println!("{:?}", ins.call(index, &args)); - return Ok(()) + return Ok(()); } // TODO: refactor this