blob: 256dc75f6b918cf1605b46be56e9b7c9625bf819 [file] [log] [blame]
ager@chromium.orgbb29dc92009-03-24 13:25:23 +00001// 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,
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000030// Mac OS, FreeBSD and OpenBSD.
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000031
32#include <unistd.h>
33#include <errno.h>
ager@chromium.org41826e72009-03-30 13:30:57 +000034#include <time.h>
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000035
36#include <sys/socket.h>
ager@chromium.org41826e72009-03-30 13:30:57 +000037#include <sys/resource.h>
38#include <sys/time.h>
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000039#include <sys/types.h>
40
41#include <arpa/inet.h>
42#include <netinet/in.h>
43#include <netdb.h>
44
kasperl@chromium.orge959c182009-07-27 08:59:04 +000045#if defined(ANDROID)
46#define LOG_TAG "v8"
47#include <utils/Log.h> // LOG_PRI_VA
48#endif
49
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000050#include "v8.h"
51
52#include "platform.h"
53
kasperl@chromium.org71affb52009-05-26 05:44:31 +000054namespace v8 {
55namespace internal {
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000056
ager@chromium.org3811b432009-10-28 14:53:37 +000057// ----------------------------------------------------------------------------
58// Math functions
59
60double modulo(double x, double y) {
61 return fmod(x, y);
62}
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000063
sgjesse@chromium.orgac6aa172009-12-04 12:29:05 +000064
65double OS::nan_value() {
66 // NAN from math.h is defined in C99 and not in POSIX.
67 return NAN;
68}
69
70
ager@chromium.orgbb29dc92009-03-24 13:25:23 +000071// ----------------------------------------------------------------------------
ager@chromium.org41826e72009-03-30 13:30:57 +000072// 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
ager@chromium.org41826e72009-03-30 13:30:57 +0000102double OS::DaylightSavingsOffset(double time) {
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000103 if (isnan(time)) return nan_value();
ager@chromium.org41826e72009-03-30 13:30:57 +0000104 time_t tv = static_cast<time_t>(floor(time/msPerSecond));
105 struct tm* t = localtime(&tv);
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000106 if (NULL == t) return nan_value();
ager@chromium.org41826e72009-03-30 13:30:57 +0000107 return t->tm_isdst > 0 ? 3600 * msPerSecond : 0;
108}
109
110
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000111int OS::GetLastError() {
112 return errno;
113}
114
115
ager@chromium.org41826e72009-03-30 13:30:57 +0000116// ----------------------------------------------------------------------------
117// POSIX stdio support.
118//
119
120FILE* OS::FOpen(const char* path, const char* mode) {
121 return fopen(path, mode);
122}
123
124
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000125bool OS::Remove(const char* path) {
126 return (remove(path) == 0);
127}
128
129
ager@chromium.org71daaf62009-04-01 07:22:49 +0000130const char* OS::LogFileOpenMode = "w";
131
132
ager@chromium.org41826e72009-03-30 13:30:57 +0000133void 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
141void OS::VPrint(const char* format, va_list args) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000142#if defined(ANDROID)
143 LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args);
144#else
ager@chromium.org41826e72009-03-30 13:30:57 +0000145 vprintf(format, args);
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000146#endif
ager@chromium.org41826e72009-03-30 13:30:57 +0000147}
148
149
whesse@chromium.org023421e2010-12-21 12:19:12 +0000150void 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
158void OS::VFPrint(FILE* out, const char* format, va_list args) {
159#if defined(ANDROID)
160 LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args);
161#else
162 vfprintf(out, format, args);
163#endif
164}
165
166
ager@chromium.org41826e72009-03-30 13:30:57 +0000167void 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
175void OS::VPrintError(const char* format, va_list args) {
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000176#if defined(ANDROID)
177 LOG_PRI_VA(ANDROID_LOG_ERROR, LOG_TAG, format, args);
178#else
ager@chromium.org41826e72009-03-30 13:30:57 +0000179 vfprintf(stderr, format, args);
kasperl@chromium.orge959c182009-07-27 08:59:04 +0000180#endif
ager@chromium.org41826e72009-03-30 13:30:57 +0000181}
182
183
184int 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
193int 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()) {
whesse@chromium.org023421e2010-12-21 12:19:12 +0000198 // If the length is zero, the assignment fails.
199 if (str.length() > 0)
200 str[str.length() - 1] = '\0';
ager@chromium.org41826e72009-03-30 13:30:57 +0000201 return -1;
202 } else {
203 return n;
204 }
205}
206
207
208// ----------------------------------------------------------------------------
209// POSIX string support.
210//
211
212char* OS::StrChr(char* str, int c) {
213 return strchr(str, c);
214}
215
216
217void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
218 strncpy(dest.start(), src, n);
219}
220
221
222// ----------------------------------------------------------------------------
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000223// POSIX socket support.
224//
225
226class POSIXSocket : public Socket {
227 public:
228 explicit POSIXSocket() {
229 // Create the socket.
230 socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
whesse@chromium.org023421e2010-12-21 12:19:12 +0000231 if (IsValid()) {
232 // Allow rapid reuse.
233 static const int kOn = 1;
234 int ret = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
235 &kOn, sizeof(kOn));
236 ASSERT(ret == 0);
237 USE(ret);
238 }
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000239 }
240 explicit POSIXSocket(int socket): socket_(socket) { }
241 virtual ~POSIXSocket() { Shutdown(); }
242
243 // Server initialization.
244 bool Bind(const int port);
245 bool Listen(int backlog) const;
246 Socket* Accept() const;
247
248 // Client initialization.
249 bool Connect(const char* host, const char* port);
250
251 // Shutdown socket for both read and write.
252 bool Shutdown();
253
254 // Data Transimission
255 int Send(const char* data, int len) const;
256 int Receive(char* data, int len) const;
257
258 bool SetReuseAddress(bool reuse_address);
259
260 bool IsValid() const { return socket_ != -1; }
261
262 private:
263 int socket_;
264};
265
266
267bool POSIXSocket::Bind(const int port) {
268 if (!IsValid()) {
269 return false;
270 }
271
272 sockaddr_in addr;
273 memset(&addr, 0, sizeof(addr));
274 addr.sin_family = AF_INET;
275 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
276 addr.sin_port = htons(port);
277 int status = bind(socket_,
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000278 BitCast<struct sockaddr *>(&addr),
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000279 sizeof(addr));
280 return status == 0;
281}
282
283
284bool POSIXSocket::Listen(int backlog) const {
285 if (!IsValid()) {
286 return false;
287 }
288
289 int status = listen(socket_, backlog);
290 return status == 0;
291}
292
293
294Socket* POSIXSocket::Accept() const {
295 if (!IsValid()) {
296 return NULL;
297 }
298
299 int socket = accept(socket_, NULL, NULL);
300 if (socket == -1) {
301 return NULL;
302 } else {
303 return new POSIXSocket(socket);
304 }
305}
306
307
308bool POSIXSocket::Connect(const char* host, const char* port) {
309 if (!IsValid()) {
310 return false;
311 }
312
313 // Lookup host and port.
314 struct addrinfo *result = NULL;
315 struct addrinfo hints;
316 memset(&hints, 0, sizeof(addrinfo));
317 hints.ai_family = AF_INET;
318 hints.ai_socktype = SOCK_STREAM;
319 hints.ai_protocol = IPPROTO_TCP;
320 int status = getaddrinfo(host, port, &hints, &result);
321 if (status != 0) {
322 return false;
323 }
324
325 // Connect.
326 status = connect(socket_, result->ai_addr, result->ai_addrlen);
327 freeaddrinfo(result);
328 return status == 0;
329}
330
331
332bool POSIXSocket::Shutdown() {
333 if (IsValid()) {
334 // Shutdown socket for both read and write.
335 int status = shutdown(socket_, SHUT_RDWR);
336 close(socket_);
337 socket_ = -1;
338 return status == 0;
339 }
340 return true;
341}
342
343
344int POSIXSocket::Send(const char* data, int len) const {
345 int status = send(socket_, data, len, 0);
346 return status;
347}
348
349
350int POSIXSocket::Receive(char* data, int len) const {
351 int status = recv(socket_, data, len, 0);
352 return status;
353}
354
355
356bool POSIXSocket::SetReuseAddress(bool reuse_address) {
357 int on = reuse_address ? 1 : 0;
358 int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
359 return status == 0;
360}
361
362
363bool Socket::Setup() {
364 // Nothing to do on POSIX.
365 return true;
366}
367
368
369int Socket::LastError() {
370 return errno;
371}
372
373
374uint16_t Socket::HToN(uint16_t value) {
375 return htons(value);
376}
377
378
379uint16_t Socket::NToH(uint16_t value) {
380 return ntohs(value);
381}
382
383
384uint32_t Socket::HToN(uint32_t value) {
385 return htonl(value);
386}
387
388
389uint32_t Socket::NToH(uint32_t value) {
390 return ntohl(value);
391}
392
393
394Socket* OS::CreateSocket() {
395 return new POSIXSocket();
396}
397
398
399} } // namespace v8::internal