dvander@11: /* dvander@11: * Copyright (C) 2012 David Anderson dvander@11: * dvander@11: * This file is part of JITCraft. dvander@11: * dvander@11: * JITCraft is free software: you can redistribute it and/or modify it under dvander@11: * the terms of the GNU General Public License as published by the Free dvander@11: * Software Foundation, either version 3 of the License, or (at your option) dvander@11: * any later version. dvander@11: * dvander@11: * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY dvander@11: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@11: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@11: * dvander@11: * You should have received a copy of the GNU General Public License along with dvander@11: * 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@11: using namespace jc; dvander@11: dvander@11: static inline DWORD dvander@11: ToProtBits(OS::Protection prot) dvander@11: { dvander@11: switch (prot) { dvander@11: 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@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: Address dvander@11: OS::MapMemoryAt(Address address, size_t amount, MapMode mode, Protection prot_) dvander@11: { dvander@11: DWORD bits = ToProtBits(prot_); dvander@11: DWORD flags = MEM_RESERVE; dvander@11: if (mode == Map_Commit) dvander@11: flags |= MEM_COMMIT; dvander@11: dvander@11: Address x = (Address)VirtualAlloc((LPVOID)address, amount, flags, bits); dvander@11: if (!x) { dvander@11: DWORD err = GetLastError(); dvander@11: return x; dvander@11: } dvander@11: return x; 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: }