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 <unistd.h> 33 #include <errno.h> 34 #include <time.h> 35 36 #include <sys/socket.h> 37 #include <sys/resource.h> 38 #include <sys/time.h> 39 #include <sys/types.h> 40 41 #include <arpa/inet.h> 42 #include <netinet/in.h> 43 #include <netdb.h> 44 45 #if defined(ANDROID) 46 #define LOG_TAG "v8" 47 #include <utils/Log.h> // LOG_PRI_VA 48 #endif 49 50 #include "v8.h" 51 52 #include "platform.h" 53 54 namespace v8 { 55 namespace internal { 56 57 // ---------------------------------------------------------------------------- 58 // Math functions 59 60 double modulo(double x, double y) { 61 return fmod(x, y); 62 } 63 64 65 double OS::nan_value() { 66 // NAN from math.h is defined in C99 and not in POSIX. 67 return NAN; 68 } 69 70 71 // ---------------------------------------------------------------------------- 72 // POSIX date/time support. 73 // 74 75 int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { 76 struct rusage usage; 77 78 if (getrusage(RUSAGE_SELF, &usage) < 0) return -1; 79 *secs = usage.ru_utime.tv_sec; 80 *usecs = usage.ru_utime.tv_usec; 81 return 0; 82 } 83 84 85 double OS::TimeCurrentMillis() { 86 struct timeval tv; 87 if (gettimeofday(&tv, NULL) < 0) return 0.0; 88 return (static_cast<double>(tv.tv_sec) * 1000) + 89 (static_cast<double>(tv.tv_usec) / 1000); 90 } 91 92 93 int64_t OS::Ticks() { 94 // gettimeofday has microsecond resolution. 95 struct timeval tv; 96 if (gettimeofday(&tv, NULL) < 0) 97 return 0; 98 return (static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec; 99 } 100 101 102 double OS::DaylightSavingsOffset(double time) { 103 if (isnan(time)) return nan_value(); 104 time_t tv = static_cast<time_t>(floor(time/msPerSecond)); 105 struct tm* t = localtime(&tv); 106 if (NULL == t) return nan_value(); 107 return t->tm_isdst > 0 ? 3600 * msPerSecond : 0; 108 } 109 110 111 int OS::GetLastError() { 112 return errno; 113 } 114 115 116 // ---------------------------------------------------------------------------- 117 // POSIX stdio support. 118 // 119 120 FILE* OS::FOpen(const char* path, const char* mode) { 121 return fopen(path, mode); 122 } 123 124 125 bool OS::Remove(const char* path) { 126 return (remove(path) == 0); 127 } 128 129 130 const char* const OS::LogFileOpenMode = "w"; 131 132 133 void OS::Print(const char* format, ...) { 134 va_list args; 135 va_start(args, format); 136 VPrint(format, args); 137 va_end(args); 138 } 139 140 141 void OS::VPrint(const char* format, va_list args) { 142 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT) 143 LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args); 144 #else 145 vprintf(format, args); 146 #endif 147 } 148 149 150 void OS::FPrint(FILE* out, const char* format, ...) { 151 va_list args; 152 va_start(args, format); 153 VFPrint(out, format, args); 154 va_end(args); 155 } 156 157 158 void OS::VFPrint(FILE* out, const char* format, va_list args) { 159 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT) 160 LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args); 161 #else 162 vfprintf(out, format, args); 163 #endif 164 } 165 166 167 void OS::PrintError(const char* format, ...) { 168 va_list args; 169 va_start(args, format); 170 VPrintError(format, args); 171 va_end(args); 172 } 173 174 175 void OS::VPrintError(const char* format, va_list args) { 176 #if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT) 177 LOG_PRI_VA(ANDROID_LOG_ERROR, LOG_TAG, format, args); 178 #else 179 vfprintf(stderr, format, args); 180 #endif 181 } 182 183 184 int OS::SNPrintF(Vector<char> str, const char* format, ...) { 185 va_list args; 186 va_start(args, format); 187 int result = VSNPrintF(str, format, args); 188 va_end(args); 189 return result; 190 } 191 192 193 int OS::VSNPrintF(Vector<char> str, 194 const char* format, 195 va_list args) { 196 int n = vsnprintf(str.start(), str.length(), format, args); 197 if (n < 0 || n >= str.length()) { 198 // If the length is zero, the assignment fails. 199 if (str.length() > 0) 200 str[str.length() - 1] = '\0'; 201 return -1; 202 } else { 203 return n; 204 } 205 } 206 207 208 #if defined(V8_TARGET_ARCH_IA32) 209 static OS::MemCopyFunction memcopy_function = NULL; 210 static Mutex* memcopy_function_mutex = OS::CreateMutex(); 211 // Defined in codegen-ia32.cc. 212 OS::MemCopyFunction CreateMemCopyFunction(); 213 214 // Copy memory area to disjoint memory area. 215 void OS::MemCopy(void* dest, const void* src, size_t size) { 216 if (memcopy_function == NULL) { 217 ScopedLock lock(memcopy_function_mutex); 218 if (memcopy_function == NULL) { 219 OS::MemCopyFunction temp = CreateMemCopyFunction(); 220 MemoryBarrier(); 221 memcopy_function = temp; 222 } 223 } 224 // Note: here we rely on dependent reads being ordered. This is true 225 // on all architectures we currently support. 226 (*memcopy_function)(dest, src, size); 227 #ifdef DEBUG 228 CHECK_EQ(0, memcmp(dest, src, size)); 229 #endif 230 } 231 #endif // V8_TARGET_ARCH_IA32 232 233 // ---------------------------------------------------------------------------- 234 // POSIX string support. 235 // 236 237 char* OS::StrChr(char* str, int c) { 238 return strchr(str, c); 239 } 240 241 242 void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) { 243 strncpy(dest.start(), src, n); 244 } 245 246 247 // ---------------------------------------------------------------------------- 248 // POSIX socket support. 249 // 250 251 class POSIXSocket : public Socket { 252 public: 253 explicit POSIXSocket() { 254 // Create the socket. 255 socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 256 if (IsValid()) { 257 // Allow rapid reuse. 258 static const int kOn = 1; 259 int ret = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, 260 &kOn, sizeof(kOn)); 261 ASSERT(ret == 0); 262 USE(ret); 263 } 264 } 265 explicit POSIXSocket(int socket): socket_(socket) { } 266 virtual ~POSIXSocket() { Shutdown(); } 267 268 // Server initialization. 269 bool Bind(const int port); 270 bool Listen(int backlog) const; 271 Socket* Accept() const; 272 273 // Client initialization. 274 bool Connect(const char* host, const char* port); 275 276 // Shutdown socket for both read and write. 277 bool Shutdown(); 278 279 // Data Transimission 280 int Send(const char* data, int len) const; 281 int Receive(char* data, int len) const; 282 283 bool SetReuseAddress(bool reuse_address); 284 285 bool IsValid() const { return socket_ != -1; } 286 287 private: 288 int socket_; 289 }; 290 291 292 bool POSIXSocket::Bind(const int port) { 293 if (!IsValid()) { 294 return false; 295 } 296 297 sockaddr_in addr; 298 memset(&addr, 0, sizeof(addr)); 299 addr.sin_family = AF_INET; 300 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 301 addr.sin_port = htons(port); 302 int status = bind(socket_, 303 BitCast<struct sockaddr *>(&addr), 304 sizeof(addr)); 305 return status == 0; 306 } 307 308 309 bool POSIXSocket::Listen(int backlog) const { 310 if (!IsValid()) { 311 return false; 312 } 313 314 int status = listen(socket_, backlog); 315 return status == 0; 316 } 317 318 319 Socket* POSIXSocket::Accept() const { 320 if (!IsValid()) { 321 return NULL; 322 } 323 324 int socket = accept(socket_, NULL, NULL); 325 if (socket == -1) { 326 return NULL; 327 } else { 328 return new POSIXSocket(socket); 329 } 330 } 331 332 333 bool POSIXSocket::Connect(const char* host, const char* port) { 334 if (!IsValid()) { 335 return false; 336 } 337 338 // Lookup host and port. 339 struct addrinfo *result = NULL; 340 struct addrinfo hints; 341 memset(&hints, 0, sizeof(addrinfo)); 342 hints.ai_family = AF_INET; 343 hints.ai_socktype = SOCK_STREAM; 344 hints.ai_protocol = IPPROTO_TCP; 345 int status = getaddrinfo(host, port, &hints, &result); 346 if (status != 0) { 347 return false; 348 } 349 350 // Connect. 351 status = connect(socket_, result->ai_addr, result->ai_addrlen); 352 freeaddrinfo(result); 353 return status == 0; 354 } 355 356 357 bool POSIXSocket::Shutdown() { 358 if (IsValid()) { 359 // Shutdown socket for both read and write. 360 int status = shutdown(socket_, SHUT_RDWR); 361 close(socket_); 362 socket_ = -1; 363 return status == 0; 364 } 365 return true; 366 } 367 368 369 int POSIXSocket::Send(const char* data, int len) const { 370 int status = send(socket_, data, len, 0); 371 return status; 372 } 373 374 375 int POSIXSocket::Receive(char* data, int len) const { 376 int status = recv(socket_, data, len, 0); 377 return status; 378 } 379 380 381 bool POSIXSocket::SetReuseAddress(bool reuse_address) { 382 int on = reuse_address ? 1 : 0; 383 int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 384 return status == 0; 385 } 386 387 388 bool Socket::Setup() { 389 // Nothing to do on POSIX. 390 return true; 391 } 392 393 394 int Socket::LastError() { 395 return errno; 396 } 397 398 399 uint16_t Socket::HToN(uint16_t value) { 400 return htons(value); 401 } 402 403 404 uint16_t Socket::NToH(uint16_t value) { 405 return ntohs(value); 406 } 407 408 409 uint32_t Socket::HToN(uint32_t value) { 410 return htonl(value); 411 } 412 413 414 uint32_t Socket::NToH(uint32_t value) { 415 return ntohl(value); 416 } 417 418 419 Socket* OS::CreateSocket() { 420 return new POSIXSocket(); 421 } 422 423 424 } } // namespace v8::internal 425