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.
     1 /* vim: set ts=4 sw=4 tw=99 et:
     2  *
     3  * Copyright (C) 2012 David Anderson
     4  *
     5  * This file is part of JITCraft.
     6  *
     7  * JITCraft is free software: you can redistribute it and/or modify it under
     8  * the terms of the GNU General Public License as published by the Free
     9  * Software Foundation, either version 3 of the License, or (at your option)
    10  * any later version.
    11  * 
    12  * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY
    13  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along with
    17  * JITCraft. If not, see http://www.gnu.org/licenses/.
    18  */
    19 #include <sys/mman.h>
    20 #include <limits.h>
    21 #include <string.h>
    22 #include <stdlib.h>
    23 #include "Platform.h"
    24 
    25 using namespace ke;
    26 
    27 static inline int
    28 ToProtBits(OS::Protection prot)
    29 {
    30     switch (prot) {
    31       case OS::Prot_ReadWrite:
    32         return PROT_READ | PROT_WRITE;
    33       case OS::Prot_ReadWriteExecute:
    34         return PROT_READ | PROT_WRITE | PROT_EXEC;
    35       default:
    36         assert(prot == OS::Prot_ReadExecute);
    37         return PROT_READ | PROT_EXEC;
    38     }
    39 }
    40 
    41 Address
    42 OS::MapMemory(size_t amount, MapMode mode, Protection prot_)
    43 {
    44     int prot = ToProtBits(prot_);
    45     void *addr = mmap(NULL, amount, prot, MAP_ANON | MAP_PRIVATE, -1, 0);
    46     if (addr == MAP_FAILED)
    47         return NULL;
    48 
    49     return Address(addr);
    50 }
    51 
    52 bool
    53 OS::CommitMemory(Address address, size_t amount, Protection prot_)
    54 {
    55     return true;
    56 }
    57 
    58 void
    59 OS::UnmapMemory(Address address, size_t size)
    60 {
    61     munmap(address, size);
    62 }
    63 
    64 OS::AlignableMapping
    65 OS::MapAlignedMemory(size_t amount, size_t alignment, MapMode mode)
    66 {
    67     assert(amount >= alignment);
    68     assert(IsPowerOfTwo(alignment));
    69 
    70     if (alignment == kPageAlignment) {
    71         Address address = MapMemory(amount, mode, Prot_ReadWrite);
    72         if (!address)
    73             return AlignableMapping();
    74         return AlignableMapping(address, alignment, amount);
    75     }
    76 
    77     size_t requested = Min(amount * 2, amount + 2 * alignment);
    78     Address address = MapMemory(requested, mode, Prot_ReadWrite);
    79     if (!address)
    80         return AlignableMapping();
    81 
    82     size_t begin = 0;
    83     Address aligned = AlignedBase(address, alignment);
    84     if (!IsAligned(address, alignment)) {
    85         // Shave off the first part of the unaligned region.
    86         aligned += alignment;
    87         begin = size_t(aligned - address);
    88         UnmapAlignedMemory(address, begin);
    89     }
    90 
    91     if (requested - begin > amount) {
    92         // Shave off the last part of the unaligned region.
    93         UnmapAlignedMemory(aligned + amount, requested - amount - begin);
    94     }
    95 
    96     return AlignableMapping(aligned, alignment, amount);
    97 }
    98 
    99 void
   100 OS::UnmapAlignedMemory(Address address, size_t size)
   101 {
   102     OS::UnmapMemory(address, size);
   103 }
   104 
   105 bool
   106 OS::GetAbsolutePath(const char *path, AutoFree<char> &chars)
   107 {
   108     chars = (char *)calloc(PATH_MAX, sizeof(char));
   109     if (!*chars)
   110         return false;
   111 
   112     char *ptr = realpath(path, *chars);
   113     if (!ptr)
   114         return false;
   115 
   116     return ptr == *chars;
   117 }
   118 
   119 bool
   120 OS::SplitPath(const char *path, AutoFree<char> &base, AutoFree<char> &name)
   121 {
   122     // dirname() and basename() pretty much suck.
   123     size_t len = strlen(path);
   124 
   125     // Skip trailing slashes.
   126     while (len > 1 && (path[len - 1] == '/'))
   127         len--;
   128 
   129     for (size_t i = len - 1; i < len; i--) {
   130         if (path[i] == '/') {
   131             name = (char *)calloc(len - i, sizeof(char));
   132             if (!*name)
   133                 return false;
   134 
   135             strcpy(*name, &path[i + 1]);
   136 
   137             base = (char *)calloc(i + 1, sizeof(char));
   138             if (!*base)
   139                 return false;
   140 
   141             memcpy(*base, path, i);
   142             (*base)[i] = '\0';
   143             return true;
   144         }
   145     }
   146     
   147     // The path should have been absolute, which contains at least one separator.
   148     return false;
   149 }
   150 
   151 const char *
   152 OS::PathSeparator()
   153 {
   154     return "/";
   155 }
   156