Skip to content

Commit

Permalink
Try #416:
Browse files Browse the repository at this point in the history
  • Loading branch information
bors[bot] committed May 15, 2019
2 parents 6b43a6a + a1a58d4 commit 0109bd9
Show file tree
Hide file tree
Showing 32 changed files with 2,451 additions and 513 deletions.
718 changes: 391 additions & 327 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion Cargo.toml
Expand Up @@ -19,6 +19,7 @@ include = [
]

[dependencies]
byteorder = "1.3.1"
errno = "0.2.4"
structopt = "0.2.11"
wabt = "0.7.2"
Expand All @@ -32,9 +33,10 @@ wasmer-runtime-core = { path = "lib/runtime-core" }
wasmer-emscripten = { path = "lib/emscripten" }
wasmer-llvm-backend = { path = "lib/llvm-backend", optional = true }
wasmer-wasi = { path = "lib/wasi", optional = true }
wasmer-kernel-loader = { path = "lib/kernel-loader", optional = true }

[workspace]
members = ["lib/clif-backend", "lib/singlepass-backend", "lib/runtime", "lib/runtime-abi", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend", "lib/wasi", "lib/middleware-common", "examples/plugin-for-example"]
members = ["lib/clif-backend", "lib/singlepass-backend", "lib/runtime", "lib/runtime-abi", "lib/runtime-core", "lib/emscripten", "lib/spectests", "lib/win-exception-handler", "lib/runtime-c-api", "lib/llvm-backend", "lib/wasi", "lib/middleware-common", "lib/kernel-loader", "lib/kwasm-net", "examples/plugin-for-example"]

[build-dependencies]
wabt = "0.7.2"
Expand All @@ -43,6 +45,7 @@ rustc_version = "0.2.3"

[features]
default = ["fast-tests", "wasi"]
"loader:kwasm" = ["wasmer-kernel-loader"]
debug = ["wasmer-runtime-core/debug"]
extra-debug = ["wasmer-clif-backend/debug", "wasmer-runtime-core/debug"]
# This feature will allow cargo test to run much faster
Expand Down
13 changes: 13 additions & 0 deletions examples/http-server/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions examples/http-server/Cargo.toml
@@ -0,0 +1,12 @@
[package]
name = "http-server"
version = "0.1.0"
authors = ["Heyang Zhou <zhy20000919@hotmail.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[workspace]

[dependencies]
kwasm-net = { path = "../../lib/kwasm-net" }
72 changes: 72 additions & 0 deletions examples/http-server/src/main.rs
@@ -0,0 +1,72 @@
#![feature(wasi_ext)]

use kwasm_net::{schedule, Epoll, Tcp4Listener, TcpStream};
use std::sync::Arc;

fn serve(stream: Arc<TcpStream>, mut all: Vec<u8>) {
let stream2 = stream.clone();
stream.read_async(
Vec::with_capacity(512),
move |result| {
match result {
Ok(buf) => {
if buf.len() == 0 {
return;
}
all.extend_from_slice(&buf);
if all.len() > 4096 {
println!("header too large");
return;
}
let s = match ::std::str::from_utf8(&all) {
Ok(x) => x,
Err(e) => {
println!("not utf8: {:?}", e);
return;
}
};
if let Some(_pos) = s.find("\r\n\r\n") {
let body = format!(
"Hello, world!\n",
).into_bytes();
let stream = stream2.clone();
stream2.write_all_async(
format!(
"HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nConnection: close\r\nContent-Length: {}\r\n\r\n",
body.len()
).into_bytes(),
|_| {
stream.write_all_async(body, |_| {});
}
);
} else {
schedule(|| serve(stream2, all));
}
}
Err(code) => {
println!("failed to read; code = {}", code);
}
}
}
);
}

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(())
}
});
println!("start epoll");
unsafe {
epoll.run();
}
}
9 changes: 9 additions & 0 deletions examples/pipe/Cargo.toml
@@ -0,0 +1,9 @@
[package]
name = "pipe"
version = "0.1.0"
authors = ["Heyang Zhou <zhy20000919@hotmail.com>"]
edition = "2018"

[workspace]

[dependencies]
13 changes: 13 additions & 0 deletions examples/pipe/src/main.rs
@@ -0,0 +1,13 @@
use std::io::{Read, Write};

fn main() {
let mut stdin = ::std::io::stdin();
let mut stdout = ::std::io::stdout();
let mut buf: Vec<u8> = vec![0; 512];
let mut total: u64 = 0;
while total < 1048576u64 * 2048 {
let n = stdin.read(&mut buf).unwrap();
stdout.write_all(&buf[..n]).unwrap();
total += n as u64;
}
}
10 changes: 10 additions & 0 deletions examples/wasi-networking/Cargo.toml
@@ -0,0 +1,10 @@
[package]
name = "wasi-networking"
version = "0.1.0"
authors = ["Heyang Zhou <zhy20000919@hotmail.com>"]
edition = "2018"

[workspace]

[dependencies]
kwasm-net = { path = "../../lib/kwasm-net" }
49 changes: 49 additions & 0 deletions examples/wasi-networking/src/main.rs
@@ -0,0 +1,49 @@
#![feature(wasi_ext)]

use kwasm_net::{schedule, Epoll, Tcp4Listener, TcpStream};
use std::sync::Arc;

fn do_echo(stream: Arc<TcpStream>, buf: Vec<u8>) {
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);
}
});
}

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(())
}
});
println!("start epoll");
unsafe {
epoll.run();
}
}
9 changes: 9 additions & 0 deletions lib/kernel-loader/Cargo.toml
@@ -0,0 +1,9 @@
[package]
name = "wasmer-kernel-loader"
version = "0.1.0"
authors = ["Heyang Zhou <zhy20000919@hotmail.com>"]
edition = "2018"

[dependencies]
libc = "0.2.49"
wasmer-runtime-core = { path = "../runtime-core" }
168 changes: 168 additions & 0 deletions lib/kernel-loader/src/lib.rs
@@ -0,0 +1,168 @@
pub mod service;

use service::{ImportInfo, LoadProfile, RunProfile, ServiceContext, TableEntryRequest};
use wasmer_runtime_core::{
backend::RunnableModule,
loader::{self, Instance, Loader},
module::ModuleInfo,
structures::TypedIndex,
types::{
FuncIndex, ImportedMemoryIndex, ImportedTableIndex, LocalMemoryIndex, LocalTableIndex,
Value,
},
vm::{Anyfunc, Ctx, LocalGlobal, SigId},
};

pub struct KernelLoader;

impl Loader for KernelLoader {
type Instance = KernelInstance;
type Error = String;

fn load(
&self,
rm: &dyn RunnableModule,
module: &ModuleInfo,
full_ctx: &Ctx,
) -> Result<Self::Instance, Self::Error> {
let ctx = &full_ctx.internal;
let code = rm.get_code().unwrap();
let memory = if let Some(_) = module.memories.get(LocalMemoryIndex::new(0)) {
Some(unsafe {
::std::slice::from_raw_parts((**ctx.memories).base, (**ctx.memories).bound)
})
} else if let Some(_) = module.imported_memories.get(ImportedMemoryIndex::new(0)) {
return Err("imported memory is not supported".into());
} else {
None
};
let table: Option<Vec<TableEntryRequest>> =
if let Some(_) = module.tables.get(LocalTableIndex::new(0)) {
Some(unsafe {
let table = &**ctx.tables;
let elements: &[Anyfunc];
#[allow(clippy::cast_ptr_alignment)]
{
elements =
::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<u64> = unsafe {
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<ImportInfo> = 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();
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(),
))
};
let param_counts: Vec<usize> = (0..module.func_assoc.len())
.map(|x| {
module
.signatures
.get(*module.func_assoc.get(FuncIndex::new(x)).unwrap())
.unwrap()
.params()
.len()
})
.collect();
let profile = LoadProfile {
code: code,
memory: memory,
memory_max: 0,
globals: &globals,
imports: &import_names,
dynamic_sigindices: dynamic_sigindices,
table: table.as_ref().map(|x| x.as_slice()),
};
let sc = ServiceContext::new(profile).map_err(|x| format!("{:?}", x))?;
Ok(KernelInstance {
context: sc,
offsets: rm.get_offsets().unwrap(),
param_counts: param_counts,
})
}
}

pub struct KernelInstance {
context: ServiceContext,
offsets: Vec<usize>,
param_counts: Vec<usize>, // FIXME: Full signature check
}

impl Instance for KernelInstance {
type Error = String;
fn call(&mut self, id: usize, args: &[Value]) -> Result<u64, String> {
if args.len() != self.param_counts[id] {
return Err("param count mismatch".into());
}
let args: Vec<u64> = 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))?;
Ok(ret)
}

fn read_memory(&mut self, offset: u32, len: u32) -> Result<Vec<u8>, String> {
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))
}
}

0 comments on commit 0109bd9

Please sign in to comment.