blob: fc12df2d7cf9629f0b6a570ba28433ccf1644930 [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
erik.corry@gmail.com9dfbea42010-05-21 12:58:28 +000047#ifdef __sun
48# ifndef signbit
49int signbit(double x);
50# endif
51#endif
52
iposva@chromium.org245aa852009-02-10 00:49:54 +000053// GCC specific stuff
54#ifdef __GNUC__
ager@chromium.org3e875802009-06-29 08:26:34 +000055
56// Needed for va_list on at least MinGW and Android.
57#include <stdarg.h>
58
iposva@chromium.org245aa852009-02-10 00:49:54 +000059#define __GNUC_VERSION__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000060
iposva@chromium.org245aa852009-02-10 00:49:54 +000061#endif // __GNUC__
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000062
ricow@chromium.org55ee8072011-09-08 16:33:10 +000063
64// Windows specific stuff.
65#ifdef WIN32
66
67// Microsoft Visual C++ specific stuff.
68#ifdef _MSC_VER
69
70#include "win32-math.h"
71
72int strncasecmp(const char* s1, const char* s2, int n);
73
74#endif // _MSC_VER
75
76// Random is missing on both Visual Studio and MinGW.
77int random();
78
79#endif // WIN32
80
kasperl@chromium.orga5551262010-12-07 12:49:48 +000081#include "atomicops.h"
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000082#include "platform-tls.h"
ager@chromium.org5f0c45f2010-12-17 08:51:21 +000083#include "utils.h"
84#include "v8globals.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000085
kasperl@chromium.org71affb52009-05-26 05:44:31 +000086namespace v8 {
87namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000088
whesse@chromium.orgcec079d2010-03-22 14:44:04 +000089// Use AtomicWord for a machine-sized pointer. It is assumed that
90// reads and writes of naturally aligned values of this type are atomic.
91typedef intptr_t AtomicWord;
92
ager@chromium.org3e875802009-06-29 08:26:34 +000093class Semaphore;
ager@chromium.org5f0c45f2010-12-17 08:51:21 +000094class Mutex;
ager@chromium.org3e875802009-06-29 08:26:34 +000095
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000096double ceiling(double x);
ager@chromium.org3811b432009-10-28 14:53:37 +000097double modulo(double x, double y);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000098
ager@chromium.org381abbb2009-02-25 13:23:22 +000099// Forward declarations.
100class Socket;
101
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000102// ----------------------------------------------------------------------------
103// OS
104//
105// This class has static methods for the different platform specific
106// functions. Add methods here to cope with differences between the
107// supported platforms.
108
109class OS {
110 public:
111 // Initializes the platform OS support. Called once at VM startup.
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000112 static void SetUp();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000113
114 // Returns the accumulated user time for thread. This routine
115 // can be used for profiling. The implementation should
116 // strive for high-precision timer resolution, preferable
117 // micro-second resolution.
118 static int GetUserTime(uint32_t* secs, uint32_t* usecs);
119
120 // Get a tick counter normalized to one tick per microsecond.
121 // Used for calculating time intervals.
122 static int64_t Ticks();
123
124 // Returns current time as the number of milliseconds since
125 // 00:00:00 UTC, January 1, 1970.
126 static double TimeCurrentMillis();
127
128 // Returns a string identifying the current time zone. The
129 // timestamp is used for determining if DST is in effect.
sgjesse@chromium.orgb9d7da12009-08-05 08:38:10 +0000130 static const char* LocalTimezone(double time);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000131
132 // Returns the local time offset in milliseconds east of UTC without
133 // taking daylight savings time into account.
134 static double LocalTimeOffset();
135
136 // Returns the daylight savings offset for the given time.
137 static double DaylightSavingsOffset(double time);
138
ager@chromium.orgea4f62e2010-08-16 16:28:43 +0000139 // Returns last OS error.
140 static int GetLastError();
141
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000142 static FILE* FOpen(const char* path, const char* mode);
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000143 static bool Remove(const char* path);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000144
whesse@chromium.org030d38e2011-07-13 13:23:34 +0000145 // Opens a temporary file, the file is auto removed on close.
146 static FILE* OpenTemporaryFile();
147
ager@chromium.org71daaf62009-04-01 07:22:49 +0000148 // Log file open mode is platform-dependent due to line ends issues.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000149 static const char* const LogFileOpenMode;
ager@chromium.org71daaf62009-04-01 07:22:49 +0000150
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000151 // Print output to console. This is mostly used for debugging output.
152 // On platforms that has standard terminal output, the output
153 // should go to stdout.
154 static void Print(const char* format, ...);
155 static void VPrint(const char* format, va_list args);
156
whesse@chromium.org023421e2010-12-21 12:19:12 +0000157 // Print output to a file. This is mostly used for debugging output.
158 static void FPrint(FILE* out, const char* format, ...);
159 static void VFPrint(FILE* out, const char* format, va_list args);
160
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000161 // Print error output to console. This is mostly used for error message
162 // output. On platforms that has standard terminal output, the output
163 // should go to stderr.
164 static void PrintError(const char* format, ...);
165 static void VPrintError(const char* format, va_list args);
166
ager@chromium.org32912102009-01-16 10:38:43 +0000167 // Allocate/Free memory used by JS heap. Pages are readable/writable, but
kasper.lund7276f142008-07-30 08:49:36 +0000168 // they are not guaranteed to be executable unless 'executable' is true.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000169 // Returns the address of allocated memory, or NULL if failed.
kasper.lund7276f142008-07-30 08:49:36 +0000170 static void* Allocate(const size_t requested,
171 size_t* allocated,
kasperl@chromium.orgf5aa8372009-03-24 14:47:14 +0000172 bool is_executable);
173 static void Free(void* address, const size_t size);
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000174
ricow@chromium.org64e3a4b2011-12-13 08:07:27 +0000175 // This is the granularity at which the ProtectCode(...) call can set page
176 // permissions.
177 static intptr_t CommitPageSize();
178
lrn@chromium.orgd4e9e222011-08-03 12:01:58 +0000179 // Mark code segments non-writable.
180 static void ProtectCode(void* address, const size_t size);
181
rossberg@chromium.org717967f2011-07-20 13:44:42 +0000182 // Assign memory as a guard page so that access will cause an exception.
183 static void Guard(void* address, const size_t size);
184
rossberg@chromium.orgb4b2aa62011-10-13 09:49:59 +0000185 // Generate a random address to be used for hinting mmap().
186 static void* GetRandomMmapAddr();
187
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188 // Get the Alignment guaranteed by Allocate().
189 static size_t AllocateAlignment();
190
191 // Returns an indication of whether a pointer is in a space that
192 // has been allocated by Allocate(). This method may conservatively
193 // always return false, but giving more accurate information may
194 // improve the robustness of the stack dump code in the presence of
195 // heap corruption.
196 static bool IsOutsideAllocatedSpace(void* pointer);
197
ager@chromium.org32912102009-01-16 10:38:43 +0000198 // Sleep for a number of milliseconds.
199 static void Sleep(const int milliseconds);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000200
201 // Abort the current process.
202 static void Abort();
203
kasper.lund7276f142008-07-30 08:49:36 +0000204 // Debug break.
205 static void DebugBreak();
206
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000207 // Walk the stack.
208 static const int kStackWalkError = -1;
209 static const int kStackWalkMaxNameLen = 256;
210 static const int kStackWalkMaxTextLen = 256;
211 struct StackFrame {
212 void* address;
213 char text[kStackWalkMaxTextLen];
214 };
215
ager@chromium.org65dad4b2009-04-23 08:48:43 +0000216 static int StackWalk(Vector<StackFrame> frames);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000217
218 // Factory method for creating platform dependent Mutex.
219 // Please use delete to reclaim the storage for the returned Mutex.
220 static Mutex* CreateMutex();
221
222 // Factory method for creating platform dependent Semaphore.
223 // Please use delete to reclaim the storage for the returned Semaphore.
224 static Semaphore* CreateSemaphore(int count);
225
ager@chromium.org381abbb2009-02-25 13:23:22 +0000226 // Factory method for creating platform dependent Socket.
227 // Please use delete to reclaim the storage for the returned Socket.
228 static Socket* CreateSocket();
229
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000230 class MemoryMappedFile {
231 public:
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000232 static MemoryMappedFile* open(const char* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000233 static MemoryMappedFile* create(const char* name, int size, void* initial);
234 virtual ~MemoryMappedFile() { }
235 virtual void* memory() = 0;
vegorov@chromium.org0a4e9012011-01-24 12:33:13 +0000236 virtual int size() = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000237 };
238
kasper.lund7276f142008-07-30 08:49:36 +0000239 // Safe formatting print. Ensures that str is always null-terminated.
240 // Returns the number of chars written, or -1 if output was truncated.
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000241 static int SNPrintF(Vector<char> str, const char* format, ...);
242 static int VSNPrintF(Vector<char> str,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000243 const char* format,
244 va_list args);
245
ager@chromium.org381abbb2009-02-25 13:23:22 +0000246 static char* StrChr(char* str, int c);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000247 static void StrNCpy(Vector<char> dest, const char* src, size_t n);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000248
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000249 // Support for the profiler. Can do nothing, in which case ticks
250 // occuring in shared libraries will not be properly accounted for.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000251 static void LogSharedLibraryAddresses();
252
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000253 // Support for the profiler. Notifies the external profiling
254 // process that a code moving garbage collection starts. Can do
255 // nothing, in which case the code objects must not move (e.g., by
256 // using --never-compact) if accurate profiling is desired.
257 static void SignalCodeMovingGC();
258
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000259 // The return value indicates the CPU features we are sure of because of the
260 // OS. For example MacOSX doesn't run on any x86 CPUs that don't have SSE2
261 // instructions.
262 // This is a little messy because the interpretation is subject to the cross
263 // of the CPU and the OS. The bits in the answer correspond to the bit
264 // positions indicated by the members of the CpuFeature enum from globals.h
265 static uint64_t CpuFeaturesImpliedByPlatform();
266
lrn@chromium.orgac2828d2011-06-23 06:29:21 +0000267 // Maximum size of the virtual memory. 0 means there is no artificial
268 // limit.
269 static intptr_t MaxVirtualMemory();
270
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000271 // Returns the double constant NAN
272 static double nan_value();
273
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000274 // Support runtime detection of VFP3 on ARM CPUs.
275 static bool ArmCpuHasFeature(CpuFeature feature);
276
sgjesse@chromium.org8e8294a2011-05-02 14:30:53 +0000277 // Support runtime detection of whether the hard float option of the
278 // EABI is used.
279 static bool ArmUsingHardFloat();
280
lrn@chromium.org7516f052011-03-30 08:52:27 +0000281 // Support runtime detection of FPU on MIPS CPUs.
282 static bool MipsCpuHasFeature(CpuFeature feature);
283
ager@chromium.org236ad962008-09-25 09:45:57 +0000284 // Returns the activation frame alignment constraint or zero if
285 // the platform doesn't care. Guaranteed to be a power of two.
286 static int ActivationFrameAlignment();
287
kmillikin@chromium.org9155e252010-05-26 13:27:57 +0000288 static void ReleaseStore(volatile AtomicWord* ptr, AtomicWord value);
289
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000290#if defined(V8_TARGET_ARCH_IA32)
291 // Copy memory area to disjoint memory area.
292 static void MemCopy(void* dest, const void* src, size_t size);
293 // Limit below which the extra overhead of the MemCopy function is likely
294 // to outweigh the benefits of faster copying.
295 static const int kMinComplexMemCopy = 64;
296 typedef void (*MemCopyFunction)(void* dest, const void* src, size_t size);
297
298#else // V8_TARGET_ARCH_IA32
299 static void MemCopy(void* dest, const void* src, size_t size) {
300 memcpy(dest, src, size);
301 }
302 static const int kMinComplexMemCopy = 256;
303#endif // V8_TARGET_ARCH_IA32
304
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000305 private:
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000306 static const int msPerSecond = 1000;
mads.s.ager31e71382008-08-13 09:32:07 +0000307
308 DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000309};
310
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000311// Represents and controls an area of reserved memory.
312// Control of the reserved memory can be assigned to another VirtualMemory
313// object by assignment or copy-contructing. This removes the reserved memory
314// from the original object.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000315class VirtualMemory {
316 public:
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000317 // Empty VirtualMemory object, controlling no reserved memory.
318 VirtualMemory();
319
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000320 // Reserves virtual memory with size.
ager@chromium.org9258b6b2008-09-11 09:11:10 +0000321 explicit VirtualMemory(size_t size);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000322
323 // Reserves virtual memory containing an area of the given size that
324 // is aligned per alignment. This may not be at the position returned
325 // by address().
326 VirtualMemory(size_t size, size_t alignment);
327
328 // Releases the reserved memory, if any, controlled by this VirtualMemory
329 // object.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000330 ~VirtualMemory();
331
332 // Returns whether the memory has been reserved.
333 bool IsReserved();
334
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000335 // Initialize or resets an embedded VirtualMemory object.
336 void Reset();
337
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000338 // Returns the start address of the reserved memory.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000339 // If the memory was reserved with an alignment, this address is not
340 // necessarily aligned. The user might need to round it up to a multiple of
341 // the alignment to get the start of the aligned block.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000342 void* address() {
343 ASSERT(IsReserved());
344 return address_;
kmillikin@chromium.org3cdd9e12010-09-06 11:39:48 +0000345 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000346
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000347 // Returns the size of the reserved memory. The returned value is only
348 // meaningful when IsReserved() returns true.
349 // If the memory was reserved with an alignment, this size may be larger
350 // than the requested size.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000351 size_t size() { return size_; }
352
353 // Commits real memory. Returns whether the operation succeeded.
kasperl@chromium.orgf5aa8372009-03-24 14:47:14 +0000354 bool Commit(void* address, size_t size, bool is_executable);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000355
356 // Uncommit real memory. Returns whether the operation succeeded.
357 bool Uncommit(void* address, size_t size);
358
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000359 void Release() {
360 ASSERT(IsReserved());
361 // Notice: Order is important here. The VirtualMemory object might live
362 // inside the allocated region.
363 void* address = address_;
364 size_t size = size_;
365 Reset();
366 bool result = ReleaseRegion(address, size);
367 USE(result);
368 ASSERT(result);
369 }
370
371 // Assign control of the reserved region to a different VirtualMemory object.
372 // The old object is no longer functional (IsReserved() returns false).
373 void TakeControl(VirtualMemory* from) {
374 ASSERT(!IsReserved());
375 address_ = from->address_;
376 size_ = from->size_;
377 from->Reset();
378 }
379
380 static void* ReserveRegion(size_t size);
381
382 static bool CommitRegion(void* base, size_t size, bool is_executable);
383
384 static bool UncommitRegion(void* base, size_t size);
385
386 // Must be called with a base pointer that has been returned by ReserveRegion
387 // and the same size it was reserved with.
388 static bool ReleaseRegion(void* base, size_t size);
389
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000390 private:
391 void* address_; // Start address of the virtual memory.
392 size_t size_; // Size of the virtual memory.
393};
394
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000395
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000396// ----------------------------------------------------------------------------
397// Thread
398//
399// Thread objects are used for creating and running threads. When the start()
400// method is called the new thread starts running the run() method in the new
401// thread. The Thread object should not be deallocated before the thread has
402// terminated.
403
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000404class Thread {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000405 public:
406 // Opaque data type for thread-local storage keys.
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000407 // LOCAL_STORAGE_KEY_MIN_VALUE and LOCAL_STORAGE_KEY_MAX_VALUE are specified
408 // to ensure that enumeration type has correct value range (see Issue 830 for
409 // more details).
410 enum LocalStorageKey {
411 LOCAL_STORAGE_KEY_MIN_VALUE = kMinInt,
412 LOCAL_STORAGE_KEY_MAX_VALUE = kMaxInt
413 };
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000414
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000415 struct Options {
416 Options() : name("v8:<unknown>"), stack_size(0) {}
417
418 const char* name;
419 int stack_size;
420 };
421
svenpanne@chromium.org6d786c92011-06-15 10:58:27 +0000422 // Create new thread.
423 explicit Thread(const Options& options);
424 explicit Thread(const char* name);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000425 virtual ~Thread();
426
427 // Start new thread by calling the Run() method in the new thread.
428 void Start();
429
430 // Wait until thread terminates.
431 void Join();
432
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000433 inline const char* name() const {
434 return name_;
435 }
436
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000437 // Abstract method for run handler.
438 virtual void Run() = 0;
439
440 // Thread-local storage.
441 static LocalStorageKey CreateThreadLocalKey();
442 static void DeleteThreadLocalKey(LocalStorageKey key);
443 static void* GetThreadLocal(LocalStorageKey key);
ager@chromium.org9085a012009-05-11 19:22:57 +0000444 static int GetThreadLocalInt(LocalStorageKey key) {
445 return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
446 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000447 static void SetThreadLocal(LocalStorageKey key, void* value);
ager@chromium.org9085a012009-05-11 19:22:57 +0000448 static void SetThreadLocalInt(LocalStorageKey key, int value) {
449 SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
450 }
451 static bool HasThreadLocal(LocalStorageKey key) {
452 return GetThreadLocal(key) != NULL;
453 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000454
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000455#ifdef V8_FAST_TLS_SUPPORTED
456 static inline void* GetExistingThreadLocal(LocalStorageKey key) {
457 void* result = reinterpret_cast<void*>(
458 InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
459 ASSERT(result == GetThreadLocal(key));
460 return result;
461 }
462#else
463 static inline void* GetExistingThreadLocal(LocalStorageKey key) {
464 return GetThreadLocal(key);
465 }
466#endif
467
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000468 // A hint to the scheduler to let another thread run.
469 static void YieldCPU();
470
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000471
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000472 // The thread name length is limited to 16 based on Linux's implementation of
473 // prctl().
474 static const int kMaxThreadNameLength = 16;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000475
476 class PlatformData;
477 PlatformData* data() { return data_; }
478
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000479 private:
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000480 void set_name(const char* name);
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000481
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000482 PlatformData* data_;
ager@chromium.orga9aa5fa2011-04-13 08:46:07 +0000483
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000484 char name_[kMaxThreadNameLength];
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000485 int stack_size_;
lrn@chromium.org5d00b602011-01-05 09:51:43 +0000486
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000487 DISALLOW_COPY_AND_ASSIGN(Thread);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000488};
489
490
491// ----------------------------------------------------------------------------
492// Mutex
493//
494// Mutexes are used for serializing access to non-reentrant sections of code.
495// The implementations of mutex should allow for nested/recursive locking.
496
497class Mutex {
498 public:
499 virtual ~Mutex() {}
500
501 // Locks the given mutex. If the mutex is currently unlocked, it becomes
502 // locked and owned by the calling thread, and immediately. If the mutex
503 // is already locked by another thread, suspends the calling thread until
504 // the mutex is unlocked.
505 virtual int Lock() = 0;
506
507 // Unlocks the given mutex. The mutex is assumed to be locked and owned by
508 // the calling thread on entrance.
509 virtual int Unlock() = 0;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000510
511 // Tries to lock the given mutex. Returns whether the mutex was
512 // successfully locked.
513 virtual bool TryLock() = 0;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000514};
515
516
517// ----------------------------------------------------------------------------
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000518// ScopedLock
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000519//
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000520// Stack-allocated ScopedLocks provide block-scoped locking and
521// unlocking of a mutex.
kasper.lund7276f142008-07-30 08:49:36 +0000522class ScopedLock {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000523 public:
kasper.lund7276f142008-07-30 08:49:36 +0000524 explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000525 ASSERT(mutex_ != NULL);
kasper.lund7276f142008-07-30 08:49:36 +0000526 mutex_->Lock();
527 }
528 ~ScopedLock() {
529 mutex_->Unlock();
530 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000531
532 private:
kasper.lund7276f142008-07-30 08:49:36 +0000533 Mutex* mutex_;
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000534 DISALLOW_COPY_AND_ASSIGN(ScopedLock);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000535};
536
537
538// ----------------------------------------------------------------------------
539// Semaphore
540//
541// A semaphore object is a synchronization object that maintains a count. The
542// count is decremented each time a thread completes a wait for the semaphore
543// object and incremented each time a thread signals the semaphore. When the
544// count reaches zero, threads waiting for the semaphore blocks until the
545// count becomes non-zero.
546
547class Semaphore {
548 public:
549 virtual ~Semaphore() {}
550
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000551 // Suspends the calling thread until the semaphore counter is non zero
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000552 // and then decrements the semaphore counter.
553 virtual void Wait() = 0;
554
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000555 // Suspends the calling thread until the counter is non zero or the timeout
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000556 // time has passed. If timeout happens the return value is false and the
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000557 // counter is unchanged. Otherwise the semaphore counter is decremented and
558 // true is returned. The timeout value is specified in microseconds.
559 virtual bool Wait(int timeout) = 0;
560
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000561 // Increments the semaphore counter.
562 virtual void Signal() = 0;
563};
564
565
ager@chromium.org381abbb2009-02-25 13:23:22 +0000566// ----------------------------------------------------------------------------
567// Socket
568//
569
570class Socket {
571 public:
572 virtual ~Socket() {}
573
574 // Server initialization.
575 virtual bool Bind(const int port) = 0;
576 virtual bool Listen(int backlog) const = 0;
577 virtual Socket* Accept() const = 0;
578
579 // Client initialization.
580 virtual bool Connect(const char* host, const char* port) = 0;
581
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000582 // Shutdown socket for both read and write. This causes blocking Send and
583 // Receive calls to exit. After Shutdown the Socket object cannot be used for
584 // any communication.
585 virtual bool Shutdown() = 0;
586
ager@chromium.org381abbb2009-02-25 13:23:22 +0000587 // Data Transimission
588 virtual int Send(const char* data, int len) const = 0;
ager@chromium.org381abbb2009-02-25 13:23:22 +0000589 virtual int Receive(char* data, int len) const = 0;
590
ager@chromium.orgbb29dc92009-03-24 13:25:23 +0000591 // Set the value of the SO_REUSEADDR socket option.
592 virtual bool SetReuseAddress(bool reuse_address) = 0;
593
ager@chromium.org381abbb2009-02-25 13:23:22 +0000594 virtual bool IsValid() const = 0;
595
erik.corry@gmail.comf2038fb2012-01-16 11:42:08 +0000596 static bool SetUp();
ager@chromium.org381abbb2009-02-25 13:23:22 +0000597 static int LastError();
598 static uint16_t HToN(uint16_t value);
599 static uint16_t NToH(uint16_t value);
600 static uint32_t HToN(uint32_t value);
601 static uint32_t NToH(uint32_t value);
602};
603
604
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000605// ----------------------------------------------------------------------------
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000606// Sampler
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000607//
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000608// A sampler periodically samples the state of the VM and optionally
609// (if used for profiling) the program counter and stack pointer for
610// the thread that created it.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000611
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000612// TickSample captures the information collected for each sample.
613class TickSample {
614 public:
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000615 TickSample()
ager@chromium.org357bf652010-04-12 11:30:10 +0000616 : state(OTHER),
617 pc(NULL),
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000618 sp(NULL),
619 fp(NULL),
fschneider@chromium.org3a5fd782011-02-24 10:10:44 +0000620 tos(NULL),
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000621 frames_count(0),
622 has_external_callback(false) {}
ager@chromium.org357bf652010-04-12 11:30:10 +0000623 StateTag state; // The state of the VM.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000624 Address pc; // Instruction pointer.
625 Address sp; // Stack pointer.
626 Address fp; // Frame pointer.
627 union {
628 Address tos; // Top stack value (*sp).
629 Address external_callback;
630 };
lrn@chromium.org25156de2010-04-06 13:10:27 +0000631 static const int kMaxFramesCount = 64;
whesse@chromium.orgcec079d2010-03-22 14:44:04 +0000632 Address stack[kMaxFramesCount]; // Call stack.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000633 int frames_count : 8; // Number of captured frames.
634 bool has_external_callback : 1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000635};
636
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000637class Sampler {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000638 public:
639 // Initialize sampler.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000640 Sampler(Isolate* isolate, int interval);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000641 virtual ~Sampler();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000642
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000643 int interval() const { return interval_; }
644
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000645 // Performs stack sampling.
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000646 void SampleStack(TickSample* sample) {
647 DoSampleStack(sample);
648 IncSamplesTaken();
649 }
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000650
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000651 // This method is called for each sampling period with the current
652 // program counter.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000653 virtual void Tick(TickSample* sample) = 0;
654
655 // Start and stop sampler.
656 void Start();
657 void Stop();
658
whesse@chromium.org4a5224e2010-10-20 12:37:07 +0000659 // Is the sampler used for profiling?
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000660 bool IsProfiling() const { return NoBarrier_Load(&profiling_) > 0; }
661 void IncreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, 1); }
662 void DecreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, -1); }
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000663
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000664 // Whether the sampler is running (that is, consumes resources).
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000665 bool IsActive() const { return NoBarrier_Load(&active_); }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000666
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000667 Isolate* isolate() { return isolate_; }
668
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000669 // Used in tests to make sure that stack sampling is performed.
670 int samples_taken() const { return samples_taken_; }
671 void ResetSamplesTaken() { samples_taken_ = 0; }
672
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000673 class PlatformData;
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000674 PlatformData* data() { return data_; }
kasperl@chromium.org71affb52009-05-26 05:44:31 +0000675
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000676 PlatformData* platform_data() { return data_; }
677
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000678 protected:
679 virtual void DoSampleStack(TickSample* sample) = 0;
680
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000681 private:
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000682 void SetActive(bool value) { NoBarrier_Store(&active_, value); }
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000683 void IncSamplesTaken() { if (++samples_taken_ < 0) samples_taken_ = 0; }
684
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000685 Isolate* isolate_;
kasperl@chromium.org2abc4502009-07-02 07:00:29 +0000686 const int interval_;
kasperl@chromium.orga5551262010-12-07 12:49:48 +0000687 Atomic32 profiling_;
688 Atomic32 active_;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000689 PlatformData* data_; // Platform specific data.
ager@chromium.orgbeb25712010-11-29 08:02:25 +0000690 int samples_taken_; // Counts stack samples taken.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000691 DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000692};
693
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000694
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000695} } // namespace v8::internal
696
697#endif // V8_PLATFORM_H_