From 6cce37796f802c2bc7395032d4fbb9bad9297c68 Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Tue, 20 Dec 2022 11:04:02 -0800 Subject: [PATCH] test: add tests for pthread API This change runs the pthread tests available in `libc-test` when `THREAD_MODEL=posix`. This is currently a work-in-progress, since there are custom build steps necessary to get this all to (mostly) work. Currently this might look like: ```console $ cd test $ make run THREAD_MODEL=posix \ ENGINE=~/Code/wasmtime/target/debug/wasmtime CC=~/Code/llvm-project/build/bin/clang ``` What are the current issues? - this requires a special build of Wasmtime that includes the `wasi-threads` implementation; this is shown above as built from source - under `THREAD_MODEL=posix`, this requires Clang to understand the `--export-memory` flag which, though merged in https://reviews.llvm.org/D135898, is not available for download yet (but can be built from latest source as shown above) - not all of the tests yet pass and some do not build: this is to be expected in several cases (PI? robust?) but there is perhaps more that can be done here to enable more of the pthread API. Only the working tests are included in this commit. --- test/Makefile | 56 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 6 deletions(-) diff --git a/test/Makefile b/test/Makefile index 61e1756bc..7f99f627f 100644 --- a/test/Makefile +++ b/test/Makefile @@ -15,6 +15,10 @@ test: run # directory (keeping with the `wasi-libc` conventions). OBJDIR ?= $(CURDIR)/build DOWNDIR ?= $(CURDIR)/download +# Like the top-level `wasi-libc` Makefile, here we can decide whether to test +# with threads (`posix`) or without (`single`). IMPORTANT: the top-level include +# directory must be built with the same value. +THREAD_MODEL ?= single ##### DOWNLOAD ################################################################# @@ -90,6 +94,14 @@ TESTS := \ $(LIBC_TEST)/src/functional/wcsstr.c \ $(LIBC_TEST)/src/functional/wcstol.c +ifeq ($(THREAD_MODEL), posix) + TESTS += \ + $(LIBC_TEST)/src/functional/pthread_cond.c \ + $(LIBC_TEST)/src/functional/pthread_tsd.c \ + $(LIBC_TEST)/src/functional/tls_init.c \ + $(LIBC_TEST)/src/functional/tls_local_exec.c +endif + # Part of the problem including more tests is that the `libc-test` # infrastructure code is not all Wasm-compilable. As we include more tests # above, this list will also likely need to grow. @@ -116,23 +128,54 @@ ifeq ($(origin CC), default) CC := clang endif LDFLAGS ?= -CFLAGS ?= --target=wasm32-wasi --sysroot=../sysroot +CFLAGS ?= --sysroot=../sysroot # Always include the `libc-test` infrastructure headers. CFLAGS += -I$(LIBC_TEST)/src/common +# Configure support for threads. +ifeq ($(THREAD_MODEL), single) +CFLAGS += --target=wasm32-wasi -mthread-model single +endif +ifeq ($(THREAD_MODEL), posix) +# Specify the tls-model until LLVM 15 is released (which should contain +# https://reviews.llvm.org/D130053). +CFLAGS += --target=wasm32-wasi-pthread -mthread-model posix -pthread -ftls-model=local-exec +# NOTE: `--export-memory` is invalid until https://reviews.llvm.org/D135898 is +# available in a released version of `wasm-ld`; this has not happened yet so +# a built-from-latest-source Clang is necessary. +LDFLAGS += -Wl,--import-memory,--export-memory,--max-memory=1048576 +endif + +# We want to be careful to rebuild the Wasm files if any important variables +# change. This block calculates a hash from key variables and writes a file +# (ENV_HASH = `build/env-`); any targets dependent on `ENV_HASH` will thus +# be rebuilt whenever `ENV_HASH` is modified, which is whenever `ENV` changes. +# The phony `env` target can be used to debug this. +ENV = "CC=$(CC);CFLAGS=$(CFLAGS);LDFLAGS=$(LDFLAGS);THREAD_MODEL=$(THREAD_MODEL)" +export ENV +ENV_HASH = $(OBJDIR)/env-$(shell echo $(ENV) | md5sum | cut -d ' ' -f 1) +$(ENV_HASH): | $(OBJDIRS) + rm -f $(OBJDIR)/env-* + echo $(ENV) > $@ +env: $(ENV_HASH) + @echo ENV = "$$ENV" + @echo ENV_HASH = $(ENV_HASH) + cat $^ +.PHONY: env + # Compile each selected test using Clang. Note that failures here are likely # due to a missing `libclang_rt.builtins-wasm32.a` in the Clang lib directory. # This location is system-dependent, but could be fixed by something like: # $ sudo mkdir /usr/lib64/clang/14.0.5/lib/wasi # $ sudo cp download/lib/wasi/libclang_rt.builtins-wasm32.a /usr/lib64/clang/14.0.5/lib/wasi/ -build: download $(WASMS) +build: download $(WASMS) $(ENV_HASH) $(WASMS): | $(OBJDIRS) -$(OBJDIR)/%.wasm: $(OBJDIR)/%.wasm.o $(INFRA_WASM_OBJS) - $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ +$(OBJDIR)/%.wasm: $(OBJDIR)/%.wasm.o $(INFRA_WASM_OBJS) $(ENV_HASH) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(filter-out $(ENV_HASH), $^) $(WASM_OBJS): $(LIBC_TEST)/src/common/test.h | $(OBJDIRS) -$(OBJDIR)/%.wasm.o: $(LIBC_TEST)/src/%.c +$(OBJDIR)/%.wasm.o: $(LIBC_TEST)/src/%.c $(ENV_HASH) $(CC) $(CFLAGS) -c -o $@ $< $(OBJDIRS): @@ -144,6 +187,7 @@ clean:: ##### RUN ###################################################################### ENGINE ?= $(WASMTIME) run +ENGINE_FLAGS ?= --wasm-features threads --wasi-modules experimental-wasi-threads ERRS:=$(WASMS:%.wasm=%.wasm.err) # Use the provided Wasm engine to execute each test, emitting its output into @@ -154,7 +198,7 @@ run: build $(ERRS) $(ERRS): | $(OBJDIRS) %.wasm.err: %.wasm - $(ENGINE) $< >$@ + $(ENGINE) $(ENGINE_FLAGS) $< clean:: rm -rf $(OBJDIR)/*/*.err