blob: ab5c0a376870100ec041f5ba4b92d5a305d85518 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +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,
Steve Blockd0582a62009-12-15 09:54:21 +000030// Mac OS, FreeBSD and OpenBSD.
Steve Blocka7e24c12009-10-30 11:49:00 +000031
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
Steve Block3ce2e202009-11-05 08:53:23 +000057// ----------------------------------------------------------------------------
58// Math functions
59
60double modulo(double x, double y) {
61 return fmod(x, y);
62}
Steve Blocka7e24c12009-10-30 11:49:00 +000063
Steve Blockd0582a62009-12-15 09:54:21 +000064
65double OS::nan_value() {
66 // NAN from math.h is defined in C99 and not in POSIX.
67 return NAN;
68}
69
70
Steve Blocka7e24c12009-10-30 11:49:00 +000071// ----------------------------------------------------------------------------
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
Steve Blocka7e24c12009-10-30 11:49:00 +0000102double 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
Iain Merrick75681382010-08-19 15:07:18 +0100111int OS::GetLastError() {
112 return errno;
113}
114
115
Steve Blocka7e24c12009-10-30 11:49:00 +0000116// ----------------------------------------------------------------------------
117// POSIX stdio support.
118//
119
120FILE* OS::FOpen(const char* path, const char* mode) {
121 return fopen(path, mode);
122}
123
124
125const char* OS::LogFileOpenMode = "w";
126
127
128void OS::Print(const char* format, ...) {
129 va_list args;
130 va_start(args, format);
131 VPrint(format, args);
132 va_end(args);
133}
134
135
136void OS::VPrint(const char* format, va_list args) {
137#if defined(ANDROID)
138 LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args);
139#else
140 vprintf(format, args);
141#endif
142}
143
144
Ben Murdochb0fe1622011-05-05 13:52:32 +0100145void OS::FPrint(FILE* out, const char* format, ...) {
146 va_list args;
147 va_start(args, format);
148 VFPrint(out, format, args);
149 va_end(args);
150}
151
152
153void OS::VFPrint(FILE* out, const char* format, va_list args) {
154#if defined(ANDROID)
155 LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args);
156#else
157 vfprintf(out, format, args);
158#endif
159}
160
161
Steve Blocka7e24c12009-10-30 11:49:00 +0000162void OS::PrintError(const char* format, ...) {
163 va_list args;
164 va_start(args, format);
165 VPrintError(format, args);
166 va_end(args);
167}
168
169
170void OS::VPrintError(const char* format, va_list args) {
171#if defined(ANDROID)
172 LOG_PRI_VA(ANDROID_LOG_ERROR, LOG_TAG, format, args);
173#else
174 vfprintf(stderr, format, args);
175#endif
176}
177
178
179int OS::SNPrintF(Vector<char> str, const char* format, ...) {
180 va_list args;
181 va_start(args, format);
182 int result = VSNPrintF(str, format, args);
183 va_end(args);
184 return result;
185}
186
187
188int OS::VSNPrintF(Vector<char> str,
189 const char* format,
190 va_list args) {
191 int n = vsnprintf(str.start(), str.length(), format, args);
192 if (n < 0 || n >= str.length()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100193 // If the length is zero, the assignment fails.
194 if (str.length() > 0)
195 str[str.length() - 1] = '\0';
Steve Blocka7e24c12009-10-30 11:49:00 +0000196 return -1;
197 } else {
198 return n;
199 }
200}
201
202
203// ----------------------------------------------------------------------------
204// POSIX string support.
205//
206
207char* OS::StrChr(char* str, int c) {
208 return strchr(str, c);
209}
210
211
212void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
213 strncpy(dest.start(), src, n);
214}
215
216
217// ----------------------------------------------------------------------------
218// POSIX socket support.
219//
220
221class POSIXSocket : public Socket {
222 public:
223 explicit POSIXSocket() {
224 // Create the socket.
225 socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100226 if (IsValid()) {
227 // Allow rapid reuse.
228 static const int kOn = 1;
229 int ret = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
230 &kOn, sizeof(kOn));
231 ASSERT(ret == 0);
232 USE(ret);
233 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000234 }
235 explicit POSIXSocket(int socket): socket_(socket) { }
236 virtual ~POSIXSocket() { Shutdown(); }
237
238 // Server initialization.
239 bool Bind(const int port);
240 bool Listen(int backlog) const;
241 Socket* Accept() const;
242
243 // Client initialization.
244 bool Connect(const char* host, const char* port);
245
246 // Shutdown socket for both read and write.
247 bool Shutdown();
248
249 // Data Transimission
250 int Send(const char* data, int len) const;
251 int Receive(char* data, int len) const;
252
253 bool SetReuseAddress(bool reuse_address);
254
255 bool IsValid() const { return socket_ != -1; }
256
257 private:
258 int socket_;
259};
260
261
262bool POSIXSocket::Bind(const int port) {
263 if (!IsValid()) {
264 return false;
265 }
266
267 sockaddr_in addr;
268 memset(&addr, 0, sizeof(addr));
269 addr.sin_family = AF_INET;
270 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
271 addr.sin_port = htons(port);
272 int status = bind(socket_,
Iain Merrick75681382010-08-19 15:07:18 +0100273 BitCast<struct sockaddr *>(&addr),
Steve Blocka7e24c12009-10-30 11:49:00 +0000274 sizeof(addr));
275 return status == 0;
276}
277
278
279bool POSIXSocket::Listen(int backlog) const {
280 if (!IsValid()) {
281 return false;
282 }
283
284 int status = listen(socket_, backlog);
285 return status == 0;
286}
287
288
289Socket* POSIXSocket::Accept() const {
290 if (!IsValid()) {
291 return NULL;
292 }
293
294 int socket = accept(socket_, NULL, NULL);
295 if (socket == -1) {
296 return NULL;
297 } else {
298 return new POSIXSocket(socket);
299 }
300}
301
302
303bool POSIXSocket::Connect(const char* host, const char* port) {
304 if (!IsValid()) {
305 return false;
306 }
307
308 // Lookup host and port.
309 struct addrinfo *result = NULL;
310 struct addrinfo hints;
311 memset(&hints, 0, sizeof(addrinfo));
312 hints.ai_family = AF_INET;
313 hints.ai_socktype = SOCK_STREAM;
314 hints.ai_protocol = IPPROTO_TCP;
315 int status = getaddrinfo(host, port, &hints, &result);
316 if (status != 0) {
317 return false;
318 }
319
320 // Connect.
321 status = connect(socket_, result->ai_addr, result->ai_addrlen);
322 freeaddrinfo(result);
323 return status == 0;
324}
325
326
327bool POSIXSocket::Shutdown() {
328 if (IsValid()) {
329 // Shutdown socket for both read and write.
330 int status = shutdown(socket_, SHUT_RDWR);
331 close(socket_);
332 socket_ = -1;
333 return status == 0;
334 }
335 return true;
336}
337
338
339int POSIXSocket::Send(const char* data, int len) const {
340 int status = send(socket_, data, len, 0);
341 return status;
342}
343
344
345int POSIXSocket::Receive(char* data, int len) const {
346 int status = recv(socket_, data, len, 0);
347 return status;
348}
349
350
351bool POSIXSocket::SetReuseAddress(bool reuse_address) {
352 int on = reuse_address ? 1 : 0;
353 int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
354 return status == 0;
355}
356
357
358bool Socket::Setup() {
359 // Nothing to do on POSIX.
360 return true;
361}
362
363
364int Socket::LastError() {
365 return errno;
366}
367
368
369uint16_t Socket::HToN(uint16_t value) {
370 return htons(value);
371}
372
373
374uint16_t Socket::NToH(uint16_t value) {
375 return ntohs(value);
376}
377
378
379uint32_t Socket::HToN(uint32_t value) {
380 return htonl(value);
381}
382
383
384uint32_t Socket::NToH(uint32_t value) {
385 return ntohl(value);
386}
387
388
389Socket* OS::CreateSocket() {
390 return new POSIXSocket();
391}
392
393
394} } // namespace v8::internal