Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 11 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,23 @@ endif
all: hello sieve itersum treesum

.PHONY: hello
hello: hello_asyncify.wasm hello_wasmfx.wasm
hello: hello_asyncify.wasm hello_asyncify_switch.wasm racecar.wasm hello_wasmfx.wasm

hello_asyncify.wasm: inc/fiber.h src/asyncify/asyncify_impl.c examples/hello.c
$(WASICC) -DSTACK_POOL_SIZE=$(STACK_POOL_SIZE) -DASYNCIFY_DEFAULT_STACK_SIZE=$(ASYNCIFY_DEFAULT_STACK_SIZE) src/asyncify/asyncify_impl.c $(WASIFLAGS) examples/hello.c -o hello_asyncfiy.pre.wasm
$(ASYNCIFY) hello_asyncfiy.pre.wasm -o hello_asyncify.wasm
chmod +x hello_asyncify.wasm

hello_asyncify_switch.wasm: inc/fiber_switch.h src/asyncify/asyncify_switch_impl.c examples/hello_switch.c
$(WASICC) -DSTACK_POOL_SIZE=$(STACK_POOL_SIZE) -DASYNCIFY_DEFAULT_STACK_SIZE=$(ASYNCIFY_DEFAULT_STACK_SIZE) src/asyncify/asyncify_switch_impl.c $(WASIFLAGS) examples/hello_switch.c -o hello_asyncfiy_switch.pre.wasm
$(ASYNCIFY) hello_asyncfiy_switch.pre.wasm -o hello_asyncify_switch.wasm
chmod +x hello_asyncify_switch.wasm

racecar.wasm: inc/fiber_switch.h src/asyncify/asyncify_switch_impl.c examples/racecar.c
$(WASICC) -DSTACK_POOL_SIZE=$(STACK_POOL_SIZE) -DASYNCIFY_DEFAULT_STACK_SIZE=$(ASYNCIFY_DEFAULT_STACK_SIZE) src/asyncify/asyncify_switch_impl.c $(WASIFLAGS) examples/racecar.c -o racecar.pre.wasm
$(ASYNCIFY) racecar.pre.wasm -o racecar.wasm
chmod +x racecar.wasm

hello_wasmfx.wasm: inc/fiber.h src/wasmfx/imports.wat src/wasmfx/wasmfx_impl.c examples/hello.c
$(WASICC) $(SHADOW_STACK_FLAG) -DWASMFX_CONT_SHADOW_STACK_SIZE=$(WASMFX_CONT_SHADOW_STACK_SIZE) -DWASMFX_CONT_TABLE_INITIAL_CAPACITY=$(WASMFX_CONT_TABLE_INITIAL_CAPACITY) -Wl,--export-table,--export-memory,--export=__stack_pointer src/wasmfx/wasmfx_impl.c $(WASIFLAGS) examples/hello.c -o hello_wasmfx.pre.wasm
$(WASM_INTERP) -d -i src/wasmfx/imports.wat -o fiber_wasmfx_imports.wasm
Expand Down
74 changes: 74 additions & 0 deletions examples/hello_switch.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Cooperative printing of "hello world"
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fiber_switch.h>

static fiber_t hello_fiber;
static fiber_t world_fiber;

static bool hello_done;
static bool world_done;


void* hello(void *arg, fiber_t main_fiber) {
uint32_t i = (uint32_t)(uintptr_t)arg;

static const char s[] = "hlowrd";

do {
putc(s[i], stdout);
i = (uint32_t)(uintptr_t)fiber_switch(world_fiber, (void*)(uintptr_t)i, &hello_fiber);
} while (!world_done && world_fiber != NULL);

hello_done = true;
fiber_return_switch(main_fiber, (void*)(uintptr_t)i);
return NULL;
}

void* world(void *arg, fiber_t __attribute__((unused))main_fiber) {
uint32_t i = (uint32_t)(uintptr_t)arg;
static const char s[] = "el ol";

do {
putc(s[i], stdout);
i++;
i = (uint32_t)(uintptr_t)fiber_switch(hello_fiber, (void*)(uintptr_t)i, &world_fiber);
} while (i < strlen(s));

world_done = true;
fiber_switch(hello_fiber, (void*)(uintptr_t)i, &world_fiber);
return NULL;
}

void *prog(void * __attribute__((unused))result, fiber_t dummy) {

hello_fiber = fiber_alloc((fiber_entry_point_t)hello);
world_fiber = fiber_alloc((fiber_entry_point_t)world);

hello_done = false;
world_done = false;

uint32_t i = 0;

// Initial switch must be from *some* fiber, so we use dummy.
(void)fiber_switch(hello_fiber, (void*)(uintptr_t)i, &dummy);

putc('\n', stdout);
fflush(stdout);

fiber_free(hello_fiber);
fiber_free(world_fiber);

return NULL;
}

int main(int __attribute__((unused)) argc, char * __attribute__((unused))argv[]) {

void *result = fiber_main(prog, NULL);

return (int)(intptr_t)result;
}
65 changes: 65 additions & 0 deletions examples/racecar.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Cooperative printing of "racecar"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fiber_switch.h>

static volatile fiber_t main_fiber;
static volatile fiber_t rr;
static volatile fiber_t cc;
static volatile fiber_t aa;
static volatile fiber_t e;

void* rr_func(void *__attribute__((unused))arg, fiber_t main_fiber) {
putc('r', stdout);
fiber_switch(aa, NULL, &rr);
putc('r', stdout);
fiber_return_switch(main_fiber, NULL);
return NULL;
}

void* aa_func(void *__attribute__((unused))arg, fiber_t __attribute__((unused))dummy) {
putc('a', stdout);
fiber_switch(cc, NULL, &aa);
putc('a', stdout);
fiber_return_switch(rr, NULL);
return NULL;
}

void* cc_func(void *__attribute__((unused))arg, fiber_t __attribute__((unused))dummy) {
putc('c', stdout);
fiber_switch(e, NULL, &cc);
putc('c', stdout);
fiber_return_switch(aa, NULL);
return NULL;
}

void* e_func(void *__attribute__((unused))arg, fiber_t __attribute__((unused))dummy) {
putc('e', stdout);
fiber_return_switch(cc, NULL);
return NULL;
}

void *prog(void * __attribute__((unused))result, fiber_t __attribute__((unused))dummy) {

rr = fiber_alloc(rr_func);
aa = fiber_alloc(aa_func);
cc = fiber_alloc(cc_func);
e = fiber_alloc(e_func);

(void)fiber_switch(rr, NULL, &main_fiber);

putc('\n', stdout);
fflush(stdout);

return NULL;
}

int main(int __attribute__((unused)) argc, char * __attribute__((unused))argv[]) {

void *result = fiber_main(prog, NULL);

return (int)(intptr_t)result;
}
48 changes: 48 additions & 0 deletions inc/fiber_switch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/** A basic fiber interface. **/
#ifndef WASMFX_FIBER_C_H
#define WASMFX_FIBER_C_H

#define export(NAME) __attribute__((export_name(NAME)))

/** The abstract type of a fiber object. **/
typedef struct fiber* fiber_t;

/** The signature of a fiber entry point. **/
/** take void* void* instead?
* first pointer: argument in switch
* second pointer: switched_from fiber_t
*/
typedef void* (*fiber_entry_point_t)(void*, fiber_t);

/** Allocates a new fiber with the default stack size. **/
export("fiber_alloc")
fiber_t fiber_alloc(fiber_entry_point_t entry);

/** Reclaims the memory occupied by the fiber object. **/
export("fiber_free")
void fiber_free(fiber_t fiber);


/** Possible status codes for `fiber_switch`. **/
typedef enum { FIBER_OK = 0, FIBER_SWITCH = 1, FIBER_ERROR = 2 } fiber_result_t;


/** Switches to a given `fiber` with argument `arg`, returning some value
of type `void*`. The output parameter `status` indicates whether
the fiber ran to completion (`FIBER_OK`), yielded control
(`FIBER_YIELD`), or failed (`FIBER_ERROR`), in the latter case the
return value will be undefined. **/
export("fiber_switch")
void* fiber_switch(fiber_t fiber, void *arg, volatile fiber_t *switched_from);

/** Switches to `target` and destroys currently executing `fiber`. **/
// todo: attribute no return
export("fiber_return_switch")
void fiber_return_switch(fiber_t target, void *arg);

/** Runs the provided `main` function in a fiber context. **/
export("fiber_main")
void *fiber_main(void *(*main)(void*,fiber_t), void* arg);

#undef export
#endif
Loading