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