Skip to content

Commit

Permalink
Merge pull request #91 from turbolent/improve-shared-memory
Browse files Browse the repository at this point in the history
  • Loading branch information
turbolent committed Dec 10, 2023
2 parents 29ac02a + 29cf6d7 commit 65e039c
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 31 deletions.
16 changes: 16 additions & 0 deletions examples/pthreads/Makefile
Original file line number Diff line number Diff line change
@@ -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
58 changes: 58 additions & 0 deletions examples/pthreads/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#include <stdlib.h>
#include <stdio.h>

#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;
}
8 changes: 8 additions & 0 deletions examples/pthreads/src/Makefile
Original file line number Diff line number Diff line change
@@ -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
53 changes: 53 additions & 0 deletions examples/pthreads/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include <stdio.h>
#include <pthread.h>

#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;
}
2 changes: 1 addition & 1 deletion examples/threads/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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 $< $@
Expand Down
2 changes: 1 addition & 1 deletion futex/futex_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
2 changes: 1 addition & 1 deletion tests/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion w2c2/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down
67 changes: 40 additions & 27 deletions w2c2/w2c2_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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)
Expand Down Expand Up @@ -748,6 +739,8 @@ wasmMemoryGrow(
wasmMemory* memory,
const U32 delta
) {
bool doRealloc = true;

const U32 oldPages = memory->pages;
const U32 newPages = memory->pages + delta;

Expand All @@ -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;
Expand Down

0 comments on commit 65e039c

Please sign in to comment.