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