this repo has no description
at trunk 221 lines 5.1 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "os.h" 3 4#include <fcntl.h> 5#include <sys/mman.h> 6#include <sys/stat.h> 7#include <time.h> 8#include <unistd.h> 9 10#include <cerrno> 11#include <csignal> 12#include <cstdio> 13#include <cstdlib> 14#include <cstring> 15 16#include "globals.h" 17#include "utils.h" 18 19namespace py { 20 21// clang-format off 22#define V(SIGNAL) { #SIGNAL, SIGNAL } 23const OS::Signal OS::kStandardSignals[] = { 24 V(SIGABRT), 25 V(SIGALRM), 26 V(SIGBUS), 27 V(SIGCHLD), 28 V(SIGCONT), 29 V(SIGFPE), 30 V(SIGHUP), 31 V(SIGILL), 32 V(SIGINT), 33 V(SIGKILL), 34 V(SIGPIPE), 35 V(SIGQUIT), 36 V(SIGSEGV), 37 V(SIGSTOP), 38 V(SIGTERM), 39 V(SIGTRAP), 40 V(SIGTSTP), 41 V(SIGTTIN), 42 V(SIGTTOU), 43 V(SIGURG), 44 V(SIGUSR1), 45 V(SIGUSR2), 46 V(SIGXCPU), 47 V(SIGXFSZ), 48 { nullptr, 0 }, 49}; 50#undef V 51// clang-format on 52 53byte* OS::allocateMemory(word size, word* allocated_size) { 54 size = Utils::roundUp(size, kPageSize); 55 if (allocated_size != nullptr) *allocated_size = size; 56 int prot = PROT_READ | PROT_WRITE; 57 int flags = MAP_PRIVATE | MAP_ANONYMOUS; 58 void* result = ::mmap(nullptr, size, prot, flags, -1, 0); 59 CHECK(result != MAP_FAILED, "mmap failure"); 60 return static_cast<byte*>(result); 61} 62 63bool OS::access(const char* path, int mode) { 64 return ::access(path, mode) == 0; 65} 66 67int OS::pageSize() { return ::sysconf(_SC_PAGESIZE); } 68 69bool OS::protectMemory(byte* address, word size, Protection mode) { 70 DCHECK(size >= 0, "invalid size %ld", size); 71 int prot; 72 switch (mode) { 73 case kNoAccess: 74 prot = PROT_NONE; 75 break; 76 case kReadWrite: 77 prot = PROT_READ | PROT_WRITE; 78 break; 79 case kReadExecute: 80 prot = PROT_READ | PROT_EXEC; 81 break; 82 case kReadWriteExecute: 83 prot = PROT_READ | PROT_WRITE | PROT_EXEC; 84 break; 85 default: 86 std::abort(); 87 } 88 int result = mprotect(address, size, prot); 89 CHECK(result == 0, "mprotect failure"); 90 return result == 0; 91} 92 93bool OS::freeMemory(byte* ptr, word size) { 94 DCHECK(size >= 0, "invalid size %ld", size); 95 int result = ::munmap(ptr, size); 96 CHECK(result != -1, "munmap failure"); 97 return result == 0; 98} 99 100class ScopedFd { 101 public: 102 explicit ScopedFd(int fd) : fd_(fd) {} 103 104 ~ScopedFd() { 105 if (fd_ != -1) { 106 close(fd_); 107 } 108 } 109 110 int get() const { return fd_; } 111 112 private: 113 int fd_; 114 DISALLOW_COPY_AND_ASSIGN(ScopedFd); 115}; 116 117bool OS::secureRandom(byte* ptr, word size) { 118 DCHECK(size >= 0, "invalid size %ld", size); 119 ScopedFd fd(::open("/dev/urandom", O_RDONLY)); 120 if (fd.get() == -1) { 121 return false; 122 } 123 do { 124 word result; 125 do { 126 result = ::read(fd.get(), ptr, size); 127 } while (result == -1 && errno == EINTR); 128 if (result == -1) { 129 break; 130 } 131 size -= result; 132 ptr += result; 133 } while (size > 0); 134 return size == 0; 135} 136 137byte* OS::readFile(FILE* fp, word* len_out) { 138 std::fseek(fp, 0, SEEK_END); 139 word length = std::ftell(fp); 140 std::fseek(fp, 0, SEEK_SET); 141 142 word capacity = length <= 0 ? 4096 : length; 143 byte* buffer = reinterpret_cast<byte*>(std::malloc(capacity)); 144 CHECK(buffer != nullptr, "out of memory"); 145 146 length = 0; 147 do { 148 if (length == capacity) { 149 capacity *= 2; 150 buffer = reinterpret_cast<byte*>(std::realloc(buffer, capacity)); 151 CHECK(buffer != nullptr, "out of memory"); 152 } 153 length += std::fread(buffer + length, 1, capacity - length, fp); 154 } while (capacity > 0 && length >= capacity); 155 if (ferror(fp)) { 156 fprintf(stderr, "file read error: %s\n", std::strerror(errno)); 157 std::free(buffer); 158 return nullptr; 159 } 160 *len_out = length; 161 return buffer; 162} 163 164bool OS::dirExists(const char* dir) { 165 struct stat st; 166 int err = ::stat(dir, &st); 167 if (err == 0 && (st.st_mode & S_IFDIR)) { 168 return true; 169 } 170 if (errno != 0 && errno != ENOENT) { 171 std::fprintf(stderr, "stat error: %s %s\n", dir, std::strerror(errno)); 172 } 173 return false; 174} 175 176bool OS::fileExists(const char* file) { 177 struct stat st; 178 int err = ::stat(file, &st); 179 if (err == 0 && S_ISREG(st.st_mode)) { 180 return true; 181 } 182 if (errno != 0 && errno != ENOENT) { 183 std::fprintf(stderr, "stat error: %s %s\n", file, std::strerror(errno)); 184 } 185 return false; 186} 187 188char* OS::readLink(const char* path) { 189 char* buffer = nullptr; 190 for (ssize_t size = 64;; size *= 2) { 191 buffer = reinterpret_cast<char*>(std::realloc(buffer, size)); 192 CHECK(buffer != nullptr, "out of memory"); 193 ssize_t res = ::readlink(path, buffer, size); 194 if (res == -1) { 195 std::free(buffer); 196 return nullptr; 197 } 198 if (res < size - 1) { 199 buffer[res] = '\0'; 200 return buffer; 201 } 202 } 203} 204 205double OS::currentTime() { 206 timespec ts; 207 int err = clock_gettime(CLOCK_REALTIME, &ts); 208 CHECK(!err, "clock_gettime failure"); 209 210 if (ts.tv_nsec == 0) { 211 return static_cast<double>(ts.tv_sec); 212 } 213 214 int64_t nanoseconds = ts.tv_sec * kNanosecondsPerSecond; 215 nanoseconds += ts.tv_nsec; 216 double result = static_cast<double>(nanoseconds); 217 result /= kNanosecondsPerSecond; 218 return result; 219} 220 221} // namespace py