1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/jitcraft/Platform-Windows.cpp Fri Jun 29 19:35:17 2012 -0700
1.3 @@ -0,0 +1,115 @@
1.4 +/*
1.5 + * Copyright (C) 2012 David Anderson
1.6 + *
1.7 + * This file is part of JITCraft.
1.8 + *
1.9 + * JITCraft is free software: you can redistribute it and/or modify it under
1.10 + * the terms of the GNU General Public License as published by the Free
1.11 + * Software Foundation, either version 3 of the License, or (at your option)
1.12 + * any later version.
1.13 + *
1.14 + * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
1.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.17 + *
1.18 + * You should have received a copy of the GNU General Public License along with
1.19 + * JITCraft. If not, see http://www.gnu.org/licenses/.
1.20 + */
1.21 +
1.22 +// :TODO: move into utility-style include
1.23 +#define WIN32_LEAN_AND_MEAN
1.24 +#include <Windows.h>
1.25 +#include "Platform.h"
1.26 +
1.27 +using namespace jc;
1.28 +
1.29 +static inline DWORD
1.30 +ToProtBits(OS::Protection prot)
1.31 +{
1.32 + switch (prot) {
1.33 + case OS::Prot_ReadWrite:
1.34 + return PAGE_READWRITE;
1.35 + case OS::Prot_ReadWriteExecute:
1.36 + return PAGE_EXECUTE_READWRITE;
1.37 + default:
1.38 + assert(prot == OS::Prot_ReadExecute);
1.39 + return PAGE_EXECUTE_READ;
1.40 + }
1.41 +}
1.42 +
1.43 +Address
1.44 +OS::MapMemory(size_t amount, MapMode mode, Protection prot_)
1.45 +{
1.46 + DWORD prot = ToProtBits(prot_);
1.47 + DWORD type = MEM_RESERVE;
1.48 + if (mode == Map_Commit)
1.49 + type |= MEM_COMMIT;
1.50 +
1.51 + return (Address)VirtualAlloc(NULL, amount, type, prot);
1.52 +}
1.53 +
1.54 +bool
1.55 +OS::CommitMemory(Address address, size_t amount, Protection prot_)
1.56 +{
1.57 + DWORD prot = ToProtBits(prot_);
1.58 + return !!VirtualAlloc(address, amount, MEM_COMMIT, prot);
1.59 +}
1.60 +
1.61 +void
1.62 +OS::UnmapMemory(Address address, size_t size)
1.63 +{
1.64 + VirtualFree(address, 0, MEM_RELEASE);
1.65 +}
1.66 +
1.67 +OS::AlignableMapping
1.68 +OS::MapAlignedMemory(size_t amount, size_t alignment, MapMode mode)
1.69 +{
1.70 + Address addr = MapMemory(amount, mode, OS::Prot_ReadWrite);
1.71 + if (!addr)
1.72 + return AlignableMapping(NULL, alignment, 0);
1.73 +
1.74 + if (!IsAligned(addr, alignment)) {
1.75 + UnmapMemory(addr, amount);
1.76 +
1.77 + // Try to grab the next available aligned address.
1.78 + addr = AlignedBase(addr, alignment);
1.79 + addr = MapMemoryAt(addr + alignment, amount, mode, OS::Prot_ReadWrite);
1.80 + while (!addr) {
1.81 + // Try to over-allocate to get the right region. This can race
1.82 + // with other threads; we expect this to be rare. If this turns
1.83 + // out to be a problem, the API is set up such that we can just
1.84 + // return two pointers: the base, and the aligned address into
1.85 + // the over-allocated region.
1.86 + addr = MapMemory(amount + alignment, mode, OS::Prot_ReadWrite);
1.87 + if (!addr)
1.88 + return AlignableMapping(NULL, alignment, 0);
1.89 + UnmapMemory(addr, amount + alignment);
1.90 + addr = AlignedBase(addr, alignment);
1.91 + addr = MapMemoryAt(addr + alignment, amount, mode, OS::Prot_ReadWrite);
1.92 + }
1.93 + }
1.94 +
1.95 + return AlignableMapping(addr, alignment, amount);
1.96 +}
1.97 +
1.98 +Address
1.99 +OS::MapMemoryAt(Address address, size_t amount, MapMode mode, Protection prot_)
1.100 +{
1.101 + DWORD bits = ToProtBits(prot_);
1.102 + DWORD flags = MEM_RESERVE;
1.103 + if (mode == Map_Commit)
1.104 + flags |= MEM_COMMIT;
1.105 +
1.106 + Address x = (Address)VirtualAlloc((LPVOID)address, amount, flags, bits);
1.107 + if (!x) {
1.108 + DWORD err = GetLastError();
1.109 + return x;
1.110 + }
1.111 + return x;
1.112 +}
1.113 +
1.114 +void
1.115 +OS::UnmapAlignedMemory(Address address, size_t size)
1.116 +{
1.117 + OS::UnmapMemory(address, size);
1.118 +}