#include "mem_utils.h" #include "aliases.h" #include "platform.h" #include #include #include #include #if defined(WAPP_PLATFORM_WINDOWS) #include #include internal const i32 access_types[] = { [WAPP_MEM_ACCESS_NONE] = PAGE_NOACCESS, [WAPP_MEM_ACCESS_READ_ONLY] = PAGE_READONLY, [WAPP_MEM_ACCESS_EXEC_ONLY] = PAGE_EXECUTE, [WAPP_MEM_ACCESS_READ_WRITE] = PAGE_READWRITE, [WAPP_MEM_ACCESS_READ_EXEC] = PAGE_EXECUTE_READ, [WAPP_MEM_ACCESS_READ_WRITE_EXEC] = PAGE_EXECUTE_READWRITE, }; internal inline void *alloc_windows(void *addr, u64 size, MemAccess access, MemAllocFlags flags); #elif defined(WAPP_PLATFORM_POSIX) #include internal const i32 access_types[] = { [WAPP_MEM_ACCESS_NONE] = PROT_NONE, [WAPP_MEM_ACCESS_READ_ONLY] = PROT_READ, [WAPP_MEM_ACCESS_EXEC_ONLY] = PROT_EXEC, [WAPP_MEM_ACCESS_READ_WRITE] = PROT_READ | PROT_WRITE, [WAPP_MEM_ACCESS_READ_EXEC] = PROT_READ | PROT_EXEC, [WAPP_MEM_ACCESS_READ_WRITE_EXEC] = PROT_READ | PROT_WRITE | PROT_EXEC, }; internal inline void *alloc_posix(void *addr, u64 size, MemAccess access, MemAllocFlags flags); #else #error "Unrecognised platform" #endif internal bool is_power_of_two(u64 num) { return (num & (num - 1)) == 0; } void *wapp_mem_util_align_forward(void *ptr, u64 alignment) { if (!ptr) { return NULL; } assert(is_power_of_two(alignment)); uptr p = (uptr)ptr; uptr align = (uptr)alignment; // Similar to p % align, but it's a faster implementation that works fine // because align is guaranteed to be a power of 2 uptr modulo = p & (align - 1); if (modulo != 0) { p += align - modulo; } return (void *)p; } void *wapp_mem_util_alloc(void *addr, u64 size, MemAccess access, MemAllocFlags flags, MemInitType type) { #if defined(WAPP_PLATFORM_WINDOWS) // Ensure memory is committed if it's meant to be initialised if (type == WAPP_MEM_INIT_INITIALISED) { flags |= WAPP_MEM_ALLOC_COMMIT; } void *output = alloc_windows(addr, size, access, flags); #elif defined(WAPP_PLATFORM_POSIX) void *output = alloc_posix(addr, size, access, flags); #else return NULL; #endif if (type == WAPP_MEM_INIT_INITIALISED) { memset(output, 0, size); } return output; } void wapp_mem_util_free(void *ptr, u64 size) { #if defined(WAPP_PLATFORM_WINDOWS) VirtualFree(ptr, size, MEM_RELEASE); #elif defined(WAPP_PLATFORM_POSIX) munmap(ptr, size); #endif } #ifdef WAPP_PLATFORM_WINDOWS internal inline void *alloc_windows(void *addr, u64 size, MemAccess access, MemAllocFlags flags) { return VirtualAlloc2(addr, NULL, (SIZE_T)size, flags, access_types[access]); } #endif #if defined(WAPP_PLATFORM_POSIX) internal inline void *alloc_posix(void *addr, u64 size, MemAccess access, MemAllocFlags flags) { i32 alloc_flags = flags | MAP_ANON | MAP_PRIVATE; #if defined(WAPP_PLATFORM_LINUX) || defined(WAPP_PLATFORM_GNU) || \ defined(WAPP_PLATFORM_NET_BSD) alloc_flags |= MAP_NORESERVE; #endif return mmap(addr, size, access_types[access], alloc_flags, -1, 0); } #endif