dvander@28: /* vim: set ts=4 sw=4 tw=99 et: dvander@28: * dvander@28: * Copyright (C) 2012 David Anderson dvander@28: * dvander@28: * This file is part of JITCraft. dvander@28: * dvander@28: * JITCraft is free software: you can redistribute it and/or modify it under dvander@28: * the terms of the GNU General Public License as published by the Free dvander@28: * Software Foundation, either version 3 of the License, or (at your option) dvander@28: * any later version. dvander@28: * dvander@28: * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY dvander@28: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@28: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@28: * dvander@28: * You should have received a copy of the GNU General Public License along with dvander@28: * JITCraft. If not, see http://www.gnu.org/licenses/. dvander@11: */ dvander@11: dvander@11: // :TODO: move into utility-style include dvander@11: #define WIN32_LEAN_AND_MEAN dvander@11: #include dvander@11: #include "Platform.h" dvander@11: dvander@59: using namespace ke; dvander@11: dvander@11: static inline DWORD dvander@11: ToProtBits(OS::Protection prot) dvander@11: { dvander@11: switch (prot) { dvander@28: case OS::Prot_ReadWrite: dvander@11: return PAGE_READWRITE; dvander@11: case OS::Prot_ReadWriteExecute: dvander@11: return PAGE_EXECUTE_READWRITE; dvander@11: default: dvander@11: assert(prot == OS::Prot_ReadExecute); dvander@11: return PAGE_EXECUTE_READ; dvander@11: } dvander@11: } dvander@11: dvander@11: Address dvander@11: OS::MapMemory(size_t amount, MapMode mode, Protection prot_) dvander@11: { dvander@11: DWORD prot = ToProtBits(prot_); dvander@11: DWORD type = MEM_RESERVE; dvander@11: if (mode == Map_Commit) dvander@11: type |= MEM_COMMIT; dvander@11: dvander@11: return (Address)VirtualAlloc(NULL, amount, type, prot); dvander@11: } dvander@11: dvander@11: bool dvander@11: OS::CommitMemory(Address address, size_t amount, Protection prot_) dvander@11: { dvander@11: DWORD prot = ToProtBits(prot_); dvander@11: return !!VirtualAlloc(address, amount, MEM_COMMIT, prot); dvander@11: } dvander@11: dvander@11: void dvander@11: OS::UnmapMemory(Address address, size_t size) dvander@11: { dvander@11: VirtualFree(address, 0, MEM_RELEASE); dvander@11: } dvander@11: dvander@28: static Address dvander@53: MapMemoryAt(Address address, size_t amount, OS::MapMode mode, OS::Protection prot_) dvander@28: { dvander@28: DWORD bits = ToProtBits(prot_); dvander@28: DWORD flags = MEM_RESERVE; dvander@53: if (mode == OS::Map_Commit) dvander@28: flags |= MEM_COMMIT; dvander@28: dvander@69: return (Address)VirtualAlloc((LPVOID)address, amount, flags, bits); dvander@28: } dvander@28: dvander@11: OS::AlignableMapping dvander@11: OS::MapAlignedMemory(size_t amount, size_t alignment, MapMode mode) dvander@11: { dvander@11: Address addr = MapMemory(amount, mode, OS::Prot_ReadWrite); dvander@11: if (!addr) dvander@11: return AlignableMapping(NULL, alignment, 0); dvander@11: dvander@11: if (!IsAligned(addr, alignment)) { dvander@11: UnmapMemory(addr, amount); dvander@11: dvander@11: // Try to grab the next available aligned address. dvander@11: addr = AlignedBase(addr, alignment); dvander@11: addr = MapMemoryAt(addr + alignment, amount, mode, OS::Prot_ReadWrite); dvander@11: while (!addr) { dvander@11: // Try to over-allocate to get the right region. This can race dvander@11: // with other threads; we expect this to be rare. If this turns dvander@11: // out to be a problem, the API is set up such that we can just dvander@11: // return two pointers: the base, and the aligned address into dvander@11: // the over-allocated region. dvander@11: addr = MapMemory(amount + alignment, mode, OS::Prot_ReadWrite); dvander@11: if (!addr) dvander@11: return AlignableMapping(NULL, alignment, 0); dvander@11: UnmapMemory(addr, amount + alignment); dvander@11: addr = AlignedBase(addr, alignment); dvander@11: addr = MapMemoryAt(addr + alignment, amount, mode, OS::Prot_ReadWrite); dvander@11: } dvander@11: } dvander@11: dvander@11: return AlignableMapping(addr, alignment, amount); dvander@11: } dvander@11: dvander@11: void dvander@11: OS::UnmapAlignedMemory(Address address, size_t size) dvander@11: { dvander@11: OS::UnmapMemory(address, size); dvander@11: }