wireform-core-0.2.0.0: cbits/magic_ring_windows.c
#ifdef _WIN32
#include <windows.h>
#include <memoryapi.h>
#include <stdint.h>
#include "magic_ring.h"
static long cached_page_size = 0;
long hs_page_size(void) {
if (cached_page_size == 0) {
SYSTEM_INFO si;
GetSystemInfo(&si);
cached_page_size = (long)si.dwAllocationGranularity;
}
return cached_page_size;
}
static size_t next_pow2(size_t val) {
val--;
val |= val >> 1;
val |= val >> 2;
val |= val >> 4;
val |= val >> 8;
val |= val >> 16;
#if defined(_WIN64)
val |= val >> 32;
#endif
val++;
return val;
}
int hs_ring_create(size_t requested, struct hs_ring *out) {
long ps = hs_page_size();
size_t size;
PVOID placeholder = NULL;
HANDLE section = NULL;
PVOID view1 = NULL, view2 = NULL;
if (requested < (size_t)ps)
requested = (size_t)ps;
size = (requested + (size_t)ps - 1) & ~((size_t)ps - 1);
size = next_pow2(size);
placeholder = VirtualAlloc2(NULL, NULL, size * 2,
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, PAGE_NOACCESS, NULL, 0);
if (!placeholder)
return -1;
/* Split the placeholder into two halves */
if (!VirtualFree(placeholder, size, MEM_RELEASE | MEM_PRESERVE_PLACEHOLDER)) {
VirtualFree(placeholder, 0, MEM_RELEASE);
return -1;
}
section = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
(DWORD)(size >> 32), (DWORD)(size & 0xFFFFFFFF), NULL);
if (!section) {
VirtualFree(placeholder, 0, MEM_RELEASE);
VirtualFree((char *)placeholder + size, 0, MEM_RELEASE);
return -1;
}
view1 = MapViewOfFile3(section, NULL, placeholder, 0, size,
MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, NULL, 0);
if (!view1)
goto fail;
view2 = MapViewOfFile3(section, NULL, (char *)placeholder + size, 0, size,
MEM_REPLACE_PLACEHOLDER, PAGE_READWRITE, NULL, 0);
if (!view2) {
UnmapViewOfFile(view1);
goto fail;
}
/* Pre-fault */
memset(view1, 0, size);
out->base = view1;
out->size = size;
out->section = section;
return 0;
fail:
CloseHandle(section);
VirtualFree(placeholder, 0, MEM_RELEASE);
VirtualFree((char *)placeholder + size, 0, MEM_RELEASE);
return -1;
}
void hs_ring_destroy(struct hs_ring *ring) {
if (ring && ring->base) {
UnmapViewOfFile(ring->base);
UnmapViewOfFile((char *)ring->base + ring->size);
CloseHandle(ring->section);
ring->base = NULL;
ring->size = 0;
ring->section = NULL;
}
}
#endif /* _WIN32 */