1 // Copyright 2011 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 // Platform specific code for POSIX goes here. This is not a platform on its 29 // own but contains the parts which are the same across POSIX platforms Linux, 30 // Mac OS, FreeBSD and OpenBSD. 31 32 #include "platform-posix.h" 33 34 #include <unistd.h> 35 #include <errno.h> 36 #include <time.h> 37 38 #include <sys/mman.h> 39 #include <sys/socket.h> 40 #include <sys/resource.h> 41 #include <sys/time.h> 42 #include <sys/types.h> 43 #include <sys/stat.h> 44 45 #include <arpa/inet.h> 46 #include <netinet/in.h> 47 #include <netdb.h> 48 49 #undef MAP_TYPE 50 51 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT) 52 #define LOG_TAG "v8" 53 #include <android/log.h> 54 #endif 55 56 #include "v8.h" 57 58 #include "codegen.h" 59 #include "platform.h" 60 61 namespace v8 { 62 namespace internal { 63 64 65 // Maximum size of the virtual memory. 0 means there is no artificial 66 // limit. 67 68 intptr_t OS::MaxVirtualMemory() { 69 struct rlimit limit; 70 int result = getrlimit(RLIMIT_DATA, &limit); 71 if (result != 0) return 0; 72 return limit.rlim_cur; 73 } 74 75 76 intptr_t OS::CommitPageSize() { 77 static intptr_t page_size = getpagesize(); 78 return page_size; 79 } 80 81 82 #ifndef __CYGWIN__ 83 // Get rid of writable permission on code allocations. 84 void OS::ProtectCode(void* address, const size_t size) { 85 mprotect(address, size, PROT_READ | PROT_EXEC); 86 } 87 88 89 // Create guard pages. 90 void OS::Guard(void* address, const size_t size) { 91 mprotect(address, size, PROT_NONE); 92 } 93 #endif // __CYGWIN__ 94 95 96 void* OS::GetRandomMmapAddr() { 97 Isolate* isolate = Isolate::UncheckedCurrent(); 98 // Note that the current isolate isn't set up in a call path via 99 // CpuFeatures::Probe. We don't care about randomization in this case because 100 // the code page is immediately freed. 101 if (isolate != NULL) { 102 #ifdef V8_TARGET_ARCH_X64 103 uint64_t rnd1 = V8::RandomPrivate(isolate); 104 uint64_t rnd2 = V8::RandomPrivate(isolate); 105 uint64_t raw_addr = (rnd1 << 32) ^ rnd2; 106 // Currently available CPUs have 48 bits of virtual addressing. Truncate 107 // the hint address to 46 bits to give the kernel a fighting chance of 108 // fulfilling our placement request. 109 raw_addr &= V8_UINT64_C(0x3ffffffff000); 110 #else 111 uint32_t raw_addr = V8::RandomPrivate(isolate); 112 // The range 0x20000000 - 0x60000000 is relatively unpopulated across a 113 // variety of ASLR modes (PAE kernel, NX compat mode, etc) and on macos 114 // 10.6 and 10.7. 115 raw_addr &= 0x3ffff000; 116 raw_addr += 0x20000000; 117 #endif 118 return reinterpret_cast<void*>(raw_addr); 119 } 120 return NULL; 121 } 122 123 124 // ---------------------------------------------------------------------------- 125 // Math functions 126 127 double modulo(double x, double y) { 128 return fmod(x, y); 129 } 130 131 132 #define UNARY_MATH_FUNCTION(name, generator) \ 133 static UnaryMathFunction fast_##name##_function = NULL; \ 134 void init_fast_##name##_function() { \ 135 fast_##name##_function = generator; \ 136 } \ 137 double fast_##name(double x) { \ 138 return (*fast_##name##_function)(x); \ 139 } 140 141 UNARY_MATH_FUNCTION(sin, CreateTranscendentalFunction(TranscendentalCache::SIN)) 142 UNARY_MATH_FUNCTION(cos, CreateTranscendentalFunction(TranscendentalCache::COS)) 143 UNARY_MATH_FUNCTION(tan, CreateTranscendentalFunction(TranscendentalCache::TAN)) 144 UNARY_MATH_FUNCTION(log, CreateTranscendentalFunction(TranscendentalCache::LOG)) 145 UNARY_MATH_FUNCTION(sqrt, CreateSqrtFunction()) 146 147 #undef MATH_FUNCTION 148 149 150 void MathSetup() { 151 init_fast_sin_function(); 152 init_fast_cos_function(); 153 init_fast_tan_function(); 154 init_fast_log_function(); 155 init_fast_sqrt_function(); 156 } 157 158 159 double OS::nan_value() { 160 // NAN from math.h is defined in C99 and not in POSIX. 161 return NAN; 162 } 163 164 165 // ---------------------------------------------------------------------------- 166 // POSIX date/time support. 167 // 168 169 int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { 170 struct rusage usage; 171 172 if (getrusage(RUSAGE_SELF, &usage) < 0) return -1; 173 *secs = usage.ru_utime.tv_sec; 174 *usecs = usage.ru_utime.tv_usec; 175 return 0; 176 } 177 178 179 double OS::TimeCurrentMillis() { 180 struct timeval tv; 181 if (gettimeofday(&tv, NULL) < 0) return 0.0; 182 return (static_cast<double>(tv.tv_sec) * 1000) + 183 (static_cast<double>(tv.tv_usec) / 1000); 184 } 185 186 187 int64_t OS::Ticks() { 188 // gettimeofday has microsecond resolution. 189 struct timeval tv; 190 if (gettimeofday(&tv, NULL) < 0) 191 return 0; 192 return (static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec; 193 } 194 195 196 double OS::DaylightSavingsOffset(double time) { 197 if (isnan(time)) return nan_value(); 198 time_t tv = static_cast<time_t>(floor(time/msPerSecond)); 199 struct tm* t = localtime(&tv); 200 if (NULL == t) return nan_value(); 201 return t->tm_isdst > 0 ? 3600 * msPerSecond : 0; 202 } 203 204 205 int OS::GetLastError() { 206 return errno; 207 } 208 209 210 // ---------------------------------------------------------------------------- 211 // POSIX stdio support. 212 // 213 214 FILE* OS::FOpen(const char* path, const char* mode) { 215 FILE* file = fopen(path, mode); 216 if (file == NULL) return NULL; 217 struct stat file_stat; 218 if (fstat(fileno(file), &file_stat) != 0) return NULL; 219 bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0); 220 if (is_regular_file) return file; 221 fclose(file); 222 return NULL; 223 } 224 225 226 bool OS::Remove(const char* path) { 227 return (remove(path) == 0); 228 } 229 230 231 FILE* OS::OpenTemporaryFile() { 232 return tmpfile(); 233 } 234 235 236 const char* const OS::LogFileOpenMode = "w"; 237 238 239 void OS::Print(const char* format, ...) { 240 va_list args; 241 va_start(args, format); 242 VPrint(format, args); 243 va_end(args); 244 } 245 246 247 void OS::VPrint(const char* format, va_list args) { 248 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT) 249 __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args); 250 #else 251 vprintf(format, args); 252 #endif 253 } 254 255 256 void OS::FPrint(FILE* out, const char* format, ...) { 257 va_list args; 258 va_start(args, format); 259 VFPrint(out, format, args); 260 va_end(args); 261 } 262 263 264 void OS::VFPrint(FILE* out, const char* format, va_list args) { 265 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT) 266 __android_log_vprint(ANDROID_LOG_INFO, LOG_TAG, format, args); 267 #else 268 vfprintf(out, format, args); 269 #endif 270 } 271 272 273 void OS::PrintError(const char* format, ...) { 274 va_list args; 275 va_start(args, format); 276 VPrintError(format, args); 277 va_end(args); 278 } 279 280 281 void OS::VPrintError(const char* format, va_list args) { 282 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT) 283 __android_log_vprint(ANDROID_LOG_ERROR, LOG_TAG, format, args); 284 #else 285 vfprintf(stderr, format, args); 286 #endif 287 } 288 289 290 int OS::SNPrintF(Vector<char> str, const char* format, ...) { 291 va_list args; 292 va_start(args, format); 293 int result = VSNPrintF(str, format, args); 294 va_end(args); 295 return result; 296 } 297 298 299 int OS::VSNPrintF(Vector<char> str, 300 const char* format, 301 va_list args) { 302 int n = vsnprintf(str.start(), str.length(), format, args); 303 if (n < 0 || n >= str.length()) { 304 // If the length is zero, the assignment fails. 305 if (str.length() > 0) 306 str[str.length() - 1] = '\0'; 307 return -1; 308 } else { 309 return n; 310 } 311 } 312 313 314 #if defined(V8_TARGET_ARCH_IA32) 315 static OS::MemCopyFunction memcopy_function = NULL; 316 static LazyMutex memcopy_function_mutex = LAZY_MUTEX_INITIALIZER; 317 // Defined in codegen-ia32.cc. 318 OS::MemCopyFunction CreateMemCopyFunction(); 319 320 // Copy memory area to disjoint memory area. 321 void OS::MemCopy(void* dest, const void* src, size_t size) { 322 if (memcopy_function == NULL) { 323 ScopedLock lock(memcopy_function_mutex.Pointer()); 324 if (memcopy_function == NULL) { 325 OS::MemCopyFunction temp = CreateMemCopyFunction(); 326 MemoryBarrier(); 327 memcopy_function = temp; 328 } 329 } 330 // Note: here we rely on dependent reads being ordered. This is true 331 // on all architectures we currently support. 332 (*memcopy_function)(dest, src, size); 333 #ifdef DEBUG 334 CHECK_EQ(0, memcmp(dest, src, size)); 335 #endif 336 } 337 #endif // V8_TARGET_ARCH_IA32 338 339 // ---------------------------------------------------------------------------- 340 // POSIX string support. 341 // 342 343 char* OS::StrChr(char* str, int c) { 344 return strchr(str, c); 345 } 346 347 348 void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) { 349 strncpy(dest.start(), src, n); 350 } 351 352 353 // ---------------------------------------------------------------------------- 354 // POSIX socket support. 355 // 356 357 class POSIXSocket : public Socket { 358 public: 359 explicit POSIXSocket() { 360 // Create the socket. 361 socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 362 if (IsValid()) { 363 // Allow rapid reuse. 364 static const int kOn = 1; 365 int ret = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, 366 &kOn, sizeof(kOn)); 367 ASSERT(ret == 0); 368 USE(ret); 369 } 370 } 371 explicit POSIXSocket(int socket): socket_(socket) { } 372 virtual ~POSIXSocket() { Shutdown(); } 373 374 // Server initialization. 375 bool Bind(const int port); 376 bool Listen(int backlog) const; 377 Socket* Accept() const; 378 379 // Client initialization. 380 bool Connect(const char* host, const char* port); 381 382 // Shutdown socket for both read and write. 383 bool Shutdown(); 384 385 // Data Transimission 386 int Send(const char* data, int len) const; 387 int Receive(char* data, int len) const; 388 389 bool SetReuseAddress(bool reuse_address); 390 391 bool IsValid() const { return socket_ != -1; } 392 393 private: 394 int socket_; 395 }; 396 397 398 bool POSIXSocket::Bind(const int port) { 399 if (!IsValid()) { 400 return false; 401 } 402 403 sockaddr_in addr; 404 memset(&addr, 0, sizeof(addr)); 405 addr.sin_family = AF_INET; 406 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 407 addr.sin_port = htons(port); 408 int status = bind(socket_, 409 BitCast<struct sockaddr *>(&addr), 410 sizeof(addr)); 411 return status == 0; 412 } 413 414 415 bool POSIXSocket::Listen(int backlog) const { 416 if (!IsValid()) { 417 return false; 418 } 419 420 int status = listen(socket_, backlog); 421 return status == 0; 422 } 423 424 425 Socket* POSIXSocket::Accept() const { 426 if (!IsValid()) { 427 return NULL; 428 } 429 430 int socket = accept(socket_, NULL, NULL); 431 if (socket == -1) { 432 return NULL; 433 } else { 434 return new POSIXSocket(socket); 435 } 436 } 437 438 439 bool POSIXSocket::Connect(const char* host, const char* port) { 440 if (!IsValid()) { 441 return false; 442 } 443 444 // Lookup host and port. 445 struct addrinfo *result = NULL; 446 struct addrinfo hints; 447 memset(&hints, 0, sizeof(addrinfo)); 448 hints.ai_family = AF_INET; 449 hints.ai_socktype = SOCK_STREAM; 450 hints.ai_protocol = IPPROTO_TCP; 451 int status = getaddrinfo(host, port, &hints, &result); 452 if (status != 0) { 453 return false; 454 } 455 456 // Connect. 457 status = connect(socket_, result->ai_addr, result->ai_addrlen); 458 freeaddrinfo(result); 459 return status == 0; 460 } 461 462 463 bool POSIXSocket::Shutdown() { 464 if (IsValid()) { 465 // Shutdown socket for both read and write. 466 int status = shutdown(socket_, SHUT_RDWR); 467 close(socket_); 468 socket_ = -1; 469 return status == 0; 470 } 471 return true; 472 } 473 474 475 int POSIXSocket::Send(const char* data, int len) const { 476 int status = send(socket_, data, len, 0); 477 return status; 478 } 479 480 481 int POSIXSocket::Receive(char* data, int len) const { 482 int status = recv(socket_, data, len, 0); 483 return status; 484 } 485 486 487 bool POSIXSocket::SetReuseAddress(bool reuse_address) { 488 int on = reuse_address ? 1 : 0; 489 int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 490 return status == 0; 491 } 492 493 494 bool Socket::SetUp() { 495 // Nothing to do on POSIX. 496 return true; 497 } 498 499 500 int Socket::LastError() { 501 return errno; 502 } 503 504 505 uint16_t Socket::HToN(uint16_t value) { 506 return htons(value); 507 } 508 509 510 uint16_t Socket::NToH(uint16_t value) { 511 return ntohs(value); 512 } 513 514 515 uint32_t Socket::HToN(uint32_t value) { 516 return htonl(value); 517 } 518 519 520 uint32_t Socket::NToH(uint32_t value) { 521 return ntohl(value); 522 } 523 524 525 Socket* OS::CreateSocket() { 526 return new POSIXSocket(); 527 } 528 529 530 } } // namespace v8::internal 531