platform-posix.cc revision 888f6729be6a6f6fbe246cb5a9f122e2dbe455b7
1// Copyright 2009 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 54namespace v8 { 55namespace internal { 56 57// ---------------------------------------------------------------------------- 58// Math functions 59 60double modulo(double x, double y) { 61 return fmod(x, y); 62} 63 64 65double 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 75int 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 85double 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 93int64_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 102double 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// ---------------------------------------------------------------------------- 112// POSIX stdio support. 113// 114 115FILE* OS::FOpen(const char* path, const char* mode) { 116 return fopen(path, mode); 117} 118 119 120const char* OS::LogFileOpenMode = "w"; 121 122 123void OS::Print(const char* format, ...) { 124 va_list args; 125 va_start(args, format); 126 VPrint(format, args); 127 va_end(args); 128} 129 130 131void OS::VPrint(const char* format, va_list args) { 132#if defined(ANDROID) 133 LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args); 134#else 135 vprintf(format, args); 136#endif 137} 138 139 140void OS::PrintError(const char* format, ...) { 141 va_list args; 142 va_start(args, format); 143 VPrintError(format, args); 144 va_end(args); 145} 146 147 148void OS::VPrintError(const char* format, va_list args) { 149#if defined(ANDROID) 150 LOG_PRI_VA(ANDROID_LOG_ERROR, LOG_TAG, format, args); 151#else 152 vfprintf(stderr, format, args); 153#endif 154} 155 156 157int OS::SNPrintF(Vector<char> str, const char* format, ...) { 158 va_list args; 159 va_start(args, format); 160 int result = VSNPrintF(str, format, args); 161 va_end(args); 162 return result; 163} 164 165 166int OS::VSNPrintF(Vector<char> str, 167 const char* format, 168 va_list args) { 169 int n = vsnprintf(str.start(), str.length(), format, args); 170 if (n < 0 || n >= str.length()) { 171 str[str.length() - 1] = '\0'; 172 return -1; 173 } else { 174 return n; 175 } 176} 177 178 179// ---------------------------------------------------------------------------- 180// POSIX string support. 181// 182 183char* OS::StrChr(char* str, int c) { 184 return strchr(str, c); 185} 186 187 188void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) { 189 strncpy(dest.start(), src, n); 190} 191 192 193// ---------------------------------------------------------------------------- 194// POSIX socket support. 195// 196 197class POSIXSocket : public Socket { 198 public: 199 explicit POSIXSocket() { 200 // Create the socket. 201 socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 202 } 203 explicit POSIXSocket(int socket): socket_(socket) { } 204 virtual ~POSIXSocket() { Shutdown(); } 205 206 // Server initialization. 207 bool Bind(const int port); 208 bool Listen(int backlog) const; 209 Socket* Accept() const; 210 211 // Client initialization. 212 bool Connect(const char* host, const char* port); 213 214 // Shutdown socket for both read and write. 215 bool Shutdown(); 216 217 // Data Transimission 218 int Send(const char* data, int len) const; 219 int Receive(char* data, int len) const; 220 221 bool SetReuseAddress(bool reuse_address); 222 223 bool IsValid() const { return socket_ != -1; } 224 225 private: 226 int socket_; 227}; 228 229 230bool POSIXSocket::Bind(const int port) { 231 if (!IsValid()) { 232 return false; 233 } 234 235 sockaddr_in addr; 236 memset(&addr, 0, sizeof(addr)); 237 addr.sin_family = AF_INET; 238 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 239 addr.sin_port = htons(port); 240 int status = bind(socket_, 241 reinterpret_cast<struct sockaddr *>(&addr), 242 sizeof(addr)); 243 return status == 0; 244} 245 246 247bool POSIXSocket::Listen(int backlog) const { 248 if (!IsValid()) { 249 return false; 250 } 251 252 int status = listen(socket_, backlog); 253 return status == 0; 254} 255 256 257Socket* POSIXSocket::Accept() const { 258 if (!IsValid()) { 259 return NULL; 260 } 261 262 int socket = accept(socket_, NULL, NULL); 263 if (socket == -1) { 264 return NULL; 265 } else { 266 return new POSIXSocket(socket); 267 } 268} 269 270 271bool POSIXSocket::Connect(const char* host, const char* port) { 272 if (!IsValid()) { 273 return false; 274 } 275 276 // Lookup host and port. 277 struct addrinfo *result = NULL; 278 struct addrinfo hints; 279 memset(&hints, 0, sizeof(addrinfo)); 280 hints.ai_family = AF_INET; 281 hints.ai_socktype = SOCK_STREAM; 282 hints.ai_protocol = IPPROTO_TCP; 283 int status = getaddrinfo(host, port, &hints, &result); 284 if (status != 0) { 285 return false; 286 } 287 288 // Connect. 289 status = connect(socket_, result->ai_addr, result->ai_addrlen); 290 freeaddrinfo(result); 291 return status == 0; 292} 293 294 295bool POSIXSocket::Shutdown() { 296 if (IsValid()) { 297 // Shutdown socket for both read and write. 298 int status = shutdown(socket_, SHUT_RDWR); 299 close(socket_); 300 socket_ = -1; 301 return status == 0; 302 } 303 return true; 304} 305 306 307int POSIXSocket::Send(const char* data, int len) const { 308 int status = send(socket_, data, len, 0); 309 return status; 310} 311 312 313int POSIXSocket::Receive(char* data, int len) const { 314 int status = recv(socket_, data, len, 0); 315 return status; 316} 317 318 319bool POSIXSocket::SetReuseAddress(bool reuse_address) { 320 int on = reuse_address ? 1 : 0; 321 int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); 322 return status == 0; 323} 324 325 326bool Socket::Setup() { 327 // Nothing to do on POSIX. 328 return true; 329} 330 331 332int Socket::LastError() { 333 return errno; 334} 335 336 337uint16_t Socket::HToN(uint16_t value) { 338 return htons(value); 339} 340 341 342uint16_t Socket::NToH(uint16_t value) { 343 return ntohs(value); 344} 345 346 347uint32_t Socket::HToN(uint32_t value) { 348 return htonl(value); 349} 350 351 352uint32_t Socket::NToH(uint32_t value) { 353 return ntohl(value); 354} 355 356 357Socket* OS::CreateSocket() { 358 return new POSIXSocket(); 359} 360 361 362} } // namespace v8::internal 363