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