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