#include <sys/mman.h>
#include "mmap.h"
#include "out.h"
char *
util_map_hint_unused(void *minaddr, size_t len, size_t align)
{
LOG(3, "minaddr %p len %zu align %zu", minaddr, len, align);
ASSERT(align > 0);
MEMORY_BASIC_INFORMATION mi;
char *lo = NULL;
char *hi = NULL;
char *raddr = minaddr;
if (raddr == NULL)
raddr += Pagesize;
raddr = (char *)roundup((uintptr_t)raddr, align);
while ((uintptr_t)raddr < UINTPTR_MAX - len) {
size_t ret = VirtualQuery(raddr, &mi, sizeof(mi));
if (ret == 0) {
ERR("VirtualQuery %p", raddr);
return MAP_FAILED;
}
LOG(4, "addr %p len %zu state %d",
mi.BaseAddress, mi.RegionSize, mi.State);
if ((mi.State != MEM_FREE) || (mi.RegionSize < len)) {
raddr = (char *)mi.BaseAddress + mi.RegionSize;
raddr = (char *)roundup((uintptr_t)raddr, align);
LOG(4, "nearest aligned addr %p", raddr);
} else {
LOG(4, "unused region of size %zu found at %p",
mi.RegionSize, mi.BaseAddress);
return mi.BaseAddress;
}
}
LOG(4, "end of address space reached");
return MAP_FAILED;
}
char *
util_map_hint(size_t len, size_t req_align)
{
LOG(3, "len %zu req_align %zu", len, req_align);
char *hint_addr = MAP_FAILED;
size_t align = util_map_hint_align(len, req_align);
if (Mmap_no_random) {
LOG(4, "user-defined hint %p", (void *)Mmap_hint);
hint_addr = util_map_hint_unused((void *)Mmap_hint, len, align);
} else {
char *addr = mmap(NULL, len + align, PROT_READ,
MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0);
if (addr != MAP_FAILED) {
LOG(4, "system choice %p", addr);
hint_addr = (char *)roundup((uintptr_t)addr, align);
munmap(addr, len + align);
}
}
LOG(4, "hint %p", hint_addr);
return hint_addr;
}