Skip to content
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

implement a webassembly allocator that handles multi-threading #22807

Open
chung-leong opened this issue Feb 7, 2025 · 2 comments
Open

implement a webassembly allocator that handles multi-threading #22807

chung-leong opened this issue Feb 7, 2025 · 2 comments
Labels
contributor friendly This issue is limited in scope and/or knowledge of Zig internals. enhancement Solving this issue will likely involve adding new logic or components to the codebase. os-wasi standard library This issue involves writing Zig code for the standard library.
Milestone

Comments

@chung-leong
Copy link

Zig Version

0.14.0-dev.3050+d72f3d353

Steps to Reproduce and Observed Behavior

Ever since this commit wasi threads have basically been disabled since we can't create an allocator.

We can make the WasAllocator thread-safe simply by adding a spinlock:

var spinlock = false;

fn acquireLock() void {
    if (!builtin.single_threaded) {
        while (@cmpxchgWeak(bool, &spinlock, false, true, .acquire, .monotonic) != null) {}
    }
}

fn releaseLock() void {
    if (!builtin.single_threaded) {
        @atomicStore(bool, &spinlock, false, .release);
    }
}

fn alloc(ctx: *anyopaque, len: usize, log2_align: u8, return_address: usize) ?[*]u8 {
    _ = ctx;
    _ = return_address;
    acquireLock();
    defer releaseLock();
    // ...
}

fn free(
    ctx: *anyopaque,
    buf: []u8,
    log2_buf_align: u8,
    return_address: usize,
) void {
    _ = ctx;
    _ = return_address;
    acquireLock();
    defer releaseLock();
    // ...
}

That should protect the allocator state from concurrent modifications. Mutex cannot be used here since the main thread of browsers doesn't allow synchronous wait.

I've put together a demo showing the spinlock approach in the browser. With 16 threads continually allocating and freeing, 100 alloc/free by the main thread doesn't seem to block for too long. The UI remains responsive, which is really the main concern.

It'll be great if we can have functional WebAssembly threads in 0.14.0. Convenient way to show people what Zig is capable of.

Expected Behavior

No comptime error.

@chung-leong chung-leong added the bug Observed behavior contradicts documented or intended behavior label Feb 7, 2025
@andrewrk andrewrk added enhancement Solving this issue will likely involve adding new logic or components to the codebase. standard library This issue involves writing Zig code for the standard library. os-wasi and removed bug Observed behavior contradicts documented or intended behavior labels Feb 7, 2025
@andrewrk andrewrk added this to the 0.15.0 milestone Feb 7, 2025
@andrewrk
Copy link
Member

andrewrk commented Feb 7, 2025

This is not a bug, it is a feature request. That allocator never worked under multithreaded conditions.

I will not accept a spinlock-based solution.

@andrewrk andrewrk added the contributor friendly This issue is limited in scope and/or knowledge of Zig internals. label Feb 7, 2025
@andrewrk andrewrk changed the title WasmAllocator throws error when builtin.single_threaded = false implement a webassembly allocator that handles multi-threading Feb 7, 2025
@chung-leong
Copy link
Author

Would a solution where only the main thread spins be acceptable? Then amount of spinning can be minimized by giving the main thread priority over other threads.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contributor friendly This issue is limited in scope and/or knowledge of Zig internals. enhancement Solving this issue will likely involve adding new logic or components to the codebase. os-wasi standard library This issue involves writing Zig code for the standard library.
Projects
None yet
Development

No branches or pull requests

2 participants