mirror of
https://github.com/fluencelabs/wasmer
synced 2024-12-13 06:15:33 +00:00
shrink select
This commit is contained in:
parent
e5951ce56d
commit
e986ec13fa
@ -102,7 +102,7 @@ impl EmscriptenVfs {
|
||||
panic!()
|
||||
}
|
||||
Some(*fd)
|
||||
},
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -1,268 +1,70 @@
|
||||
use crate::macros::emscripten_memory_ptr;
|
||||
use crate::syscalls::emscripten_vfs::{FileHandle, VirtualFd};
|
||||
use crate::syscalls::emscripten_vfs::{EmscriptenVfs, VirtualFd};
|
||||
use crate::varargs::VarArgs;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::c_void;
|
||||
use std::slice;
|
||||
use crate::EmscriptenData;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
|
||||
#[cfg(feature = "vfs")]
|
||||
#[derive(Debug)]
|
||||
struct FdPair {
|
||||
pub virtual_fd: i32,
|
||||
pub host_fd: i32,
|
||||
}
|
||||
|
||||
#[cfg(feature = "vfs")]
|
||||
fn translate_to_host_file_descriptors(
|
||||
ctx: &mut Ctx,
|
||||
mut varargs: &mut VarArgs,
|
||||
vfs: &EmscriptenVfs,
|
||||
set_ptr: *mut libc::fd_set,
|
||||
nfds: i32,
|
||||
fds_set_offset: u32,
|
||||
) -> (i32, HashMap<i32, i32>, Vec<FdPair>) {
|
||||
let set_ptr = emscripten_memory_ptr(ctx.memory(0), fds_set_offset) as *mut _; // e.g. libc::unix::bsd::fd_set
|
||||
let set_u8_ptr = set_ptr as *mut u8;
|
||||
|
||||
let bit_array_size = if nfds >= 0 { (nfds + 7) / 8 } else { 0 } as usize;
|
||||
let end_offset = fds_set_offset as usize + bit_array_size;
|
||||
let set_view = &ctx.memory(0).view::<u8>()[(fds_set_offset as usize)..end_offset];
|
||||
use bit_field::BitArray;
|
||||
// let check = set_ptr.get_bit(1);
|
||||
|
||||
let fds_slice = unsafe { slice::from_raw_parts(set_u8_ptr, bit_array_size) };
|
||||
|
||||
// (0usize..nfds as usize).filter_map(|x| fds_slice.get_bit(x));
|
||||
// let ofds = (0..nfds).filter_map(|v| fd_slice.v)
|
||||
let original_fds: Vec<i32> = (0..nfds)
|
||||
.filter_map(|virtual_fd| {
|
||||
if fds_slice.get_bit(virtual_fd as usize) {
|
||||
Some(virtual_fd as i32)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
) -> (i32, Vec<i32>) {
|
||||
let pairs = (0..nfds)
|
||||
.map(|vfd| (vfd, vfs.get_host_socket_fd(&VirtualFd(vfd)).unwrap_or(-1)))
|
||||
.filter(|(vfd, _)| unsafe { libc::FD_ISSET(*vfd, set_ptr) })
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let vfs = crate::env::get_emscripten_data(ctx).vfs.as_mut().unwrap();
|
||||
|
||||
// virtual read and write file descriptors
|
||||
let file_descriptor_pairs = original_fds
|
||||
let max = pairs
|
||||
.iter()
|
||||
.filter(|vfd| {
|
||||
if let FileHandle::VirtualFile(handle) = vfs.fd_map.get(&VirtualFd(**vfd)).unwrap() {
|
||||
debug!(
|
||||
"skipping virtual fd {} (vbox handle {}) because is a virtual file",
|
||||
*vfd, *handle
|
||||
);
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
.map(|vfd| {
|
||||
let vfd = VirtualFd(*vfd);
|
||||
let file_handle = vfs.fd_map.get(&vfd).unwrap();
|
||||
let host_fd = match file_handle {
|
||||
FileHandle::Socket(host_fd) => host_fd,
|
||||
// FileHandle::VirtualFile(handle) => handle,
|
||||
_ => panic!(),
|
||||
};
|
||||
let pair = FdPair {
|
||||
virtual_fd: vfd.0,
|
||||
host_fd: *host_fd,
|
||||
};
|
||||
// swap the read descriptors
|
||||
unsafe {
|
||||
libc::FD_CLR(pair.virtual_fd, set_ptr);
|
||||
libc::FD_SET(pair.host_fd, set_ptr);
|
||||
};
|
||||
pair
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let mut sz = 0;
|
||||
|
||||
// helper look up tables
|
||||
let mut lookup = HashMap::new();
|
||||
for pair in file_descriptor_pairs.iter() {
|
||||
// if pair.virtual_fd > sz { sz = pair.host_fd }
|
||||
if pair.host_fd > sz {
|
||||
sz = pair.host_fd
|
||||
}
|
||||
lookup.insert(pair.host_fd, pair.virtual_fd);
|
||||
}
|
||||
|
||||
let max_file_descriptor = sz;
|
||||
(max_file_descriptor, lookup, file_descriptor_pairs)
|
||||
.map(|(_, host_fd)| *host_fd)
|
||||
.max()
|
||||
.unwrap_or(-1)
|
||||
+ 1;
|
||||
let mut internal_handles = vec![0; max as usize];
|
||||
unsafe { libc::FD_ZERO(set_ptr) };
|
||||
pairs.iter().for_each(|(vfd, host_fd)| {
|
||||
internal_handles[*host_fd as usize] = *vfd;
|
||||
unsafe {
|
||||
libc::FD_SET(*host_fd, set_ptr);
|
||||
};
|
||||
});
|
||||
(max, internal_handles)
|
||||
}
|
||||
|
||||
#[cfg(feature = "vfs")]
|
||||
fn translate_to_virtual_file_descriptors(
|
||||
ctx: &mut Ctx,
|
||||
nfds: i32,
|
||||
fds_set_offset: u32,
|
||||
lookup: HashMap<i32, i32>,
|
||||
) -> Vec<FdPair> {
|
||||
let set_ptr = emscripten_memory_pointer!(ctx.memory(0), fds_set_offset) as *mut _;
|
||||
let set_u8_ptr = set_ptr as *mut u8;
|
||||
let fds_slice = unsafe { slice::from_raw_parts_mut(set_u8_ptr, nfds as usize) };
|
||||
use bit_field::BitArray;
|
||||
|
||||
let fds = (0..nfds)
|
||||
.filter_map(|virtual_fd| {
|
||||
if fds_slice.get_bit(virtual_fd as usize) {
|
||||
Some(virtual_fd as i32)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// swap descriptors back
|
||||
let pairs = fds
|
||||
fn translate_to_virtual_file_descriptors(set_ptr: *mut libc::fd_set, internal_handles: Vec<i32>) {
|
||||
let virtual_fds = internal_handles
|
||||
.iter()
|
||||
.filter_map(|host_fd| {
|
||||
lookup
|
||||
.get(&host_fd)
|
||||
.map(|virtual_fd| (*virtual_fd, host_fd))
|
||||
})
|
||||
.map(|(virtual_fd, host_fd)| {
|
||||
unsafe {
|
||||
libc::FD_CLR(*host_fd, set_ptr);
|
||||
libc::FD_SET(virtual_fd, set_ptr);
|
||||
}
|
||||
FdPair {
|
||||
virtual_fd,
|
||||
host_fd: *host_fd,
|
||||
}
|
||||
})
|
||||
.enumerate()
|
||||
.filter(|(host_fd, _)| unsafe { libc::FD_ISSET(*host_fd as i32, set_ptr) })
|
||||
.map(|(_, vfd)| *vfd)
|
||||
.collect::<Vec<_>>();
|
||||
pairs
|
||||
unsafe { libc::FD_ZERO(set_ptr) };
|
||||
virtual_fds
|
||||
.iter()
|
||||
.for_each(|vfd| unsafe { libc::FD_SET(*vfd, set_ptr) });
|
||||
}
|
||||
|
||||
/// select
|
||||
#[cfg(feature = "vfs")]
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
pub fn ___syscall142(ctx: &mut Ctx, _which: libc::c_int, mut varargs: VarArgs) -> libc::c_int {
|
||||
debug!("emscripten::___syscall142 (newselect) {}", _which);
|
||||
pub fn ___syscall142(ctx: &mut Ctx, _: libc::c_int, mut varargs: VarArgs) -> libc::c_int {
|
||||
debug!("emscripten::___syscall142 (select)");
|
||||
let nfds: i32 = varargs.get(ctx);
|
||||
let readfds: u32 = varargs.get(ctx);
|
||||
let writefds: u32 = varargs.get(ctx);
|
||||
let _exceptfds: u32 = varargs.get(ctx);
|
||||
let timeout: i32 = varargs.get(ctx);
|
||||
let _timeout: i32 = varargs.get(ctx);
|
||||
assert!(nfds <= 64, "`nfds` must be less than or equal to 64");
|
||||
let readfds_set_ptr = emscripten_memory_pointer!(ctx.memory(0), readfds) as *mut _;
|
||||
let writefds_set_ptr = emscripten_memory_pointer!(ctx.memory(0), writefds) as *mut _;
|
||||
|
||||
// debug!(" select read descriptors: {:?}", read_fds);
|
||||
//
|
||||
// debug!("select write descriptors: {:?}", write_fds);
|
||||
|
||||
let (read_max, read_lookup, read_pairs) =
|
||||
translate_to_host_file_descriptors(ctx, &mut varargs, nfds, readfds);
|
||||
let (write_max, write_lookup, write_pairs) =
|
||||
translate_to_host_file_descriptors(ctx, &mut varargs, nfds, writefds);
|
||||
|
||||
let max = if read_max > write_max {
|
||||
read_max
|
||||
} else {
|
||||
write_max
|
||||
};
|
||||
debug!("max host fd for select: {}", max);
|
||||
|
||||
let mut sz = max;
|
||||
|
||||
debug!(
|
||||
"set read descriptors BEFORE select: {:?}",
|
||||
read_pairs // .iter()
|
||||
// .map(|pair| pair.virtual_fd)
|
||||
// .collect::<Vec<_>>()
|
||||
);
|
||||
debug!(
|
||||
"set write descriptors BEFORE select: {:?}",
|
||||
write_pairs // .iter()
|
||||
// .map(|pair| pair.virtual_fd)
|
||||
// .collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
// call `select`
|
||||
sz = sz + 1;
|
||||
debug!(
|
||||
"readfds_set_ptr: {:?}",
|
||||
read_pairs
|
||||
.iter()
|
||||
.map(|pair| pair.host_fd)
|
||||
.collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
unsafe {
|
||||
use libc::FD_ISSET;
|
||||
let s = 3;
|
||||
let x = [
|
||||
FD_ISSET(s, readfds_set_ptr),
|
||||
FD_ISSET(s + 1, readfds_set_ptr),
|
||||
FD_ISSET(s + 2, readfds_set_ptr),
|
||||
FD_ISSET(s + 3, readfds_set_ptr),
|
||||
FD_ISSET(s + 4, readfds_set_ptr),
|
||||
FD_ISSET(s + 5, readfds_set_ptr),
|
||||
FD_ISSET(s + 6, readfds_set_ptr),
|
||||
FD_ISSET(s + 7, readfds_set_ptr),
|
||||
FD_ISSET(s + 8, readfds_set_ptr),
|
||||
FD_ISSET(s + 9, readfds_set_ptr),
|
||||
FD_ISSET(s + 10, readfds_set_ptr),
|
||||
FD_ISSET(s + 11, readfds_set_ptr),
|
||||
];
|
||||
debug!("BEFORE sets start with fd #{}: {:?}", s, x);
|
||||
}
|
||||
|
||||
let fds_slice = unsafe { slice::from_raw_parts(readfds_set_ptr as *const u8, 4) } as &[u8];
|
||||
debug!("host read set before: {:?}", fds_slice);
|
||||
let mut result = unsafe { libc::select(sz, readfds_set_ptr, writefds_set_ptr, 0 as _, 0 as _) };
|
||||
debug!("host read set after: {:?}", fds_slice);
|
||||
|
||||
unsafe {
|
||||
use libc::FD_ISSET;
|
||||
let s = 3;
|
||||
let x = [
|
||||
FD_ISSET(s, readfds_set_ptr),
|
||||
FD_ISSET(s + 1, readfds_set_ptr),
|
||||
FD_ISSET(s + 2, readfds_set_ptr),
|
||||
FD_ISSET(s + 3, readfds_set_ptr),
|
||||
FD_ISSET(s + 4, readfds_set_ptr),
|
||||
FD_ISSET(s + 5, readfds_set_ptr),
|
||||
FD_ISSET(s + 6, readfds_set_ptr),
|
||||
FD_ISSET(s + 7, readfds_set_ptr),
|
||||
FD_ISSET(s + 8, readfds_set_ptr),
|
||||
FD_ISSET(s + 9, readfds_set_ptr),
|
||||
FD_ISSET(s + 10, readfds_set_ptr),
|
||||
FD_ISSET(s + 11, readfds_set_ptr),
|
||||
];
|
||||
debug!("AFTER sets (start with fd #{}: {:?}", s, x);
|
||||
}
|
||||
|
||||
if result == -1 {
|
||||
panic!(
|
||||
"result returned from select was -1. The errno code: {}",
|
||||
errno::errno()
|
||||
);
|
||||
}
|
||||
|
||||
let read_pairs = translate_to_virtual_file_descriptors(ctx, sz, readfds, read_lookup);
|
||||
debug!(
|
||||
"select read descriptors after select completes: {:?}",
|
||||
read_pairs // .iter()
|
||||
// .map(|pair| pair.virtual_fd)
|
||||
// .collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
let write_pairs = translate_to_virtual_file_descriptors(ctx, sz, writefds, write_lookup);
|
||||
debug!(
|
||||
"select write descriptors after select completes: {:?}",
|
||||
write_pairs // .iter()
|
||||
// .map(|pair| pair.virtual_fd)
|
||||
// .collect::<Vec<_>>()
|
||||
);
|
||||
|
||||
let emscripten_memory = ctx.memory(0);
|
||||
let read_set_ptr = emscripten_memory_ptr(emscripten_memory, readfds) as _;
|
||||
let write_set_ptr = emscripten_memory_ptr(emscripten_memory, writefds) as _;
|
||||
let vfs = unsafe { (*(ctx.data as *const EmscriptenData)).vfs.as_ref().unwrap() };
|
||||
let (read_host_nfds, read_lookup) = translate_to_host_file_descriptors(vfs, read_set_ptr, nfds);
|
||||
let (write_host_nfds, write_lookup) =
|
||||
translate_to_host_file_descriptors(vfs, write_set_ptr, nfds);
|
||||
let host_nfds = std::cmp::max(read_host_nfds, write_host_nfds);
|
||||
// TODO: timeout and except fds set
|
||||
let result = unsafe { libc::select(host_nfds, read_set_ptr, write_set_ptr, 0 as _, 0 as _) };
|
||||
translate_to_virtual_file_descriptors(read_set_ptr, read_lookup);
|
||||
translate_to_virtual_file_descriptors(write_set_ptr, write_lookup);
|
||||
debug!("select returns {}", result);
|
||||
result
|
||||
}
|
||||
|
@ -3,9 +3,7 @@ use crate::syscalls::emscripten_vfs::FileHandle::{Socket, VirtualFile};
|
||||
use crate::syscalls::emscripten_vfs::{FileHandle, VirtualFd};
|
||||
use crate::utils::{copy_stat_into_wasm, read_string_from_wasm};
|
||||
use crate::varargs::VarArgs;
|
||||
use bit_field::BitArray;
|
||||
use libc::stat;
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::c_void;
|
||||
use std::os::raw::c_int;
|
||||
use std::slice;
|
||||
@ -553,7 +551,10 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
||||
socket, flags, len, recv_result
|
||||
);
|
||||
if recv_result < 0 {
|
||||
panic!("recvfrom result was less than zero. Errno: {}", errno::errno());
|
||||
panic!(
|
||||
"recvfrom result was less than zero. Errno: {}",
|
||||
errno::errno()
|
||||
);
|
||||
}
|
||||
recv_result
|
||||
}
|
||||
@ -608,7 +609,13 @@ pub fn ___syscall102(ctx: &mut Ctx, _which: c_int, mut varargs: VarArgs) -> c_in
|
||||
let host_socket_fd = vfs.get_host_socket_fd(&vfd).unwrap();
|
||||
|
||||
let result = unsafe {
|
||||
libc::getsockopt(host_socket_fd, correct_level, correct_name, value_addr, option_len_addr)
|
||||
libc::getsockopt(
|
||||
host_socket_fd,
|
||||
correct_level,
|
||||
correct_name,
|
||||
value_addr,
|
||||
option_len_addr,
|
||||
)
|
||||
};
|
||||
|
||||
if result == -1 {
|
||||
@ -698,7 +705,10 @@ pub fn ___syscall146(ctx: &mut Ctx, _which: i32, mut varargs: VarArgs) -> i32 {
|
||||
Some(FileHandle::Socket(host_fd)) => unsafe {
|
||||
let count = libc::write(*host_fd, iov_buf_ptr, count);
|
||||
if count < 0 {
|
||||
panic!("the count from write was less than zero. errno: {}", errno::errno());
|
||||
panic!(
|
||||
"the count from write was less than zero. errno: {}",
|
||||
errno::errno()
|
||||
);
|
||||
}
|
||||
count as usize
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user