From 49896cd35fdce7df9192c0e076d943a45f694b28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Sat, 9 Dec 2023 16:39:41 -0800 Subject: [PATCH 1/3] allocate maximum number of pages for shared memory --- w2c2/c.c | 2 +- w2c2/w2c2_base.h | 67 +++++++++++++++++++++++++++++------------------- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/w2c2/c.c b/w2c2/c.c index 22ebccf..66e053a 100644 --- a/w2c2/c.c +++ b/w2c2/c.c @@ -5378,7 +5378,7 @@ wasmCWriteInitMemories( fputs(indentation, file); } wasmCWriteFileMemoryUse(file, module, moduleMemoryIndex, NULL, true); - fprintf(file, " = wasmMemoryAllocate(%u, %u);\n", memory.min, memory.max); + fprintf(file, " = wasmMemoryAllocate(%u, %u, false);\n", memory.min, memory.max); } } } diff --git a/w2c2/w2c2_base.h b/w2c2/w2c2_base.h index 5ae6dc0..ea169bb 100644 --- a/w2c2/w2c2_base.h +++ b/w2c2/w2c2_base.h @@ -673,9 +673,10 @@ W2C2_INLINE wasmMemory* wasmMemoryAllocate( const U32 initialPages, - const U32 maxPages + const U32 maxPages, + const bool shared ) { - const U32 size = initialPages * WASM_PAGE_SIZE; + const U32 size = (shared ? maxPages : initialPages) * WASM_PAGE_SIZE; wasmMemory* memory = (wasmMemory*)calloc(1, sizeof(wasmMemory)); if (!memory) { abort(); @@ -684,34 +685,24 @@ wasmMemoryAllocate( memory->size = size; memory->pages = initialPages; memory->maxPages = maxPages; - memory->shared = false; + memory->shared = shared; memory->futex = NULL; memory->futexFree = NULL; - return memory; -} - -static -W2C2_INLINE -wasmMemory* -wasmMemoryAllocateShared( - const U32 initialPages, - const U32 maxPages -) { - wasmMemory* memory = wasmMemoryAllocate(initialPages, maxPages); - memory->shared = true; + if (shared) { #ifdef WASM_MUTEX_TYPE - if (!WASM_MUTEX_INIT(&memory->mutex)) { - abort(); - } + if (!WASM_MUTEX_INIT(&memory->mutex)) { + abort(); + } #else - abort(); + abort(); #endif + } return memory; } #ifdef WASM_MUTEX_TYPE #define WASM_MEMORY_ALLOCATE_SHARED(initialPages, maxPages) \ - wasmMemoryAllocateShared(initialPages, maxPages) + wasmMemoryAllocate(initialPages, maxPages, true) #else #define WASM_MEMORY_ALLOCATE_SHARED(initialPages, maxPages) \ (_Pragma ("GCC error \"Shared memory not supported. Please define a threads implementation to use (WASM_THREADS_*)\"") NULL) @@ -748,6 +739,8 @@ wasmMemoryGrow( wasmMemory* memory, const U32 delta ) { + bool doRealloc = true; + const U32 oldPages = memory->pages; const U32 newPages = memory->pages + delta; @@ -759,19 +752,39 @@ wasmMemoryGrow( return (U32) -1; } + if (memory->shared) { + doRealloc = false; +#ifdef WASM_MUTEX_TYPE + WASM_MUTEX_LOCK(&memory->mutex); +#else + abort(); +#endif + } + { - const U32 oldSize = oldPages * WASM_PAGE_SIZE; const U32 newSize = newPages * WASM_PAGE_SIZE; - const U32 deltaSize = delta * WASM_PAGE_SIZE; - U8* newData = (U8*)realloc(memory->data, newSize); - if (newData == NULL) { - return (U32) -1; + if (doRealloc) { + const U32 oldSize = oldPages * WASM_PAGE_SIZE; + const U32 deltaSize = delta * WASM_PAGE_SIZE; + U8* newData = (U8*)realloc(memory->data, newSize); + if (newData == NULL) { + return (U32) -1; + } + + memset(newData + oldSize, 0, deltaSize); + memory->data = newData; } - memset(newData + oldSize, 0, deltaSize); memory->pages = newPages; memory->size = newSize; - memory->data = newData; + } + + if (memory->shared) { +#ifdef WASM_MUTEX_TYPE + WASM_MUTEX_UNLOCK(&memory->mutex); +#else + abort(); +#endif } return oldPages; From 55edb586e5d891170918e170ff9fd501d5543f68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Sat, 9 Dec 2023 16:43:05 -0800 Subject: [PATCH 2/3] add pthreads example --- examples/pthreads/Makefile | 16 ++++++++++ examples/pthreads/main.c | 58 ++++++++++++++++++++++++++++++++++ examples/pthreads/src/Makefile | 8 +++++ examples/pthreads/src/main.c | 53 +++++++++++++++++++++++++++++++ examples/threads/Makefile | 2 +- 5 files changed, 136 insertions(+), 1 deletion(-) create mode 100755 examples/pthreads/Makefile create mode 100644 examples/pthreads/main.c create mode 100644 examples/pthreads/src/Makefile create mode 100644 examples/pthreads/src/main.c diff --git a/examples/pthreads/Makefile b/examples/pthreads/Makefile new file mode 100755 index 0000000..8fdec85 --- /dev/null +++ b/examples/pthreads/Makefile @@ -0,0 +1,16 @@ +LDFLAGS += -lm -L../../wasi -lw2c2wasi -L../../futex -lw2c2futex +CFLAGS += -O0 -g -DWASM_THREADS_PTHREADS +W2C2 ?= ../../w2c2/w2c2 + +pthreads: pthreads.o main.o + $(CC) $(CFLAGS) $^ -o pthreads $(LDFLAGS) + +%.c: src/%.wasm + $(W2C2) -g $< $@ + +%.o: %.c + $(CC) -I../../w2c2 -c $(CFLAGS) $< -o $@ + +.PHONY: clean +clean: + rm -f *.o pthreads pthreads.h diff --git a/examples/pthreads/main.c b/examples/pthreads/main.c new file mode 100644 index 0000000..102b7e2 --- /dev/null +++ b/examples/pthreads/main.c @@ -0,0 +1,58 @@ +#include +#include + +#include "w2c2_base.h" +#include "../../wasi/wasi.h" +#include "pthreads.h" + +void +trap( + Trap trap +) { + fprintf(stderr, "TRAP: %s\n", trapDescription(trap)); + abort(); +} + + +wasmMemory* +wasiMemory( + void* instance +) { + return pthreads_memory((pthreadsInstance*)instance); +} + +extern char** environ; + +wasmMemory* mem = NULL; + +void* resolveImport(const char* moduleName, const char* importName) { + if (strcmp(moduleName, "env") == 0 && strcmp(importName, "memory") == 0) { + return mem; + } + return NULL; +} + +int main(int argc, char** argv) { + pthreadsInstance instance; + + mem = WASM_MEMORY_ALLOCATE_SHARED(10, 20); + + pthreadsInstantiate(&instance, resolveImport); + + if (!wasiInit(argc, argv, environ)) { + fprintf(stderr, "failed to initialize WASI\n"); + return 1; + } + + if (!wasiFileDescriptorAdd(-1, "/", NULL)) { + fprintf(stderr, "failed to add preopen\n"); + return 1; + } + + + pthreads__start(&instance); + + pthreadsFreeInstance(&instance); + + return 0; +} diff --git a/examples/pthreads/src/Makefile b/examples/pthreads/src/Makefile new file mode 100644 index 0000000..970cb21 --- /dev/null +++ b/examples/pthreads/src/Makefile @@ -0,0 +1,8 @@ +CC = ${WASI_SDK_PATH}/bin/clang + +pthreads.wasm: main.c + $(CC) --target=wasm32-wasi-threads --sysroot ${WASI_SDK_PATH}/share/wasi-sysroot -O0 -g -pthread -Wl,--import-memory,--export-memory,--max-memory=67108864 -o $@ $< + +.PHONY: +clean: + rm pthreads.wasm diff --git a/examples/pthreads/src/main.c b/examples/pthreads/src/main.c new file mode 100644 index 0000000..7df3e15 --- /dev/null +++ b/examples/pthreads/src/main.c @@ -0,0 +1,53 @@ +#include +#include + +#define NUM_THREADS 4 +#define NUM_ITER 10 + +int g_count = 0; + +static void* thread(void *arg) { + printf("Entering thread\n"); + + for (int i = 0; i < NUM_ITER; i++) { + printf( + "Incremented counter: %d\n", + __atomic_add_fetch(&g_count, 1, __ATOMIC_SEQ_CST) + ); + } + + printf("Leaving thread\n"); + + return NULL; +} + +int main(int argc, char **argv) { + pthread_t tids[NUM_THREADS]; + + printf("Starting threads\n"); + + for (int i = 0; i < NUM_THREADS; i++) { + if (pthread_create(&tids[i], NULL, thread, NULL) != 0) { + printf("Thread creation failed\n"); + } + } + + printf("Joining threads\n"); + + for (int i = 0; i < NUM_THREADS; i++) { + if (pthread_join(tids[i], NULL) != 0) { + printf("Thread join failed\n"); + } + } + + printf( + "Value of counter after update: %d (expected=%d)\n", + g_count, + NUM_THREADS * NUM_ITER + ); + if (g_count != NUM_THREADS * NUM_ITER) { + __builtin_trap(); + } + + return 0; +} diff --git a/examples/threads/Makefile b/examples/threads/Makefile index d0dab3b..db8f4e3 100755 --- a/examples/threads/Makefile +++ b/examples/threads/Makefile @@ -9,7 +9,7 @@ else endif threads: threads.o main.o - $(CC) $^ -o threads $(LDFLAGS) + $(CC) $(CFLAGS) $^ -o threads $(LDFLAGS) %.c: src/%.wasm $(W2C2) -g $< $@ From 29cf6d73b54288a593b6313118f924d6ce112580 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Sat, 9 Dec 2023 16:59:00 -0800 Subject: [PATCH 3/3] fix wasmMemoryAllocate invocations --- futex/futex_test.c | 2 +- tests/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/futex/futex_test.c b/futex/futex_test.c index 84ba3c9..641ad6d 100644 --- a/futex/futex_test.c +++ b/futex/futex_test.c @@ -56,7 +56,7 @@ testFutex(void) { TestThreadArg arg3; TestThreadArg arg4; - mem = wasmMemoryAllocateShared(1, 1); + mem = wasmMemoryAllocate(1, 1, true); /* Three threads will wait on waitAddress1, * one thread will wait on waitAddress2. */ diff --git a/tests/main.c b/tests/main.c index a2a72d9..c616aee 100644 --- a/tests/main.c +++ b/tests/main.c @@ -117,7 +117,7 @@ void printOK(const char* description) { } static void initTest() { - spectest_memory = wasmMemoryAllocate(1, 2); + spectest_memory = wasmMemoryAllocate(1, 2, false); spectest_shared_memory = WASM_MEMORY_ALLOCATE_SHARED(1, 2); wasmTableAllocate(&spectest_table, 10, 20); }