Path: blob/main/examples/min-platform/embedding/wasmtime-platform.c
2450 views
#include <assert.h>1#include <errno.h>2#include <signal.h>3#include <string.h>4#include <sys/mman.h>5#include <sys/ucontext.h>6#include <unistd.h>78#include "wasmtime-platform.h"910#ifdef WASMTIME_VIRTUAL_MEMORY1112static int wasmtime_to_mmap_prot_flags(uint32_t prot_flags) {13int flags = 0;14if (prot_flags & WASMTIME_PROT_READ)15flags |= PROT_READ;16if (prot_flags & WASMTIME_PROT_WRITE)17flags |= PROT_WRITE;18if (prot_flags & WASMTIME_PROT_EXEC)19flags |= PROT_EXEC;20return flags;21}2223int wasmtime_mmap_new(uintptr_t size, uint32_t prot_flags, uint8_t **ret) {24void *rc = mmap(NULL, size, wasmtime_to_mmap_prot_flags(prot_flags),25MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);26if (rc == MAP_FAILED)27return errno;28*ret = rc;29return 0;30}3132int wasmtime_mmap_remap(uint8_t *addr, uintptr_t size, uint32_t prot_flags) {33void *rc = mmap(addr, size, wasmtime_to_mmap_prot_flags(prot_flags),34MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);35if (rc == MAP_FAILED)36return errno;37return 0;38}3940int wasmtime_munmap(uint8_t *ptr, uintptr_t size) {41int rc = munmap(ptr, size);42if (rc != 0)43return errno;44return 0;45}4647int wasmtime_mprotect(uint8_t *ptr, uintptr_t size, uint32_t prot_flags) {48int rc = mprotect(ptr, size, wasmtime_to_mmap_prot_flags(prot_flags));49if (rc != 0)50return errno;51return 0;52}5354uintptr_t wasmtime_page_size(void) { return sysconf(_SC_PAGESIZE); }5556#endif // WASMTIME_VIRTUAL_MEMORY5758#ifdef WASMTIME_NATIVE_SIGNALS5960static wasmtime_trap_handler_t g_handler = NULL;6162static void handle_signal(int signo, siginfo_t *info, void *context) {63assert(g_handler != NULL);64uintptr_t ip, fp;65#if defined(__aarch64__)66ucontext_t *cx = context;67ip = cx->uc_mcontext.pc;68fp = cx->uc_mcontext.regs[29];69#elif defined(__x86_64__)70ucontext_t *cx = context;71ip = cx->uc_mcontext.gregs[REG_RIP];72fp = cx->uc_mcontext.gregs[REG_RBP];73#else74#error "Unsupported platform"75#endif7677bool has_faulting_addr = signo == SIGSEGV;78uintptr_t faulting_addr = 0;79if (has_faulting_addr)80faulting_addr = (uintptr_t)info->si_addr;81g_handler(ip, fp, has_faulting_addr, faulting_addr);8283// If wasmtime didn't handle this trap then reset the handler to the default84// behavior which will probably abort the process.85signal(signo, SIG_DFL);86}8788int wasmtime_init_traps(wasmtime_trap_handler_t handler) {89int rc;90g_handler = handler;9192struct sigaction action;93memset(&action, 0, sizeof(action));9495action.sa_sigaction = handle_signal;96action.sa_flags = SA_SIGINFO | SA_NODEFER;97sigemptyset(&action.sa_mask);9899rc = sigaction(SIGILL, &action, NULL);100if (rc != 0)101return errno;102rc = sigaction(SIGSEGV, &action, NULL);103if (rc != 0)104return errno;105rc = sigaction(SIGFPE, &action, NULL);106if (rc != 0)107return errno;108return 0;109}110111#endif // WASMTIME_NATIVE_SIGNALS112113#ifdef WASMTIME_VIRTUAL_MEMORY114115int wasmtime_memory_image_new(const uint8_t *ptr, uintptr_t len,116struct wasmtime_memory_image **ret) {117*ret = NULL;118return 0;119}120121int wasmtime_memory_image_map_at(struct wasmtime_memory_image *image,122uint8_t *addr, uintptr_t len) {123abort();124}125126void wasmtime_memory_image_free(struct wasmtime_memory_image *image) {127abort();128}129130#endif // WASMTIME_VIRTUAL_MEMORY131132#ifdef WASMTIME_CUSTOM_SYNC133134// Multi-threaded TLS using pthread135#include <pthread.h>136137static pthread_key_t wasmtime_tls_key;138static pthread_once_t wasmtime_tls_key_once = PTHREAD_ONCE_INIT;139140static void make_tls_key(void) { pthread_key_create(&wasmtime_tls_key, NULL); }141142uint8_t *wasmtime_tls_get(void) {143pthread_once(&wasmtime_tls_key_once, make_tls_key);144return (uint8_t *)pthread_getspecific(wasmtime_tls_key);145}146147void wasmtime_tls_set(uint8_t *val) {148pthread_once(&wasmtime_tls_key_once, make_tls_key);149pthread_setspecific(wasmtime_tls_key, val);150}151152#else153154// Single-threaded TLS using a static variable155static uint8_t *WASMTIME_TLS = NULL;156157uint8_t *wasmtime_tls_get(void) { return WASMTIME_TLS; }158159void wasmtime_tls_set(uint8_t *val) { WASMTIME_TLS = val; }160161#endif162163#ifdef WASMTIME_CUSTOM_SYNC164165#include <stdlib.h>166167void wasmtime_sync_lock_free(uintptr_t *lock) {168if (*lock != 0) {169pthread_mutex_t *mutex = (pthread_mutex_t *)*lock;170pthread_mutex_destroy(mutex);171free(mutex);172*lock = 0;173}174}175176static pthread_mutex_t *mutex_lazy_init(uintptr_t *lock) {177pthread_mutex_t *mutex = (pthread_mutex_t *)*lock;178if (mutex == NULL) {179pthread_mutex_t *new_mutex = malloc(sizeof(pthread_mutex_t));180if (new_mutex == NULL) {181abort();182}183pthread_mutex_init(new_mutex, NULL);184185// Atomically set lock only if it's still NULL186if (!__sync_bool_compare_and_swap(lock, 0, (uintptr_t)new_mutex)) {187pthread_mutex_destroy(new_mutex);188free(new_mutex);189}190mutex = (pthread_mutex_t *)*lock;191}192return mutex;193}194195void wasmtime_sync_lock_acquire(uintptr_t *lock) {196pthread_mutex_t *mutex = mutex_lazy_init(lock);197pthread_mutex_lock(mutex);198}199200void wasmtime_sync_lock_release(uintptr_t *lock) {201pthread_mutex_t *mutex = mutex_lazy_init(lock);202pthread_mutex_unlock(mutex);203}204205void wasmtime_sync_rwlock_free(uintptr_t *lock) {206if (*lock != 0) {207pthread_rwlock_t *rwlock = (pthread_rwlock_t *)*lock;208pthread_rwlock_destroy(rwlock);209free(rwlock);210*lock = 0;211}212}213214static pthread_rwlock_t *rwlock_lazy_init(uintptr_t *lock) {215pthread_rwlock_t *rwlock = (pthread_rwlock_t *)*lock;216if (rwlock == NULL) {217pthread_rwlock_t *new_rwlock = malloc(sizeof(pthread_rwlock_t));218if (new_rwlock == NULL) {219abort();220}221pthread_rwlock_init(new_rwlock, NULL);222223// Atomically set lock only if it's still NULL224if (!__sync_bool_compare_and_swap(lock, 0, (uintptr_t)new_rwlock)) {225// Another thread won the race, discard our allocation226pthread_rwlock_destroy(new_rwlock);227free(new_rwlock);228}229rwlock = (pthread_rwlock_t *)*lock;230}231return rwlock;232}233234void wasmtime_sync_rwlock_read(uintptr_t *lock) {235pthread_rwlock_t *rwlock = rwlock_lazy_init(lock);236pthread_rwlock_rdlock(rwlock);237}238239void wasmtime_sync_rwlock_read_release(uintptr_t *lock) {240pthread_rwlock_t *rwlock = rwlock_lazy_init(lock);241pthread_rwlock_unlock(rwlock);242}243244void wasmtime_sync_rwlock_write(uintptr_t *lock) {245pthread_rwlock_t *rwlock = rwlock_lazy_init(lock);246pthread_rwlock_wrlock(rwlock);247}248249void wasmtime_sync_rwlock_write_release(uintptr_t *lock) {250pthread_rwlock_t *rwlock = rwlock_lazy_init(lock);251pthread_rwlock_unlock(rwlock);252}253254#endif // WASMTIME_CUSTOM_SYNC255256257