src/Platform-Posix.cpp
author David Anderson <dvander@alliedmods.net>
Tue Jan 01 15:34:07 2013 -0800 (2013-01-01)
changeset 251 ca99a81745fe
parent 92 e3974e7360e9
child 252 1dee2330aa78
permissions -rw-r--r--
Refactor compilation process around the new concept of packages.
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@28
     5
 * This file is part of JITCraft.
dvander@28
     6
 *
dvander@28
     7
 * JITCraft 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@28
    12
 * Foobar 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@28
    17
 * JITCraft. If not, see http://www.gnu.org/licenses/.
dvander@28
    18
 */
dvander@28
    19
#include <sys/mman.h>
dvander@251
    20
#include <limits.h>
dvander@251
    21
#include <string.h>
dvander@251
    22
#include <stdlib.h>
dvander@28
    23
#include "Platform.h"
dvander@28
    24
danderson@91
    25
using namespace ke;
dvander@28
    26
dvander@28
    27
static inline int
dvander@28
    28
ToProtBits(OS::Protection prot)
dvander@28
    29
{
dvander@28
    30
    switch (prot) {
dvander@28
    31
      case OS::Prot_ReadWrite:
dvander@28
    32
        return PROT_READ | PROT_WRITE;
dvander@28
    33
      case OS::Prot_ReadWriteExecute:
dvander@28
    34
        return PROT_READ | PROT_WRITE | PROT_EXEC;
dvander@28
    35
      default:
dvander@28
    36
        assert(prot == OS::Prot_ReadExecute);
dvander@28
    37
        return PROT_READ | PROT_EXEC;
dvander@28
    38
    }
dvander@28
    39
}
dvander@28
    40
dvander@28
    41
Address
dvander@28
    42
OS::MapMemory(size_t amount, MapMode mode, Protection prot_)
dvander@28
    43
{
dvander@28
    44
    int prot = ToProtBits(prot_);
dvander@28
    45
    void *addr = mmap(NULL, amount, prot, MAP_ANON | MAP_PRIVATE, -1, 0);
dvander@28
    46
    if (addr == MAP_FAILED)
dvander@28
    47
        return NULL;
dvander@28
    48
dvander@28
    49
    return Address(addr);
dvander@28
    50
}
dvander@28
    51
dvander@28
    52
bool
dvander@28
    53
OS::CommitMemory(Address address, size_t amount, Protection prot_)
dvander@28
    54
{
dvander@28
    55
    return true;
dvander@28
    56
}
dvander@28
    57
dvander@28
    58
void
dvander@28
    59
OS::UnmapMemory(Address address, size_t size)
dvander@28
    60
{
dvander@28
    61
    munmap(address, size);
dvander@28
    62
}
dvander@28
    63
dvander@28
    64
OS::AlignableMapping
dvander@28
    65
OS::MapAlignedMemory(size_t amount, size_t alignment, MapMode mode)
dvander@28
    66
{
dvander@28
    67
    assert(amount >= alignment);
dvander@28
    68
    assert(IsPowerOfTwo(alignment));
dvander@28
    69
dvander@28
    70
    if (alignment == kPageAlignment) {
dvander@28
    71
        Address address = MapMemory(amount, mode, Prot_ReadWrite);
dvander@28
    72
        if (!address)
dvander@28
    73
            return AlignableMapping();
dvander@28
    74
        return AlignableMapping(address, alignment, amount);
dvander@28
    75
    }
dvander@28
    76
dvander@28
    77
    size_t requested = Min(amount * 2, amount + 2 * alignment);
danderson@92
    78
    Address address = MapMemory(requested, mode, Prot_ReadWrite);
dvander@28
    79
    if (!address)
dvander@28
    80
        return AlignableMapping();
dvander@28
    81
dvander@28
    82
    size_t begin = 0;
dvander@28
    83
    Address aligned = AlignedBase(address, alignment);
dvander@28
    84
    if (!IsAligned(address, alignment)) {
dvander@28
    85
        // Shave off the first part of the unaligned region.
dvander@28
    86
        aligned += alignment;
dvander@28
    87
        begin = size_t(aligned - address);
dvander@28
    88
        UnmapAlignedMemory(address, begin);
dvander@28
    89
    }
dvander@28
    90
dvander@28
    91
    if (requested - begin > amount) {
dvander@28
    92
        // Shave off the last part of the unaligned region.
danderson@92
    93
        UnmapAlignedMemory(aligned + amount, requested - amount - begin);
dvander@28
    94
    }
dvander@28
    95
dvander@28
    96
    return AlignableMapping(aligned, alignment, amount);
dvander@28
    97
}
dvander@28
    98
dvander@28
    99
void
dvander@28
   100
OS::UnmapAlignedMemory(Address address, size_t size)
dvander@28
   101
{
dvander@28
   102
    OS::UnmapMemory(address, size);
dvander@28
   103
}
dvander@28
   104
dvander@251
   105
bool
dvander@251
   106
OS::GetAbsolutePath(const char *path, AutoFree<char> &chars)
dvander@251
   107
{
dvander@251
   108
    chars = (char *)calloc(PATH_MAX, sizeof(char));
dvander@251
   109
    if (!*chars)
dvander@251
   110
        return false;
dvander@251
   111
dvander@251
   112
    char *ptr = realpath(path, *chars);
dvander@251
   113
    if (!ptr)
dvander@251
   114
        return false;
dvander@251
   115
dvander@251
   116
    return ptr == *chars;
dvander@251
   117
}
dvander@251
   118
dvander@251
   119
bool
dvander@251
   120
OS::SplitPath(const char *path, AutoFree<char> &base, AutoFree<char> &name)
dvander@251
   121
{
dvander@251
   122
    // dirname() and basename() pretty much suck.
dvander@251
   123
    size_t len = strlen(path);
dvander@251
   124
dvander@251
   125
    // Skip trailing slashes.
dvander@251
   126
    while (len > 1 && (path[len - 1] == '/'))
dvander@251
   127
        len--;
dvander@251
   128
dvander@251
   129
    for (size_t i = len - 1; i < len; i--) {
dvander@251
   130
        if (path[i] == '/') {
dvander@251
   131
            name = (char *)calloc(len - i, sizeof(char));
dvander@251
   132
            if (!*name)
dvander@251
   133
                return false;
dvander@251
   134
dvander@251
   135
            strcpy(*name, &path[i + 1]);
dvander@251
   136
dvander@251
   137
            base = (char *)calloc(i + 1, sizeof(char));
dvander@251
   138
            if (!*base)
dvander@251
   139
                return false;
dvander@251
   140
dvander@251
   141
            memcpy(*base, path, i);
dvander@251
   142
            (*base)[i] = '\0';
dvander@251
   143
            return true;
dvander@251
   144
        }
dvander@251
   145
    }
dvander@251
   146
    
dvander@251
   147
    // The path should have been absolute, which contains at least one separator.
dvander@251
   148
    return false;
dvander@251
   149
}
dvander@251
   150
dvander@251
   151
const char *
dvander@251
   152
OS::PathSeparator()
dvander@251
   153
{
dvander@251
   154
    return "/";
dvander@251
   155
}
dvander@251
   156