blob: 6b2348c8903f4eabcbb2455283793688ada56844 [file] [log] [blame]
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001// Copyright 2011 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +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// This module contains the platform-specific code. This make the rest of the
29// code less dependent on operating system, compilers and runtime libraries.
30// This module does specifically not deal with differences between different
31// processor architecture.
32// The platform classes have the same definition for all platforms. The
33// implementation for a particular platform is put in platform_<os>.cc.
34// The build system then uses the implementation for the target platform.
35//
ager@chromium.org32912102009-01-16 10:38:43 +000036// This design has been chosen because it is simple and fast. Alternatively,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000037// the platform dependent classes could have been implemented using abstract
38// superclasses with virtual methods and having specializations for each
39// platform. This design was rejected because it was more complicated and
40// slower. It would require factory methods for selecting the right
41// implementation and the overhead of virtual methods for performance
42// sensitive like mutex locking/unlocking.
43
44#ifndef V8_PLATFORM_H_
45#define V8_PLATFORM_H_
46
ager@chromium.org3e875802009-06-29 08:26:34 +000047#define V8_INFINITY INFINITY
48
iposva@chromium.org245aa852009-02-10 00:49:54 +000049// Windows specific stuff.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000050#ifdef WIN32
51
iposva@chromium.org245aa852009-02-10 00:49:54 +000052// Microsoft Visual C++ specific stuff.
53#ifdef _MSC_VER
54
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000055enum {
56 FP_NAN,
57 FP_INFINITE,
58 FP_ZERO,
59 FP_SUBNORMAL,
60 FP_NORMAL
61};
62
ager@chromium.org3e875802009-06-29 08:26:34 +000063#undef V8_INFINITY
64#define V8_INFINITY HUGE_VAL
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000065
kasperl@chromium.org71affb52009-05-26 05:44:31 +000066namespace v8 {
67namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000068int isfinite(double x);
69} }
70int isnan(double x);
71int isinf(double x);
72int isless(double x, double y);
73int isgreater(double x, double y);
74int fpclassify(double x);
75int signbit(double x);
76
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000077int strncasecmp(const char* s1, const char* s2, int n);
78
iposva@chromium.org245aa852009-02-10 00:49:54 +000079#endif // _MSC_VER
80
iposva@chromium.org245aa852009-02-10 00:49:54 +000081// Random is missing on both Visual Studio and MinGW.
82int random();
83
84#endif // WIN32
85
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +000086
87#ifdef __sun
88# ifndef signbit
89int signbit(double x);
90# endif
91#endif
92
93
iposva@chromium.org245aa852009-02-10 00:49:54 +000094// GCC specific stuff
95#ifdef __GNUC__
ager@chromium.org3e875802009-06-29 08:26:34 +000096
97// Needed for va_list on at least MinGW and Android.
98#include <stdarg.h>
99
iposva@chromium.org245aa852009-02-10 00:49:54 +0000100#define __GNUC_VERSION__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000101
102// Unfortunately, the INFINITY macro cannot be used with the '-pedantic'
103// warning flag and certain versions of GCC due to a bug:
104// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11931
105// For now, we use the more involved template-based version from <limits>, but
106// only when compiling with GCC versions affected by the bug (2.96.x - 4.0.x)
107// __GNUC_PREREQ is not defined in GCC for Mac OS X, so we define our own macro
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000108#if __GNUC_VERSION__ >= 29600 && __GNUC_VERSION__ < 40100
109#include <limits>
ager@chromium.org3e875802009-06-29 08:26:34 +0000110#undef V8_INFINITY
111#define V8_INFINITY std::numeric_limits<double>::infinity()
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000112#endif
113
iposva@chromium.org245aa852009-02-10 00:49:54 +0000114#endif // __GNUC__
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000115
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000116#include "atomicops.h"
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000117#include "platform-tls.h"
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000118#include "utils.h"
119#include "v8globals.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000120
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000121namespace v8 {
122namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000123
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000124// Use AtomicWord for a machine-sized pointer. It is assumed that
125// reads and writes of naturally aligned values of this type are atomic.
126typedef intptr_t AtomicWord;
127
ager@chromium.org3e875802009-06-29 08:26:34 +0000128class Semaphore;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +0000129class Mutex;
ager@chromium.org3e875802009-06-29 08:26:34 +0000130
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000131double ceiling(double x);
ager@chromium.org3811b432009-10-28 14:53:37 +0000132double modulo(double x, double y);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000133
ager@chromium.org381abbb2009-02-25 13:23:22 +0000134// Forward declarations.
135class Socket;
136
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000137// ----------------------------------------------------------------------------
138// OS
139//
140// This class has static methods for the different platform specific
141// functions. Add methods here to cope with differences between the
142// supported platforms.
143
144class OS {
145 public:
146 // Initializes the platform OS support. Called once at VM startup.
147 static void Setup();
148
149 // Returns the accumulated user time for thread. This routine
150 // can be used for profiling. The implementation should
151 // strive for high-precision timer resolution, preferable
152 // micro-second resolution.
153 static int GetUserTime(uint32_t* secs, uint32_t* usecs);
154
155 // Get a tick counter normalized to one tick per microsecond.
156 // Used for calculating time intervals.
157 static int64_t Ticks();
158
159 // Returns current time as the number of milliseconds since
160 // 00:00:00 UTC, January 1, 1970.
161 static double TimeCurrentMillis();
162
163 // Returns a string identifying the current time zone. The
164 // timestamp is used for determining if DST is in effect.
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000165 static const char* LocalTimezone(double time);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000166
167 // Returns the local time offset in milliseconds east of UTC without
168 // taking daylight savings time into account.
169 static double LocalTimeOffset();
170
171 // Returns the daylight savings offset for the given time.
172 static double DaylightSavingsOffset(double time);
173
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000174 // Returns last OS error.
175 static int GetLastError();
176
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000177 static FILE* FOpen(const char* path, const char* mode);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000178 static bool Remove(const char* path);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000179
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000180 // Opens a temporary file, the file is auto removed on close.
181 static FILE* OpenTemporaryFile();
182
ager@chromium.org71daaf62009-04-01 07:22:49 +0000183 // Log file open mode is platform-dependent due to line ends issues.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000184 static const char* const LogFileOpenMode;
ager@chromium.org71daaf62009-04-01 07:22:49 +0000185
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000186 // Print output to console. This is mostly used for debugging output.
187 // On platforms that has standard terminal output, the output
188 // should go to stdout.
189 static void Print(const char* format, ...);
190 static void VPrint(const char* format, va_list args);
191
whesse@chromium.org023421e2010-12-21 12:19:12 +0000192 // Print output to a file. This is mostly used for debugging output.
193 static void FPrint(FILE* out, const char* format, ...);
194 static void VFPrint(FILE* out, const char* format, va_list args);
195
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000196 // Print error output to console. This is mostly used for error message
197 // output. On platforms that has standard terminal output, the output
198 // should go to stderr.
199 static void PrintError(const char* format, ...);
200 static void VPrintError(const char* format, va_list args);
201
ager@chromium.org32912102009-01-16 10:38:43 +0000202 // Allocate/Free memory used by JS heap. Pages are readable/writable, but
kasper.lund7276f142008-07-30 08:49:36 +0000203 // they are not guaranteed to be executable unless 'executable' is true.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000204 // Returns the address of allocated memory, or NULL if failed.
kasper.lund7276f142008-07-30 08:49:36 +0000205 static void* Allocate(const size_t requested,
206 size_t* allocated,
kasperl@chromium.orgf5aa8372009-03-24 14:47:14 +0000207 bool is_executable);
208 static void Free(void* address, const size_t size);
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000209
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +0000210 // Mark code segments non-writable.
211 static void ProtectCode(void* address, const size_t size);
212
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000213 // Assign memory as a guard page so that access will cause an exception.
214 static void Guard(void* address, const size_t size);
215
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000216 // Get the Alignment guaranteed by Allocate().
217 static size_t AllocateAlignment();
218
219 // Returns an indication of whether a pointer is in a space that
220 // has been allocated by Allocate(). This method may conservatively
221 // always return false, but giving more accurate information may
222 // improve the robustness of the stack dump code in the presence of
223 // heap corruption.
224 static bool IsOutsideAllocatedSpace(void* pointer);
225
ager@chromium.org32912102009-01-16 10:38:43 +0000226 // Sleep for a number of milliseconds.
227 static void Sleep(const int milliseconds);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000228
229 // Abort the current process.
230 static void Abort();
231
kasper.lund7276f142008-07-30 08:49:36 +0000232 // Debug break.
233 static void DebugBreak();
234
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000235 // Walk the stack.
236 static const int kStackWalkError = -1;
237 static const int kStackWalkMaxNameLen = 256;
238 static const int kStackWalkMaxTextLen = 256;
239 struct StackFrame {
240 void* address;
241 char text[kStackWalkMaxTextLen];
242 };
243
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000244 static int StackWalk(Vector<StackFrame> frames);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000245
246 // Factory method for creating platform dependent Mutex.
247 // Please use delete to reclaim the storage for the returned Mutex.
248 static Mutex* CreateMutex();
249
250 // Factory method for creating platform dependent Semaphore.
251 // Please use delete to reclaim the storage for the returned Semaphore.
252 static Semaphore* CreateSemaphore(int count);
253
ager@chromium.org381abbb2009-02-25 13:23:22 +0000254 // Factory method for creating platform dependent Socket.
255 // Please use delete to reclaim the storage for the returned Socket.
256 static Socket* CreateSocket();
257
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000258 class MemoryMappedFile {
259 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000260 static MemoryMappedFile* open(const char* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000261 static MemoryMappedFile* create(const char* name, int size, void* initial);
262 virtual ~MemoryMappedFile() { }
263 virtual void* memory() = 0;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000264 virtual int size() = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000265 };
266
kasper.lund7276f142008-07-30 08:49:36 +0000267 // Safe formatting print. Ensures that str is always null-terminated.
268 // Returns the number of chars written, or -1 if output was truncated.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000269 static int SNPrintF(Vector<char> str, const char* format, ...);
270 static int VSNPrintF(Vector<char> str,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000271 const char* format,
272 va_list args);
273
ager@chromium.org381abbb2009-02-25 13:23:22 +0000274 static char* StrChr(char* str, int c);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000275 static void StrNCpy(Vector<char> dest, const char* src, size_t n);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000276
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000277 // Support for the profiler. Can do nothing, in which case ticks
278 // occuring in shared libraries will not be properly accounted for.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000279 static void LogSharedLibraryAddresses();
280
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000281 // Support for the profiler. Notifies the external profiling
282 // process that a code moving garbage collection starts. Can do
283 // nothing, in which case the code objects must not move (e.g., by
284 // using --never-compact) if accurate profiling is desired.
285 static void SignalCodeMovingGC();
286
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000287 // The return value indicates the CPU features we are sure of because of the
288 // OS. For example MacOSX doesn't run on any x86 CPUs that don't have SSE2
289 // instructions.
290 // This is a little messy because the interpretation is subject to the cross
291 // of the CPU and the OS. The bits in the answer correspond to the bit
292 // positions indicated by the members of the CpuFeature enum from globals.h
293 static uint64_t CpuFeaturesImpliedByPlatform();
294
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000295 // Maximum size of the virtual memory. 0 means there is no artificial
296 // limit.
297 static intptr_t MaxVirtualMemory();
298
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000299 // Returns the double constant NAN
300 static double nan_value();
301
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000302 // Support runtime detection of VFP3 on ARM CPUs.
303 static bool ArmCpuHasFeature(CpuFeature feature);
304
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000305 // Support runtime detection of whether the hard float option of the
306 // EABI is used.
307 static bool ArmUsingHardFloat();
308
lrn@chromium.org7516f052011-03-30 08:52:27 +0000309 // Support runtime detection of FPU on MIPS CPUs.
310 static bool MipsCpuHasFeature(CpuFeature feature);
311
ager@chromium.org236ad962008-09-25 09:45:57 +0000312 // Returns the activation frame alignment constraint or zero if
313 // the platform doesn't care. Guaranteed to be a power of two.
314 static int ActivationFrameAlignment();
315
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000316 static void ReleaseStore(volatile AtomicWord* ptr, AtomicWord value);
317
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000318#if defined(V8_TARGET_ARCH_IA32)
319 // Copy memory area to disjoint memory area.
320 static void MemCopy(void* dest, const void* src, size_t size);
321 // Limit below which the extra overhead of the MemCopy function is likely
322 // to outweigh the benefits of faster copying.
323 static const int kMinComplexMemCopy = 64;
324 typedef void (*MemCopyFunction)(void* dest, const void* src, size_t size);
325
326#else // V8_TARGET_ARCH_IA32
327 static void MemCopy(void* dest, const void* src, size_t size) {
328 memcpy(dest, src, size);
329 }
330 static const int kMinComplexMemCopy = 256;
331#endif // V8_TARGET_ARCH_IA32
332
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000333 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000334 static const int msPerSecond = 1000;
mads.s.ager31e71382008-08-13 09:32:07 +0000335
336 DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000337};
338
339
340class VirtualMemory {
341 public:
342 // Reserves virtual memory with size.
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000343 explicit VirtualMemory(size_t size);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000344 ~VirtualMemory();
345
346 // Returns whether the memory has been reserved.
347 bool IsReserved();
348
349 // Returns the start address of the reserved memory.
350 void* address() {
351 ASSERT(IsReserved());
352 return address_;
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000353 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000354
355 // Returns the size of the reserved memory.
356 size_t size() { return size_; }
357
358 // Commits real memory. Returns whether the operation succeeded.
kasperl@chromium.orgf5aa8372009-03-24 14:47:14 +0000359 bool Commit(void* address, size_t size, bool is_executable);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000360
361 // Uncommit real memory. Returns whether the operation succeeded.
362 bool Uncommit(void* address, size_t size);
363
364 private:
365 void* address_; // Start address of the virtual memory.
366 size_t size_; // Size of the virtual memory.
367};
368
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000369// ----------------------------------------------------------------------------
370// Thread
371//
372// Thread objects are used for creating and running threads. When the start()
373// method is called the new thread starts running the run() method in the new
374// thread. The Thread object should not be deallocated before the thread has
375// terminated.
376
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000377class Thread {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000378 public:
379 // Opaque data type for thread-local storage keys.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000380 // LOCAL_STORAGE_KEY_MIN_VALUE and LOCAL_STORAGE_KEY_MAX_VALUE are specified
381 // to ensure that enumeration type has correct value range (see Issue 830 for
382 // more details).
383 enum LocalStorageKey {
384 LOCAL_STORAGE_KEY_MIN_VALUE = kMinInt,
385 LOCAL_STORAGE_KEY_MAX_VALUE = kMaxInt
386 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000387
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000388 struct Options {
389 Options() : name("v8:<unknown>"), stack_size(0) {}
390
391 const char* name;
392 int stack_size;
393 };
394
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000395 // Create new thread.
396 explicit Thread(const Options& options);
397 explicit Thread(const char* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000398 virtual ~Thread();
399
400 // Start new thread by calling the Run() method in the new thread.
401 void Start();
402
403 // Wait until thread terminates.
404 void Join();
405
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000406 inline const char* name() const {
407 return name_;
408 }
409
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000410 // Abstract method for run handler.
411 virtual void Run() = 0;
412
413 // Thread-local storage.
414 static LocalStorageKey CreateThreadLocalKey();
415 static void DeleteThreadLocalKey(LocalStorageKey key);
416 static void* GetThreadLocal(LocalStorageKey key);
ager@chromium.org9085a012009-05-11 19:22:57 +0000417 static int GetThreadLocalInt(LocalStorageKey key) {
418 return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
419 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000420 static void SetThreadLocal(LocalStorageKey key, void* value);
ager@chromium.org9085a012009-05-11 19:22:57 +0000421 static void SetThreadLocalInt(LocalStorageKey key, int value) {
422 SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
423 }
424 static bool HasThreadLocal(LocalStorageKey key) {
425 return GetThreadLocal(key) != NULL;
426 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000427
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000428#ifdef V8_FAST_TLS_SUPPORTED
429 static inline void* GetExistingThreadLocal(LocalStorageKey key) {
430 void* result = reinterpret_cast<void*>(
431 InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
432 ASSERT(result == GetThreadLocal(key));
433 return result;
434 }
435#else
436 static inline void* GetExistingThreadLocal(LocalStorageKey key) {
437 return GetThreadLocal(key);
438 }
439#endif
440
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000441 // A hint to the scheduler to let another thread run.
442 static void YieldCPU();
443
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000444
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000445 // The thread name length is limited to 16 based on Linux's implementation of
446 // prctl().
447 static const int kMaxThreadNameLength = 16;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000448
449 class PlatformData;
450 PlatformData* data() { return data_; }
451
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000452 private:
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000453 void set_name(const char *name);
454
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000455 PlatformData* data_;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000456
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000457 char name_[kMaxThreadNameLength];
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000458 int stack_size_;
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000459
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000460 DISALLOW_COPY_AND_ASSIGN(Thread);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000461};
462
463
464// ----------------------------------------------------------------------------
465// Mutex
466//
467// Mutexes are used for serializing access to non-reentrant sections of code.
468// The implementations of mutex should allow for nested/recursive locking.
469
470class Mutex {
471 public:
472 virtual ~Mutex() {}
473
474 // Locks the given mutex. If the mutex is currently unlocked, it becomes
475 // locked and owned by the calling thread, and immediately. If the mutex
476 // is already locked by another thread, suspends the calling thread until
477 // the mutex is unlocked.
478 virtual int Lock() = 0;
479
480 // Unlocks the given mutex. The mutex is assumed to be locked and owned by
481 // the calling thread on entrance.
482 virtual int Unlock() = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000483
484 // Tries to lock the given mutex. Returns whether the mutex was
485 // successfully locked.
486 virtual bool TryLock() = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000487};
488
489
490// ----------------------------------------------------------------------------
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000491// ScopedLock
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000492//
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000493// Stack-allocated ScopedLocks provide block-scoped locking and
494// unlocking of a mutex.
kasper.lund7276f142008-07-30 08:49:36 +0000495class ScopedLock {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000496 public:
kasper.lund7276f142008-07-30 08:49:36 +0000497 explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000498 ASSERT(mutex_ != NULL);
kasper.lund7276f142008-07-30 08:49:36 +0000499 mutex_->Lock();
500 }
501 ~ScopedLock() {
502 mutex_->Unlock();
503 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000504
505 private:
kasper.lund7276f142008-07-30 08:49:36 +0000506 Mutex* mutex_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000507 DISALLOW_COPY_AND_ASSIGN(ScopedLock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000508};
509
510
511// ----------------------------------------------------------------------------
512// Semaphore
513//
514// A semaphore object is a synchronization object that maintains a count. The
515// count is decremented each time a thread completes a wait for the semaphore
516// object and incremented each time a thread signals the semaphore. When the
517// count reaches zero, threads waiting for the semaphore blocks until the
518// count becomes non-zero.
519
520class Semaphore {
521 public:
522 virtual ~Semaphore() {}
523
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000524 // Suspends the calling thread until the semaphore counter is non zero
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000525 // and then decrements the semaphore counter.
526 virtual void Wait() = 0;
527
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000528 // Suspends the calling thread until the counter is non zero or the timeout
529 // time has passsed. If timeout happens the return value is false and the
530 // counter is unchanged. Otherwise the semaphore counter is decremented and
531 // true is returned. The timeout value is specified in microseconds.
532 virtual bool Wait(int timeout) = 0;
533
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000534 // Increments the semaphore counter.
535 virtual void Signal() = 0;
536};
537
538
ager@chromium.org381abbb2009-02-25 13:23:22 +0000539// ----------------------------------------------------------------------------
540// Socket
541//
542
543class Socket {
544 public:
545 virtual ~Socket() {}
546
547 // Server initialization.
548 virtual bool Bind(const int port) = 0;
549 virtual bool Listen(int backlog) const = 0;
550 virtual Socket* Accept() const = 0;
551
552 // Client initialization.
553 virtual bool Connect(const char* host, const char* port) = 0;
554
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000555 // Shutdown socket for both read and write. This causes blocking Send and
556 // Receive calls to exit. After Shutdown the Socket object cannot be used for
557 // any communication.
558 virtual bool Shutdown() = 0;
559
ager@chromium.org381abbb2009-02-25 13:23:22 +0000560 // Data Transimission
561 virtual int Send(const char* data, int len) const = 0;
ager@chromium.org381abbb2009-02-25 13:23:22 +0000562 virtual int Receive(char* data, int len) const = 0;
563
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000564 // Set the value of the SO_REUSEADDR socket option.
565 virtual bool SetReuseAddress(bool reuse_address) = 0;
566
ager@chromium.org381abbb2009-02-25 13:23:22 +0000567 virtual bool IsValid() const = 0;
568
569 static bool Setup();
570 static int LastError();
571 static uint16_t HToN(uint16_t value);
572 static uint16_t NToH(uint16_t value);
573 static uint32_t HToN(uint32_t value);
574 static uint32_t NToH(uint32_t value);
575};
576
577
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000578// ----------------------------------------------------------------------------
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000579// Sampler
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000580//
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000581// A sampler periodically samples the state of the VM and optionally
582// (if used for profiling) the program counter and stack pointer for
583// the thread that created it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000584
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000585// TickSample captures the information collected for each sample.
586class TickSample {
587 public:
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000588 TickSample()
ager@chromium.org357bf652010-04-12 11:30:10 +0000589 : state(OTHER),
590 pc(NULL),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000591 sp(NULL),
592 fp(NULL),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000593 tos(NULL),
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000594 frames_count(0),
595 has_external_callback(false) {}
ager@chromium.org357bf652010-04-12 11:30:10 +0000596 StateTag state; // The state of the VM.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000597 Address pc; // Instruction pointer.
598 Address sp; // Stack pointer.
599 Address fp; // Frame pointer.
600 union {
601 Address tos; // Top stack value (*sp).
602 Address external_callback;
603 };
lrn@chromium.org25156de2010-04-06 13:10:27 +0000604 static const int kMaxFramesCount = 64;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000605 Address stack[kMaxFramesCount]; // Call stack.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000606 int frames_count : 8; // Number of captured frames.
607 bool has_external_callback : 1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000608};
609
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000610class Sampler {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000611 public:
612 // Initialize sampler.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000613 Sampler(Isolate* isolate, int interval);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000614 virtual ~Sampler();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000615
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000616 int interval() const { return interval_; }
617
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000618 // Performs stack sampling.
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000619 void SampleStack(TickSample* sample) {
620 DoSampleStack(sample);
621 IncSamplesTaken();
622 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000623
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000624 // This method is called for each sampling period with the current
625 // program counter.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000626 virtual void Tick(TickSample* sample) = 0;
627
628 // Start and stop sampler.
629 void Start();
630 void Stop();
631
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000632 // Is the sampler used for profiling?
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000633 bool IsProfiling() const { return NoBarrier_Load(&profiling_) > 0; }
634 void IncreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, 1); }
635 void DecreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, -1); }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000636
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000637 // Whether the sampler is running (that is, consumes resources).
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000638 bool IsActive() const { return NoBarrier_Load(&active_); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000639
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000640 Isolate* isolate() { return isolate_; }
641
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000642 // Used in tests to make sure that stack sampling is performed.
643 int samples_taken() const { return samples_taken_; }
644 void ResetSamplesTaken() { samples_taken_ = 0; }
645
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000646 class PlatformData;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000647 PlatformData* data() { return data_; }
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000648
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000649 PlatformData* platform_data() { return data_; }
650
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000651 protected:
652 virtual void DoSampleStack(TickSample* sample) = 0;
653
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000654 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000655 void SetActive(bool value) { NoBarrier_Store(&active_, value); }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000656 void IncSamplesTaken() { if (++samples_taken_ < 0) samples_taken_ = 0; }
657
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000658 Isolate* isolate_;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000659 const int interval_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000660 Atomic32 profiling_;
661 Atomic32 active_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000662 PlatformData* data_; // Platform specific data.
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000663 int samples_taken_; // Counts stack samples taken.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000664 DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000665};
666
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000667
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000668} } // namespace v8::internal
669
670#endif // V8_PLATFORM_H_