blob: 52cf02963a0580f2cd17d0aca5f2025b6cbe38a5 [file] [log] [blame]
Ben Murdoch8b112d22011-06-08 16:22:53 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// 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
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000036#include <sys/mman.h>
Steve Blocka7e24c12009-10-30 11:49:00 +000037#include <sys/socket.h>
38#include <sys/resource.h>
39#include <sys/time.h>
40#include <sys/types.h>
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000041#include <sys/stat.h>
Steve Blocka7e24c12009-10-30 11:49:00 +000042
43#include <arpa/inet.h>
44#include <netinet/in.h>
45#include <netdb.h>
46
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000047#undef MAP_TYPE
48
Steve Blocka7e24c12009-10-30 11:49:00 +000049#if defined(ANDROID)
50#define LOG_TAG "v8"
51#include <utils/Log.h> // LOG_PRI_VA
52#endif
53
54#include "v8.h"
55
56#include "platform.h"
57
58namespace v8 {
59namespace internal {
60
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000061
62// Maximum size of the virtual memory. 0 means there is no artificial
63// limit.
64
65intptr_t OS::MaxVirtualMemory() {
66 struct rlimit limit;
67 int result = getrlimit(RLIMIT_DATA, &limit);
68 if (result != 0) return 0;
69 return limit.rlim_cur;
70}
71
72
Ben Murdoch69a99ed2011-11-30 16:03:39 +000073#ifndef __CYGWIN__
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000074// Get rid of writable permission on code allocations.
75void OS::ProtectCode(void* address, const size_t size) {
76 mprotect(address, size, PROT_READ | PROT_EXEC);
77}
78
79
80// Create guard pages.
81void OS::Guard(void* address, const size_t size) {
82 mprotect(address, size, PROT_NONE);
83}
Ben Murdoch69a99ed2011-11-30 16:03:39 +000084#endif // __CYGWIN__
Ben Murdoch3fb3ca82011-12-02 17:19:32 +000085
86
Steve Block3ce2e202009-11-05 08:53:23 +000087// ----------------------------------------------------------------------------
88// Math functions
89
90double modulo(double x, double y) {
91 return fmod(x, y);
92}
Steve Blocka7e24c12009-10-30 11:49:00 +000093
Steve Blockd0582a62009-12-15 09:54:21 +000094
95double OS::nan_value() {
96 // NAN from math.h is defined in C99 and not in POSIX.
97 return NAN;
98}
99
100
Steve Blocka7e24c12009-10-30 11:49:00 +0000101// ----------------------------------------------------------------------------
102// POSIX date/time support.
103//
104
105int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) {
106 struct rusage usage;
107
108 if (getrusage(RUSAGE_SELF, &usage) < 0) return -1;
109 *secs = usage.ru_utime.tv_sec;
110 *usecs = usage.ru_utime.tv_usec;
111 return 0;
112}
113
114
115double OS::TimeCurrentMillis() {
116 struct timeval tv;
117 if (gettimeofday(&tv, NULL) < 0) return 0.0;
118 return (static_cast<double>(tv.tv_sec) * 1000) +
119 (static_cast<double>(tv.tv_usec) / 1000);
120}
121
122
123int64_t OS::Ticks() {
124 // gettimeofday has microsecond resolution.
125 struct timeval tv;
126 if (gettimeofday(&tv, NULL) < 0)
127 return 0;
128 return (static_cast<int64_t>(tv.tv_sec) * 1000000) + tv.tv_usec;
129}
130
131
Steve Blocka7e24c12009-10-30 11:49:00 +0000132double OS::DaylightSavingsOffset(double time) {
133 if (isnan(time)) return nan_value();
134 time_t tv = static_cast<time_t>(floor(time/msPerSecond));
135 struct tm* t = localtime(&tv);
136 if (NULL == t) return nan_value();
137 return t->tm_isdst > 0 ? 3600 * msPerSecond : 0;
138}
139
140
Iain Merrick75681382010-08-19 15:07:18 +0100141int OS::GetLastError() {
142 return errno;
143}
144
145
Steve Blocka7e24c12009-10-30 11:49:00 +0000146// ----------------------------------------------------------------------------
147// POSIX stdio support.
148//
149
150FILE* OS::FOpen(const char* path, const char* mode) {
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000151 FILE* file = fopen(path, mode);
152 if (file == NULL) return NULL;
153 struct stat file_stat;
154 if (fstat(fileno(file), &file_stat) != 0) return NULL;
155 bool is_regular_file = ((file_stat.st_mode & S_IFREG) != 0);
156 if (is_regular_file) return file;
157 fclose(file);
158 return NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000159}
160
161
Steve Block1e0659c2011-05-24 12:43:12 +0100162bool OS::Remove(const char* path) {
163 return (remove(path) == 0);
164}
165
166
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000167FILE* OS::OpenTemporaryFile() {
168 return tmpfile();
169}
170
171
Steve Block44f0eee2011-05-26 01:26:41 +0100172const char* const OS::LogFileOpenMode = "w";
Steve Blocka7e24c12009-10-30 11:49:00 +0000173
174
175void OS::Print(const char* format, ...) {
176 va_list args;
177 va_start(args, format);
178 VPrint(format, args);
179 va_end(args);
180}
181
182
183void OS::VPrint(const char* format, va_list args) {
Steve Block44f0eee2011-05-26 01:26:41 +0100184#if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
Steve Blocka7e24c12009-10-30 11:49:00 +0000185 LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args);
186#else
187 vprintf(format, args);
188#endif
189}
190
191
Ben Murdochb0fe1622011-05-05 13:52:32 +0100192void OS::FPrint(FILE* out, const char* format, ...) {
193 va_list args;
194 va_start(args, format);
195 VFPrint(out, format, args);
196 va_end(args);
197}
198
199
200void OS::VFPrint(FILE* out, const char* format, va_list args) {
Steve Block44f0eee2011-05-26 01:26:41 +0100201#if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
Ben Murdochb0fe1622011-05-05 13:52:32 +0100202 LOG_PRI_VA(ANDROID_LOG_INFO, LOG_TAG, format, args);
203#else
204 vfprintf(out, format, args);
205#endif
206}
207
208
Steve Blocka7e24c12009-10-30 11:49:00 +0000209void OS::PrintError(const char* format, ...) {
210 va_list args;
211 va_start(args, format);
212 VPrintError(format, args);
213 va_end(args);
214}
215
216
217void OS::VPrintError(const char* format, va_list args) {
Steve Block44f0eee2011-05-26 01:26:41 +0100218#if defined(ANDROID) && !defined(V8_ANDROID_LOG_STDOUT)
Steve Blocka7e24c12009-10-30 11:49:00 +0000219 LOG_PRI_VA(ANDROID_LOG_ERROR, LOG_TAG, format, args);
220#else
221 vfprintf(stderr, format, args);
222#endif
223}
224
225
226int OS::SNPrintF(Vector<char> str, const char* format, ...) {
227 va_list args;
228 va_start(args, format);
229 int result = VSNPrintF(str, format, args);
230 va_end(args);
231 return result;
232}
233
234
235int OS::VSNPrintF(Vector<char> str,
236 const char* format,
237 va_list args) {
238 int n = vsnprintf(str.start(), str.length(), format, args);
239 if (n < 0 || n >= str.length()) {
Ben Murdochb0fe1622011-05-05 13:52:32 +0100240 // If the length is zero, the assignment fails.
241 if (str.length() > 0)
242 str[str.length() - 1] = '\0';
Steve Blocka7e24c12009-10-30 11:49:00 +0000243 return -1;
244 } else {
245 return n;
246 }
247}
248
249
Ben Murdoch8b112d22011-06-08 16:22:53 +0100250#if defined(V8_TARGET_ARCH_IA32)
251static OS::MemCopyFunction memcopy_function = NULL;
252static Mutex* memcopy_function_mutex = OS::CreateMutex();
253// Defined in codegen-ia32.cc.
254OS::MemCopyFunction CreateMemCopyFunction();
255
256// Copy memory area to disjoint memory area.
257void OS::MemCopy(void* dest, const void* src, size_t size) {
258 if (memcopy_function == NULL) {
259 ScopedLock lock(memcopy_function_mutex);
260 if (memcopy_function == NULL) {
261 OS::MemCopyFunction temp = CreateMemCopyFunction();
262 MemoryBarrier();
263 memcopy_function = temp;
264 }
265 }
266 // Note: here we rely on dependent reads being ordered. This is true
267 // on all architectures we currently support.
268 (*memcopy_function)(dest, src, size);
269#ifdef DEBUG
270 CHECK_EQ(0, memcmp(dest, src, size));
271#endif
272}
273#endif // V8_TARGET_ARCH_IA32
274
Steve Blocka7e24c12009-10-30 11:49:00 +0000275// ----------------------------------------------------------------------------
276// POSIX string support.
277//
278
279char* OS::StrChr(char* str, int c) {
280 return strchr(str, c);
281}
282
283
284void OS::StrNCpy(Vector<char> dest, const char* src, size_t n) {
285 strncpy(dest.start(), src, n);
286}
287
288
289// ----------------------------------------------------------------------------
290// POSIX socket support.
291//
292
293class POSIXSocket : public Socket {
294 public:
295 explicit POSIXSocket() {
296 // Create the socket.
297 socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100298 if (IsValid()) {
299 // Allow rapid reuse.
300 static const int kOn = 1;
301 int ret = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR,
302 &kOn, sizeof(kOn));
303 ASSERT(ret == 0);
304 USE(ret);
305 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000306 }
307 explicit POSIXSocket(int socket): socket_(socket) { }
308 virtual ~POSIXSocket() { Shutdown(); }
309
310 // Server initialization.
311 bool Bind(const int port);
312 bool Listen(int backlog) const;
313 Socket* Accept() const;
314
315 // Client initialization.
316 bool Connect(const char* host, const char* port);
317
318 // Shutdown socket for both read and write.
319 bool Shutdown();
320
321 // Data Transimission
322 int Send(const char* data, int len) const;
323 int Receive(char* data, int len) const;
324
325 bool SetReuseAddress(bool reuse_address);
326
327 bool IsValid() const { return socket_ != -1; }
328
329 private:
330 int socket_;
331};
332
333
334bool POSIXSocket::Bind(const int port) {
335 if (!IsValid()) {
336 return false;
337 }
338
339 sockaddr_in addr;
340 memset(&addr, 0, sizeof(addr));
341 addr.sin_family = AF_INET;
342 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
343 addr.sin_port = htons(port);
344 int status = bind(socket_,
Iain Merrick75681382010-08-19 15:07:18 +0100345 BitCast<struct sockaddr *>(&addr),
Steve Blocka7e24c12009-10-30 11:49:00 +0000346 sizeof(addr));
347 return status == 0;
348}
349
350
351bool POSIXSocket::Listen(int backlog) const {
352 if (!IsValid()) {
353 return false;
354 }
355
356 int status = listen(socket_, backlog);
357 return status == 0;
358}
359
360
361Socket* POSIXSocket::Accept() const {
362 if (!IsValid()) {
363 return NULL;
364 }
365
366 int socket = accept(socket_, NULL, NULL);
367 if (socket == -1) {
368 return NULL;
369 } else {
370 return new POSIXSocket(socket);
371 }
372}
373
374
375bool POSIXSocket::Connect(const char* host, const char* port) {
376 if (!IsValid()) {
377 return false;
378 }
379
380 // Lookup host and port.
381 struct addrinfo *result = NULL;
382 struct addrinfo hints;
383 memset(&hints, 0, sizeof(addrinfo));
384 hints.ai_family = AF_INET;
385 hints.ai_socktype = SOCK_STREAM;
386 hints.ai_protocol = IPPROTO_TCP;
387 int status = getaddrinfo(host, port, &hints, &result);
388 if (status != 0) {
389 return false;
390 }
391
392 // Connect.
393 status = connect(socket_, result->ai_addr, result->ai_addrlen);
394 freeaddrinfo(result);
395 return status == 0;
396}
397
398
399bool POSIXSocket::Shutdown() {
400 if (IsValid()) {
401 // Shutdown socket for both read and write.
402 int status = shutdown(socket_, SHUT_RDWR);
403 close(socket_);
404 socket_ = -1;
405 return status == 0;
406 }
407 return true;
408}
409
410
411int POSIXSocket::Send(const char* data, int len) const {
412 int status = send(socket_, data, len, 0);
413 return status;
414}
415
416
417int POSIXSocket::Receive(char* data, int len) const {
418 int status = recv(socket_, data, len, 0);
419 return status;
420}
421
422
423bool POSIXSocket::SetReuseAddress(bool reuse_address) {
424 int on = reuse_address ? 1 : 0;
425 int status = setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
426 return status == 0;
427}
428
429
430bool Socket::Setup() {
431 // Nothing to do on POSIX.
432 return true;
433}
434
435
436int Socket::LastError() {
437 return errno;
438}
439
440
441uint16_t Socket::HToN(uint16_t value) {
442 return htons(value);
443}
444
445
446uint16_t Socket::NToH(uint16_t value) {
447 return ntohs(value);
448}
449
450
451uint32_t Socket::HToN(uint32_t value) {
452 return htonl(value);
453}
454
455
456uint32_t Socket::NToH(uint32_t value) {
457 return ntohl(value);
458}
459
460
461Socket* OS::CreateSocket() {
462 return new POSIXSocket();
463}
464
465
466} } // namespace v8::internal