HN user

tombl

140 karma
Posts0
Comments33
View on HN
No posts found.

Yeah, nommu absolutely doesn't imply zero memory isolation. I have a kernel port to an architecture with a nonstandard way of doing memory isolation and the existing nommu infrastructure is the only reason it can exist.

It's funny, I would actually argue the opposite point. When Deno and Bun first came out, they promised a hard break from the Node ecosystem, like how Deno leaned heavily into browser compatibility, and Bun into framework features like Bun.App.

At some point they both decided that Node compatibility was more important than their unique features, but in the time since their release Node got type stripping, require(esm), sqlite, single executable apps, a permission system, a test runner, and basically ever other Deno/Bun feature they could port over.

So at this point why use runtimes that imitate Node when you could just use Node? You'll get most of the modern niceties, but also get 100% compatibility with the existing ecosystem.

JSLinux 1 year ago

I'm effectively lying to the kernel about the environment it's executing in, and trying to convince it that it's running on the kind of hardware it expects, when in reality it's running inside a very different environment.

Since I map guest threads 1:1 to host threads in JS, and architecture-specific code manages the loading/unloading of programs, the exec syscall is exercising these lies in a way that they're not currently equipped to handle.

What I'm currently doing is improving those lies to the point where exec stops noticing they're lies and just starts functioning as expected.

JSLinux 1 year ago

yep, that's to be expected, this is a very wip demo. I'm implementing exec() support now, so currently only shell builtins work.

JSLinux 1 year ago

Thanks for pointing this out, I've deployed a fix. One of my goals for the project is to create a useful computing environment on top of any arbitrary locked down platform, so I'd love to turn it into an iOS app at some point.

JSLinux 1 year ago

Fabrice does a great job at building these self-contained pieces of software which often grow to have lives of their own. As a lesser known example, JSLinux's terminal emulator was forked a few times and is now known as xterm.js, which has become the predominant web embeddable terminal emulator.

This all comes full circle, because now I'm building a true successor to JSLinux that's way faster because I've natively compiled the kernel/userspace to wasm, and of course I'm using xterm.js for the terminal emulation.

If you like buggy demos that probably shouldn't be shared yet, you should check out https://linux.tombl.dev, but note that it's currently just a busybox shell and nothing else, so I hope you're good with `echo *` instead of `ls`.

hmm, it looks like you've got a bug in the demo app. if you type too quickly into the search bar, the entire app slows to a halt.

seems like you'd want to move the filtering logic off the main thread, or you'd want to reinvent React's "Fiber" suspendable rendering architecture.

yeah I'm also taking great inspiration from Alpine, but I like to see diversity in the space.

as one example, musl values portability over performance (great for my usecase), which makes it often significantly slower than glibc. Alpine keeps their musl relatively close to upstream, where Chimera is patches theirs more heavily.

I'm slightly hesitant to mention it for fear of a flamewar, but as someone with a niche usecase that procludes me from using systemd/glibc, I'm very grateful to Chimera as a modern take on non-GNU/Linux.

Go's "nothing is async because everything is async" model, combined with WebAssembly's (current) lack of support for stack switching and arbitrary goto, essentially mean that the compiler needs to insert extra code everywhere to support arbitrarily un/rewinding the stack.

This massively bloats binaries and means that go compiled to wasm is much slower than native speed, significantly more so than than the equivalent slowdown for c/rust.

see https://github.com/golang/go/issues/65440

I believe this is still true. Originally you could store a compiled wasm module in IndexedDB and cache it manually, but that was removed in favor of {instantiate,compile}Streaming, which take a HTTP response and hook into the existing HTTP caching layer, which was already storing the compliation output for JS.

This is a fair point, but dropping the kernel patch guarantees that essentially nobody will use this.

Given part of the patch was software emulation for unsupported CPUs, it's possible that people would've implemented support for it anyway, incentivising Intel to push it more broadly.

VanillaJSX.com 2 years ago

Yup, in order to scale this approach to any real size (and still have confidence that everything is working together like you expect), a proper reactivity solution is needed.

For those that appreciate this approach of JSX returning concrete DOM elements, Solid works exactly like this, with the addition of a proper reactivity layer.

Rather than the "easy" way of porting an x86 emulator to WASM, I've been trying to natively port the Linux kernel to WASM.

UML[0] and LKL[1] prove that running the kernel in a process is viable. μClinux efforts like NOMMU and binfmt_flat prove that you don't need memory-management nor ELF to run the kernel.

Both my own independent experiments and WALI[2] have shown it's possible to port the Linux syscall interface and userland ecosystem to WASM.

I'm confident it's doable, but there are a number of other challenges to solve along the way (like dynamic linking, the Harvard architecture, etc). Currently I'm blocked on the fact that while the kernel supports running non-ELF binaries, it really wants to be an ELF itself.

[0] https://en.wikipedia.org/wiki/User-mode_Linux

[1] https://github.com/lkl/linux

[2] https://arxiv.org/abs/2312.03858

There don't seem to be many write-ups on this concept. The best reference seems to be existing implementations:

Wasmer's implementation of metering[0] just traps when it runs out of fuel. WasmEdge's implementation of interruptibility[1] checks a flag and stops execution if it's set.

While neither of these support resuming execution after the deadline, replacing the halt with a call to a signal dispatcher should work.

Wasmtime has two different implementations of interrupting execution that both support resuming[2]. The fuel mechanism[3] is deterministic but the epoch mechanism[4] is more performant. If you're free to pick your runtime, I'm sure you could configure Wasmtime into doing what you want.

[0] https://github.com/wasmerio/wasmer/blob/master/lib/middlewar...

[1] https://github.com/WasmEdge/WasmEdge/pull/910

[2] https://docs.rs/wasmtime/latest/wasmtime/struct.Config.html#...

[3] https://github.com/bytecodealliance/wasmtime/pull/2611

[4] https://github.com/bytecodealliance/wasmtime/pull/3699

I think the closest existing concept to signals is the gas/fuel mechanism implemented in some WebAssembly runtimes, used by WASM blockchain VMs to preempt untrusted code. Runtimes either instrument the JITed code to check a fuel counter in every function/loop, or they register a timer signal/interrupt that periodically checks the counter.

From a similar handler, you could check if a signal flag has been set, then call a user-defined signal handler exported from the module.

If you don't control the runtime, you could do this instrumentation to the bytecode rather than the generated machine code, effectively simulating preemption via injected yield points.