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