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 threads extension #90

Merged
merged 39 commits into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
a78883d
start implementation of threads extension (atomic instructions)
turbolent Nov 12, 2023
d6f0616
add atomic test cases
turbolent Nov 12, 2023
a3b8c0c
implement atomic functions
turbolent Nov 13, 2023
2f1e4eb
add support for big-endian atomic load/stores
turbolent Nov 13, 2023
82aeddf
add big-endian support for atomic operations using memory mutex
turbolent Nov 14, 2023
5736183
link atomic where needed
turbolent Nov 16, 2023
8b55b6c
define mutex implementation by default
turbolent Nov 16, 2023
b23b5f4
link atomic for tests, not w2c2 itself
turbolent Nov 16, 2023
d1009f7
riscv64 needs atomic library on CI
turbolent Nov 16, 2023
1e6e81e
atomic RMW operations need mutex implementation
turbolent Nov 16, 2023
7cbed17
fix typo
turbolent Nov 16, 2023
e719ba9
add tests for bulk memory extension
turbolent Nov 25, 2023
919d1dd
fix reporting of unsupported misc opcode
turbolent Nov 25, 2023
55436f4
enable bulk memory extension for bulk memory tests
turbolent Nov 25, 2023
27107a0
clean up
turbolent Nov 25, 2023
a31b9c2
read memory index of memory.copy as leb128, just like for other instr…
turbolent Nov 25, 2023
cc3e76c
read (and omit) data count section
turbolent Nov 25, 2023
43f2c65
add support for reading passive data segments and data segments with …
turbolent Nov 25, 2023
61fa7d8
only add function name annotation if function is not exported
turbolent Nov 25, 2023
184f685
fix C++ support
turbolent Nov 25, 2023
d92d4af
record all exported functions in instance, to enable dynamic lookup/i…
turbolent Nov 25, 2023
65f1997
make memories pointers, so they can be shared across instances. imple…
turbolent Nov 25, 2023
e5b1c73
generate code for atomic memory wait and notify instructions
turbolent Nov 25, 2023
ce6f509
add new futex library which implements atomic memory wait and notify …
turbolent Nov 25, 2023
b65efc8
remove unnecessary memory allocation
turbolent Nov 25, 2023
cc7cab4
allow storing futex info in memory
turbolent Nov 25, 2023
809b1ae
add function to instantiate child of existing instance
turbolent Nov 25, 2023
24b1ab3
implement wasi.thread-spawn
turbolent Nov 25, 2023
836bad8
add threads example
turbolent Nov 25, 2023
67bab01
clean up
turbolent Nov 25, 2023
db08356
improve makefiles
turbolent Nov 25, 2023
e3c43c9
fix tests
turbolent Nov 25, 2023
4a62b37
build futex library, required for tests
turbolent Nov 25, 2023
75fb161
fix 32-bit support, clean up, fix C90 support
turbolent Nov 25, 2023
ea5ea5e
fix scoping
turbolent Nov 25, 2023
abc9982
link futex before atomic
turbolent Nov 26, 2023
9978886
i386 needs to link atomic
turbolent Nov 26, 2023
b7cabe5
add threads implementation for Windows
turbolent Nov 26, 2023
7f824e6
document new functionality
turbolent Nov 27, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 52 additions & 83 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,69 +23,82 @@ jobs:
build: [release, debug]
threads: [true, false]
system:
- { target: gcc, cc: gcc, }
- { target: clang, cc: clang, }
- { target: arm, toolchain: gcc-arm-linux-gnueabi, cc: arm-linux-gnueabi-gcc, qemu: qemu-arm-static }
- { target: armhf, toolchain: gcc-arm-linux-gnueabihf, cc: arm-linux-gnueabihf-gcc, qemu: qemu-arm-static }
- { target: aarch64, toolchain: gcc-aarch64-linux-gnu, cc: aarch64-linux-gnu-gcc, qemu: qemu-aarch64-static }
- { target: riscv64, toolchain: gcc-riscv64-linux-gnu, cc: riscv64-linux-gnu-gcc, qemu: qemu-riscv64-static }
- { target: ppc, toolchain: gcc-powerpc-linux-gnu, cc: powerpc-linux-gnu-gcc, qemu: qemu-ppc-static }
- { target: ppc64, toolchain: gcc-powerpc64-linux-gnu, cc: powerpc64-linux-gnu-gcc, qemu: qemu-ppc64-static }
- { target: s390x, toolchain: gcc-s390x-linux-gnu, cc: s390x-linux-gnu-gcc, qemu: qemu-s390x-static }
- { target: alpha, toolchain: gcc-alpha-linux-gnu, cc: alpha-linux-gnu-gcc, qemu: qemu-alpha-static }
- { target: gcc, cc: gcc }
- { target: clang, cc: clang }
- { target: arm, toolchain: gcc-arm-linux-gnueabi, cc: arm-linux-gnueabi-gcc, qemu: qemu-arm-static, linkAtomic: true }
- { target: armhf, toolchain: gcc-arm-linux-gnueabihf, cc: arm-linux-gnueabihf-gcc, qemu: qemu-arm-static }
- { target: aarch64, toolchain: gcc-aarch64-linux-gnu, cc: aarch64-linux-gnu-gcc, qemu: qemu-aarch64-static }
- { target: riscv64, toolchain: gcc-riscv64-linux-gnu, cc: riscv64-linux-gnu-gcc, qemu: qemu-riscv64-static, linkAtomic: true }
- { target: ppc, toolchain: gcc-powerpc-linux-gnu, cc: powerpc-linux-gnu-gcc, qemu: qemu-ppc-static, linkAtomic: true }
- { target: ppc64, toolchain: gcc-powerpc64-linux-gnu, cc: powerpc64-linux-gnu-gcc, qemu: qemu-ppc64-static }
- { target: s390x, toolchain: gcc-s390x-linux-gnu, cc: s390x-linux-gnu-gcc, qemu: qemu-s390x-static }
- { target: alpha, toolchain: gcc-alpha-linux-gnu, cc: alpha-linux-gnu-gcc, qemu: qemu-alpha-static }

# Architectures with expected failures (mostly due to FP issues, e.g. NaN representation, conversion, arithemtic)
- { target: i386, toolchain: gcc-multilib, cc: clang -m32, qemu: qemu-i386-static }
- { target: hppa, toolchain: gcc-hppa-linux-gnu, cc: hppa-linux-gnu-gcc, qemu: qemu-hppa-static }
- { target: mips, toolchain: gcc-mips-linux-gnu, cc: mips-linux-gnu-gcc, qemu: qemu-mips-static }
- { target: mipsel, toolchain: gcc-mipsel-linux-gnu, cc: mipsel-linux-gnu-gcc, qemu: qemu-mipsel-static }
- { target: mips64, toolchain: gcc-mips64-linux-gnuabi64, cc: mips64-linux-gnuabi64-gcc, qemu: qemu-mips64-static }
- { target: mips64el, toolchain: gcc-mips64el-linux-gnuabi64, cc: mips64el-linux-gnuabi64-gcc, qemu: qemu-mips64el-static }
- { target: ppc64le, toolchain: gcc-powerpc64le-linux-gnu, cc: powerpc64le-linux-gnu-gcc, qemu: qemu-ppc64le-static }
- { target: i386, toolchain: gcc-multilib, cc: clang -m32, qemu: qemu-i386-static, linkAtomic: true }
- { target: hppa, toolchain: gcc-hppa-linux-gnu, cc: hppa-linux-gnu-gcc, qemu: qemu-hppa-static }
- { target: mips, toolchain: gcc-mips-linux-gnu, cc: mips-linux-gnu-gcc, qemu: qemu-mips-static, linkAtomic: true }
- { target: mipsel, toolchain: gcc-mipsel-linux-gnu, cc: mipsel-linux-gnu-gcc, qemu: qemu-mipsel-static, linkAtomic: true }
- { target: mips64, toolchain: gcc-mips64-linux-gnuabi64, cc: mips64-linux-gnuabi64-gcc, qemu: qemu-mips64-static }
- { target: mips64el, toolchain: gcc-mips64el-linux-gnuabi64, cc: mips64el-linux-gnuabi64-gcc, qemu: qemu-mips64el-static }
- { target: ppc64le, toolchain: gcc-powerpc64le-linux-gnu, cc: powerpc64le-linux-gnu-gcc, qemu: qemu-ppc64le-static }

# Disabled due to miscompilation or qemu issues (?)
# - { target: sh4, toolchain: gcc-sh4-linux-gnu, cc: sh4-linux-gnu-gcc, qemu: qemu-sh4-static }
# - { target: sparc64, toolchain: gcc-sparc64-linux-gnu, cc: sparc64-linux-gnu-gcc, qemu: qemu-sparc64-static }
# - { target: sh4, toolchain: gcc-sh4-linux-gnu, cc: sh4-linux-gnu-gcc, qemu: qemu-sh4-static }
# - { target: sparc64, toolchain: gcc-sparc64-linux-gnu, cc: sparc64-linux-gnu-gcc, qemu: qemu-sparc64-static }

# Disabled due to too large `switch'-statement
# - { target: m68k, toolchain: gcc-m68k-linux-gnu, cc: m68k-linux-gnu-gcc, qemu: qemu-m68k-static }
# - { target: m68k, toolchain: gcc-m68k-linux-gnu, cc: m68k-linux-gnu-gcc, qemu: qemu-m68k-static }

env:
CC: ${{ matrix.system.cc }}

steps:
- uses: actions/checkout@v3

- name: Install QEMU
if: ${{ matrix.system.qemu }}
run: |
sudo apt update
sudo apt install qemu-user-static

- name: Install ${{ matrix.system.toolchain }}
if: ${{ matrix.system.toolchain }}
run: |
sudo apt install ${{ matrix.system.toolchain }}

- uses: dorny/paths-filter@v2
id: changes
with:
filters: |
w2c2:
- 'w2c2/**'
- 'futex/**'
- 'tests/**'
wasi:
- 'wasi/**'

- if: steps.changes.outputs.w2c2 == 'true'
name: Build w2c2
env:
LDFLAGS: -static
working-directory: ./w2c2
run: make BUILD=${{ matrix.build }} FEATURES="unistd libgen getopt glob ${{ matrix.threads && 'threads' || '' }}"

- if: steps.changes.outputs.w2c2 == 'true'
name: Build futex
working-directory: ./futex
run: make BUILD=${{ matrix.build }}

- if: steps.changes.outputs.w2c2 == 'true'
name: Run w2c2 tests
name: Run WebAssembly tests
env:
LDFLAGS: -static
LDFLAGS: -static ${{ matrix.system.linkAtomic && '-latomic' || '' }}
ARCH: ${{ matrix.system.target }}
working-directory: ./tests
shell: bash
run: make run-tests

- if: steps.changes.outputs.wasi == 'true'
name: Build wasi
working-directory: ./wasi
Expand All @@ -103,85 +116,40 @@ jobs:

steps:
- uses: actions/checkout@v3

- uses: dorny/paths-filter@v2
id: changes
with:
filters: |
w2c2:
- 'w2c2/**'
- 'futex/**'
- 'tests/**'
wasi:
- 'wasi/**'

- if: steps.changes.outputs.w2c2 == 'true'
name: Build w2c2
working-directory: ./w2c2
run: make BUILD=${{ matrix.build }} FEATURES="unistd libgen getopt glob ${{ matrix.threads && 'threads' || '' }}"

- if: steps.changes.outputs.w2c2 == 'true'
name: Run tests
working-directory: ./tests
shell: bash
name: Build futex
working-directory: ./futex
run: make BUILD=${{ matrix.build }}

- if: steps.changes.outputs.w2c2 == 'true'
name: Run WebAssembly tests
env:
ARCH: ${{ matrix.system.target }}
working-directory: ./tests
shell: bash
run: make run-tests

- if: steps.changes.outputs.wasi == 'true'
name: Build wasi
working-directory: ./wasi
run: make BUILD=${{ matrix.build }} FEATURES="unistd sysuio systime sysresource strndup fcntl timespec lstat"

# Disabled due to sqrt issues
#
# windows-mingw:
# runs-on: windows-latest
# name: "Windows (mingw), ${{ matrix.system.target }} (build=${{ matrix.build }}, threads=${{ matrix.threads }})"
#
# strategy:
# fail-fast: false
# matrix:
# build: [release, debug]
# threads: [true, false]
# system:
# - { target: mingw64, env: x86_64 }
# - { target: mingw32, env: i686 }
#
# defaults:
# run:
# shell: msys2 {0}
#
# env:
# CC: gcc
#
# steps:
# - uses: actions/checkout@v3
# - uses: msys2/setup-msys2@v2
# with:
# msystem: ${{ matrix.system.target }}
# install: >-
# make
# gcc
# - uses: dorny/paths-filter@v2
# id: changes
# with:
# filters: |
# w2c2:
# - 'w2c2/**'
# wasi:
# - 'wasi/**'
# - if: steps.changes.outputs.w2c2 == 'true'
# name: Build w2c2
# env:
# LDFLAGS: -static
# working-directory: ./w2c2
# run: make BUILD=${{ matrix.build }} FEATURES="getopt ${{ matrix.threads && 'threads' || '' }}"
# - if: steps.changes.outputs.w2c2 == 'true'
# name: Run tests
# working-directory: ./tests
# shell: bash
# env:
# ARCH: ${{ matrix.system.target }}
# run: make run-tests
# - if: steps.changes.outputs.wasi == 'true'
# name: Build wasi
# working-directory: ./wasi
# run: make BUILD=${{ matrix.build }}
run: make BUILD=${{ matrix.build }} FEATURES="unistd sysuio systime sysresource strndup fcntl timespec lstat pthreads"

windows-msvc:
runs-on: windows-2019
Expand All @@ -197,13 +165,14 @@ jobs:
- 'w2c2/**'
wasi:
- 'wasi/**'

- if: steps.changes.outputs.w2c2 == 'true'
name: Build w2c2
working-directory: ./w2c2
run: |
cmake -Bbuild
cmake --build build
# TODO: run tests

- if: steps.changes.outputs.wasi == 'true'
name: Build wasi
working-directory: ./wasi
Expand Down
101 changes: 54 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@ Working towards [WebAssembly as the Elusive Universal Binary](https://kripken.gi

## Features

- Implements the [WebAssembly Core Specification 1.0](https://www.w3.org/TR/wasm-core-1/), as well as
- Implements the [WebAssembly Core Specification 1.0](https://www.w3.org/TR/wasm-core-1/)
- Implements several extensions:
- [Threads and atomics](https://github.com/WebAssembly/threads/blob/master/proposals/threads/Overview.md)
- [Bulk memory operations](https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md)
- [Conditional data segment initialization](https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md)
- [Sign-extension operators](https://github.com/WebAssembly/sign-extension-ops/blob/master/proposals/sign-extension-ops/Overview.md)
- [Non-trapping Float-to-int Conversions](https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/main/proposals/nontrapping-float-to-int-conversion/Overview.md)
- [Non-trapping float-to-int conversions](https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/main/proposals/nontrapping-float-to-int-conversion/Overview.md)
- Passes 99.9% of the WebAssembly core semantics test suite
- Written in C89 and generates C89
- Support for many operating systems (e.g. Mac OS X, Mac OS 9, Haiku, Rhapsody, OPENSTEP, NeXTSTEP, DOS, Windows XP, etc.)
Expand All @@ -35,7 +38,10 @@ Working towards [WebAssembly as the Elusive Universal Binary](https://kripken.gi
- Function names, if function names are provided in the [`names` custom section](https://webassembly.github.io/spec/core/appendix/custom.html#function-names)
- Source line mapping, if DWARF line information is provided in the [`.debug_line` custom section](https://yurydelendik.github.io/webassembly-dwarf/).
Requires [libdwarf](https://github.com/davea42/libdwarf-code) to be installed. See instructions below.
- WASI implementation which is able to run clang and Python
- WASI implementation
- Able to run clang and Python
- Support for many operating systems and architectures, support for big-endian systems
- Implements the [threads proposal](https://github.com/webAssembly/wasi-threads)

## Performance

Expand Down Expand Up @@ -116,50 +122,51 @@ make run-tests

## WASI Status

- [x] args_get
- [x] args_sizes_get
- [x] clock_res_get
- [x] clock_time_get
- [x] environ_get
- [x] environ_sizes_get
- [ ] fd_advise
- [ ] fd_allocate
- [x] fd_close
- [x] fd_datasync
- [x] fd_fdstat_get
- [ ] fd_fdstat_set_flags
- [ ] fd_fdstat_set_rights
- [x] fd_filestat_get
- [ ] fd_filestat_set_size
- [ ] fd_filestat_set_times
- [x] fd_pread
- [x] fd_prestat_get
- [x] fd_prestat_dir_name
- [x] fd_pwrite
- [x] fd_read
- [x] fd_readdir
- [ ] fd_renumber
- [x] fd_seek
- [x] fd_sync
- [x] fd_tell
- [x] fd_write
- [x] path_create_directory
- [x] path_filestat_get
- [ ] path_filestat_set_times
- [ ] path_link
- [x] path_open
- [x] path_readlink
- [x] path_remove_directory
- [x] path_rename
- [x] path_symlink
- [x] path_unlink_file
- [ ] poll_oneoff
- [x] proc_exit
- [x] random_get
- [ ] sched_yield
- [ ] sock_recv
- [ ] sock_send
- [ ] sock_shutdown
- [x] `args_get`
- [x] `args_sizes_get`
- [x] `clock_res_get`
- [x] `clock_time_get`
- [x] `environ_get`
- [x] `environ_sizes_get`
- [ ] `fd_advise`
- [ ] `fd_allocate`
- [x] `fd_close`
- [x] `fd_datasync`
- [x] `fd_fdstat_get`
- [ ] `fd_fdstat_set_flags`
- [ ] `fd_fdstat_set_rights`
- [x] `fd_filestat_get`
- [ ] `fd_filestat_set_size`
- [ ] `fd_filestat_set_times`
- [x] `fd_pread`
- [x] `fd_prestat_get`
- [x] `fd_prestat_dir_name`
- [x] `fd_pwrite`
- [x] `fd_read`
- [x] `fd_readdir`
- [ ] `fd_renumber`
- [x] `fd_seek`
- [x] `fd_sync`
- [x] `fd_tell`
- [x] `fd_write`
- [x] `path_create_directory`
- [x] `path_filestat_get`
- [ ] `path_filestat_set_times`
- [ ] `path_link`
- [x] `path_open`
- [x] `path_readlink`
- [x] `path_remove_directory`
- [x] `path_rename`
- [x] `path_symlink`
- [x] `path_unlink_file`
- [ ] `poll_oneoff`
- [x] `proc_exit`
- [x] `random_get`
- [ ] `sched_yield`
- [ ] `sock_recv`
- [ ] `sock_send`
- [ ] `sock_shutdown`
- [x] `thread-spawn` (from the [threads proposal](https://github.com/webAssembly/wasi-threads))

## Development

Expand Down
22 changes: 22 additions & 0 deletions examples/threads/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
LDFLAGS += -lm -L../../wasi -lw2c2wasi -L../../futex -lw2c2futex
CFLAGS += -O0 -g
W2C2 ?= ../../w2c2/w2c2

ifeq ($(OS),Windows_NT)
CFLAGS += -DWASM_THREADS_WIN32
else
CFLAGS += -pthread -DWASM_THREADS_PTHREADS
endif

threads: threads.o main.o
$(CC) $^ -o threads $(LDFLAGS)

%.c: src/%.wasm
$(W2C2) -g $< $@

%.o: %.c
$(CC) -I../../w2c2 -c $(CFLAGS) $< -o $@

.PHONY: clean
clean:
rm -f *.o threads threads.h
Loading
Loading