/*
* Copyright 2018 WebAssembly Community Group participants
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "wasm-rt-impl.h"
#include <assert.h>
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/mman.h>
#endif
#define WASM_PAGE_SIZE 65536
#ifdef WASM_RT_GROW_FAILED_HANDLER
extern void WASM_RT_GROW_FAILED_HANDLER();
#endif
#define C11_MEMORY_LOCK_VAR_INIT(name) \
if (mtx_init(&(name), mtx_plain) != thrd_success) { \
fprintf(stderr,
"Lock init failed\n"); \
abort(); \
}
#define C11_MEMORY_LOCK_AQUIRE(name) \
if (mtx_lock(&(name)) != thrd_success) { \
fprintf(stderr,
"Lock acquire failed\n"); \
abort(); \
}
#define C11_MEMORY_LOCK_RELEASE(name) \
if (mtx_unlock(&(name)) != thrd_success) { \
fprintf(stderr,
"Lock release failed\n"); \
abort(); \
}
#define PTHREAD_MEMORY_LOCK_VAR_INIT(name) \
if (pthread_mutex_init(&(name), NULL) != 0) { \
fprintf(stderr,
"Lock init failed\n"); \
abort(); \
}
#define PTHREAD_MEMORY_LOCK_AQUIRE(name) \
if (pthread_mutex_lock(&(name)) != 0) { \
fprintf(stderr,
"Lock acquire failed\n"); \
abort(); \
}
#define PTHREAD_MEMORY_LOCK_RELEASE(name) \
if (pthread_mutex_unlock(&(name)) != 0) { \
fprintf(stderr,
"Lock release failed\n"); \
abort(); \
}
#define WIN_MEMORY_LOCK_VAR_INIT(name) InitializeCriticalSection(&(name))
#define WIN_MEMORY_LOCK_AQUIRE(name) EnterCriticalSection(&(name))
#define WIN_MEMORY_LOCK_RELEASE(name) LeaveCriticalSection(&(name))
#if WASM_RT_USE_MMAP
#ifdef _WIN32
static void* os_mmap(size_t size) {
void* ret = VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS);
return ret;
}
static int os_munmap(
void* addr, size_t size) {
// Windows can only unmap the whole mapping
(
void)size;
/* unused */
BOOL succeeded = VirtualFree(addr, 0, MEM_RELEASE);
return succeeded ? 0 : -1;
}
static int os_mprotect(
void* addr, size_t size) {
if (size == 0) {
return 0;
}
void* ret = VirtualAlloc(addr, size, MEM_COMMIT, PAGE_READWRITE);
if (ret == addr) {
return 0;
}
VirtualFree(addr, 0, MEM_RELEASE);
return -1;
}
static void os_print_last_error(
const char* msg) {
DWORD errorMessageID = GetLastError();
if (errorMessageID != 0) {
LPSTR messageBuffer = 0;
// The api creates the buffer that holds the message
size_t size = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&messageBuffer, 0, NULL);
(
void)size;
printf(
"%s. %s\n", msg, messageBuffer);
LocalFree(messageBuffer);
}
else {
printf(
"%s. No error code.\n", msg);
}
}
#else
static void* os_mmap(size_t size) {
int map_prot = PROT_NONE;
int map_flags = MAP_ANONYMOUS | MAP_PRIVATE;
uint8_t* addr = mmap(NULL, size, map_prot, map_flags, -1, 0);
if (addr == MAP_FAILED)
return NULL;
return addr;
}
static int os_munmap(
void* addr, size_t size) {
return munmap(addr, size);
}
static int os_mprotect(
void* addr, size_t size) {
return mprotect(addr, size, PROT_READ | PROT_WRITE);
}
static void os_print_last_error(
const char* msg) {
perror(msg);
}
#endif
static uint64_t get_alloc_size_for_mmap(uint64_t max_pages,
bool is64) {
assert(!is64 &&
"memory64 is not yet compatible with WASM_RT_USE_MMAP");
#if WASM_RT_MEMCHECK_GUARD_PAGES
/* Reserve 8GiB. */
const uint64_t max_size = 0x200000000ul;
return max_size;
#else
if (max_pages != 0) {
const uint64_t max_size = max_pages * WASM_PAGE_SIZE;
return max_size;
}
/* Reserve 4GiB. */
const uint64_t max_size = 0x100000000ul;
return max_size;
#endif
}
#endif
// Include operations for memory
#define WASM_RT_MEM_OPS
#include "wasm-rt-mem-impl-helper.inc"
#undef WASM_RT_MEM_OPS
// Include operations for shared memory
#define WASM_RT_MEM_OPS_SHARED
#include "wasm-rt-mem-impl-helper.inc"
#undef WASM_RT_MEM_OPS_SHARED
#undef C11_MEMORY_LOCK_VAR_INIT
#undef C11_MEMORY_LOCK_AQUIRE
#undef C11_MEMORY_LOCK_RELEASE
#undef PTHREAD_MEMORY_LOCK_VAR_INIT
#undef PTHREAD_MEMORY_LOCK_AQUIRE
#undef PTHREAD_MEMORY_LOCK_RELEASE
#undef WIN_MEMORY_LOCK_VAR_INIT
#undef WIN_MEMORY_LOCK_AQUIRE
#undef WIN_MEMORY_LOCK_RELEASE
#undef WASM_PAGE_SIZE