jitcraft/Platform-Windows.cpp
author David Anderson <dvander@alliedmods.net>
Sat Jun 30 22:45:25 2012 -0700 (2012-06-30)
changeset 16 23627f8bc421
parent 11 a350c2cc736a
child 28 a9665857cfd5
permissions -rw-r--r--
Added support for arbitrary expression references.
dvander@11
     1
/*
dvander@11
     2
 * Copyright (C) 2012 David Anderson
dvander@11
     3
 *
dvander@11
     4
 * This file is part of JITCraft.
dvander@11
     5
 *
dvander@11
     6
 * JITCraft is free software: you can redistribute it and/or modify it under
dvander@11
     7
 * the terms of the GNU General Public License as published by the Free
dvander@11
     8
 * Software Foundation, either version 3 of the License, or (at your option)
dvander@11
     9
 * any later version.
dvander@11
    10
 * 
dvander@11
    11
 * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
dvander@11
    12
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
dvander@11
    13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
dvander@11
    14
 *
dvander@11
    15
 * You should have received a copy of the GNU General Public License along with
dvander@11
    16
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@11
    17
 */
dvander@11
    18
dvander@11
    19
// :TODO: move into utility-style include
dvander@11
    20
#define WIN32_LEAN_AND_MEAN
dvander@11
    21
#include <Windows.h>
dvander@11
    22
#include "Platform.h"
dvander@11
    23
dvander@11
    24
using namespace jc;
dvander@11
    25
dvander@11
    26
static inline DWORD
dvander@11
    27
ToProtBits(OS::Protection prot)
dvander@11
    28
{
dvander@11
    29
    switch (prot) {
dvander@11
    30
	  case OS::Prot_ReadWrite:
dvander@11
    31
        return PAGE_READWRITE;
dvander@11
    32
      case OS::Prot_ReadWriteExecute:
dvander@11
    33
        return PAGE_EXECUTE_READWRITE;
dvander@11
    34
      default:
dvander@11
    35
        assert(prot == OS::Prot_ReadExecute);
dvander@11
    36
        return PAGE_EXECUTE_READ;
dvander@11
    37
    }
dvander@11
    38
}
dvander@11
    39
dvander@11
    40
Address
dvander@11
    41
OS::MapMemory(size_t amount, MapMode mode, Protection prot_)
dvander@11
    42
{
dvander@11
    43
    DWORD prot = ToProtBits(prot_);
dvander@11
    44
    DWORD type = MEM_RESERVE;
dvander@11
    45
    if (mode == Map_Commit)
dvander@11
    46
        type |= MEM_COMMIT;
dvander@11
    47
dvander@11
    48
    return (Address)VirtualAlloc(NULL, amount, type, prot);
dvander@11
    49
}
dvander@11
    50
dvander@11
    51
bool
dvander@11
    52
OS::CommitMemory(Address address, size_t amount, Protection prot_)
dvander@11
    53
{
dvander@11
    54
    DWORD prot = ToProtBits(prot_);
dvander@11
    55
    return !!VirtualAlloc(address, amount, MEM_COMMIT, prot);
dvander@11
    56
}
dvander@11
    57
dvander@11
    58
void
dvander@11
    59
OS::UnmapMemory(Address address, size_t size)
dvander@11
    60
{
dvander@11
    61
    VirtualFree(address, 0, MEM_RELEASE);
dvander@11
    62
}
dvander@11
    63
dvander@11
    64
OS::AlignableMapping
dvander@11
    65
OS::MapAlignedMemory(size_t amount, size_t alignment, MapMode mode)
dvander@11
    66
{
dvander@11
    67
    Address addr = MapMemory(amount, mode, OS::Prot_ReadWrite);
dvander@11
    68
    if (!addr)
dvander@11
    69
        return AlignableMapping(NULL, alignment, 0);
dvander@11
    70
dvander@11
    71
    if (!IsAligned(addr, alignment)) {
dvander@11
    72
        UnmapMemory(addr, amount);
dvander@11
    73
dvander@11
    74
        // Try to grab the next available aligned address.
dvander@11
    75
        addr = AlignedBase(addr, alignment);
dvander@11
    76
        addr = MapMemoryAt(addr + alignment, amount, mode, OS::Prot_ReadWrite);
dvander@11
    77
        while (!addr) {
dvander@11
    78
            // Try to over-allocate to get the right region. This can race
dvander@11
    79
            // with other threads; we expect this to be rare. If this turns
dvander@11
    80
            // out to be a problem, the API is set up such that we can just
dvander@11
    81
            // return two pointers: the base, and the aligned address into
dvander@11
    82
            // the over-allocated region.
dvander@11
    83
            addr = MapMemory(amount + alignment, mode, OS::Prot_ReadWrite);
dvander@11
    84
            if (!addr)
dvander@11
    85
                return AlignableMapping(NULL, alignment, 0);
dvander@11
    86
            UnmapMemory(addr, amount + alignment);
dvander@11
    87
            addr = AlignedBase(addr, alignment);
dvander@11
    88
            addr = MapMemoryAt(addr + alignment, amount, mode, OS::Prot_ReadWrite);
dvander@11
    89
        }
dvander@11
    90
    }
dvander@11
    91
dvander@11
    92
    return AlignableMapping(addr, alignment, amount);
dvander@11
    93
}
dvander@11
    94
dvander@11
    95
Address
dvander@11
    96
OS::MapMemoryAt(Address address, size_t amount, MapMode mode, Protection prot_)
dvander@11
    97
{
dvander@11
    98
    DWORD bits = ToProtBits(prot_);
dvander@11
    99
    DWORD flags = MEM_RESERVE;
dvander@11
   100
    if (mode == Map_Commit)
dvander@11
   101
        flags |= MEM_COMMIT;
dvander@11
   102
dvander@11
   103
    Address x = (Address)VirtualAlloc((LPVOID)address, amount, flags, bits);
dvander@11
   104
    if (!x) {
dvander@11
   105
        DWORD err = GetLastError();
dvander@11
   106
        return x;
dvander@11
   107
    }
dvander@11
   108
    return x;
dvander@11
   109
}
dvander@11
   110
dvander@11
   111
void
dvander@11
   112
OS::UnmapAlignedMemory(Address address, size_t size)
dvander@11
   113
{
dvander@11
   114
    OS::UnmapMemory(address, size);
dvander@11
   115
}