dvander@28: /* vim: set ts=4 sw=4 tw=99 et: dvander@28: * dvander@28: * Copyright (C) 2012 David Anderson dvander@28: * dvander@28: * This file is part of JITCraft. dvander@28: * dvander@28: * JITCraft is free software: you can redistribute it and/or modify it under dvander@28: * the terms of the GNU General Public License as published by the Free dvander@28: * Software Foundation, either version 3 of the License, or (at your option) dvander@28: * any later version. dvander@28: * dvander@28: * Foobar is distributed in the hope that it will be useful, but WITHOUT ANY dvander@28: * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@28: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. dvander@28: * dvander@28: * You should have received a copy of the GNU General Public License along with dvander@28: * JITCraft. If not, see http://www.gnu.org/licenses/. dvander@28: */ dvander@28: #include dvander@251: #include dvander@251: #include dvander@251: #include dvander@28: #include "Platform.h" dvander@28: danderson@91: using namespace ke; dvander@28: dvander@28: static inline int dvander@28: ToProtBits(OS::Protection prot) dvander@28: { dvander@28: switch (prot) { dvander@28: case OS::Prot_ReadWrite: dvander@28: return PROT_READ | PROT_WRITE; dvander@28: case OS::Prot_ReadWriteExecute: dvander@28: return PROT_READ | PROT_WRITE | PROT_EXEC; dvander@28: default: dvander@28: assert(prot == OS::Prot_ReadExecute); dvander@28: return PROT_READ | PROT_EXEC; dvander@28: } dvander@28: } dvander@28: dvander@28: Address dvander@28: OS::MapMemory(size_t amount, MapMode mode, Protection prot_) dvander@28: { dvander@28: int prot = ToProtBits(prot_); dvander@28: void *addr = mmap(NULL, amount, prot, MAP_ANON | MAP_PRIVATE, -1, 0); dvander@28: if (addr == MAP_FAILED) dvander@28: return NULL; dvander@28: dvander@28: return Address(addr); dvander@28: } dvander@28: dvander@28: bool dvander@28: OS::CommitMemory(Address address, size_t amount, Protection prot_) dvander@28: { dvander@28: return true; dvander@28: } dvander@28: dvander@28: void dvander@28: OS::UnmapMemory(Address address, size_t size) dvander@28: { dvander@28: munmap(address, size); dvander@28: } dvander@28: dvander@28: OS::AlignableMapping dvander@28: OS::MapAlignedMemory(size_t amount, size_t alignment, MapMode mode) dvander@28: { dvander@28: assert(amount >= alignment); dvander@28: assert(IsPowerOfTwo(alignment)); dvander@28: dvander@28: if (alignment == kPageAlignment) { dvander@28: Address address = MapMemory(amount, mode, Prot_ReadWrite); dvander@28: if (!address) dvander@28: return AlignableMapping(); dvander@28: return AlignableMapping(address, alignment, amount); dvander@28: } dvander@28: dvander@28: size_t requested = Min(amount * 2, amount + 2 * alignment); danderson@92: Address address = MapMemory(requested, mode, Prot_ReadWrite); dvander@28: if (!address) dvander@28: return AlignableMapping(); dvander@28: dvander@28: size_t begin = 0; dvander@28: Address aligned = AlignedBase(address, alignment); dvander@28: if (!IsAligned(address, alignment)) { dvander@28: // Shave off the first part of the unaligned region. dvander@28: aligned += alignment; dvander@28: begin = size_t(aligned - address); dvander@28: UnmapAlignedMemory(address, begin); dvander@28: } dvander@28: dvander@28: if (requested - begin > amount) { dvander@28: // Shave off the last part of the unaligned region. danderson@92: UnmapAlignedMemory(aligned + amount, requested - amount - begin); dvander@28: } dvander@28: dvander@28: return AlignableMapping(aligned, alignment, amount); dvander@28: } dvander@28: dvander@28: void dvander@28: OS::UnmapAlignedMemory(Address address, size_t size) dvander@28: { dvander@28: OS::UnmapMemory(address, size); dvander@28: } dvander@28: dvander@251: bool dvander@251: OS::GetAbsolutePath(const char *path, AutoFree &chars) dvander@251: { dvander@251: chars = (char *)calloc(PATH_MAX, sizeof(char)); dvander@251: if (!*chars) dvander@251: return false; dvander@251: dvander@251: char *ptr = realpath(path, *chars); dvander@251: if (!ptr) dvander@251: return false; dvander@251: dvander@251: return ptr == *chars; dvander@251: } dvander@251: dvander@251: bool dvander@251: OS::SplitPath(const char *path, AutoFree &base, AutoFree &name) dvander@251: { dvander@251: // dirname() and basename() pretty much suck. dvander@251: size_t len = strlen(path); dvander@251: dvander@251: // Skip trailing slashes. dvander@251: while (len > 1 && (path[len - 1] == '/')) dvander@251: len--; dvander@251: dvander@251: for (size_t i = len - 1; i < len; i--) { dvander@251: if (path[i] == '/') { dvander@251: name = (char *)calloc(len - i, sizeof(char)); dvander@251: if (!*name) dvander@251: return false; dvander@251: dvander@251: strcpy(*name, &path[i + 1]); dvander@251: dvander@251: base = (char *)calloc(i + 1, sizeof(char)); dvander@251: if (!*base) dvander@251: return false; dvander@251: dvander@251: memcpy(*base, path, i); dvander@251: (*base)[i] = '\0'; dvander@251: return true; dvander@251: } dvander@251: } dvander@251: dvander@251: // The path should have been absolute, which contains at least one separator. dvander@251: return false; dvander@251: } dvander@251: dvander@251: const char * dvander@251: OS::PathSeparator() dvander@251: { dvander@251: return "/"; dvander@251: } dvander@251: