Home | History | Annotate | Download | only in src
      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