blob: 4ec6057c5df01d563e39d3b8a07457d5bc8e8d96 [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// 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//
36// This design has been chosen because it is simple and fast. Alternatively,
37// 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
Leon Clarkef7060e22010-06-03 12:02:55 +010047#ifdef __sun
48# ifndef signbit
49int signbit(double x);
50# endif
51#endif
52
Steve Blocka7e24c12009-10-30 11:49:00 +000053// GCC specific stuff
54#ifdef __GNUC__
55
56// Needed for va_list on at least MinGW and Android.
57#include <stdarg.h>
58
59#define __GNUC_VERSION__ (__GNUC__ * 10000 + __GNUC_MINOR__ * 100)
60
Steve Blocka7e24c12009-10-30 11:49:00 +000061#endif // __GNUC__
62
Ben Murdoch589d6972011-11-30 16:04:58 +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
Ben Murdochb0fe1622011-05-05 13:52:32 +010081#include "atomicops.h"
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +010082#include "lazy-instance.h"
Steve Block44f0eee2011-05-26 01:26:41 +010083#include "platform-tls.h"
Ben Murdochb0fe1622011-05-05 13:52:32 +010084#include "utils.h"
85#include "v8globals.h"
86
Steve Blocka7e24c12009-10-30 11:49:00 +000087namespace v8 {
88namespace internal {
89
Steve Block6ded16b2010-05-10 14:33:55 +010090// Use AtomicWord for a machine-sized pointer. It is assumed that
91// reads and writes of naturally aligned values of this type are atomic.
92typedef intptr_t AtomicWord;
93
Steve Blocka7e24c12009-10-30 11:49:00 +000094class Semaphore;
Ben Murdochb0fe1622011-05-05 13:52:32 +010095class Mutex;
Steve Blocka7e24c12009-10-30 11:49:00 +000096
97double ceiling(double x);
Steve Block3ce2e202009-11-05 08:53:23 +000098double modulo(double x, double y);
Steve Blocka7e24c12009-10-30 11:49:00 +000099
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100100// Custom implementation of sin, cos, tan and log.
101double fast_sin(double input);
102double fast_cos(double input);
103double fast_tan(double input);
104double fast_log(double input);
105double fast_sqrt(double input);
106
Steve Blocka7e24c12009-10-30 11:49:00 +0000107// Forward declarations.
108class Socket;
109
110// ----------------------------------------------------------------------------
111// OS
112//
113// This class has static methods for the different platform specific
114// functions. Add methods here to cope with differences between the
115// supported platforms.
116
117class OS {
118 public:
119 // Initializes the platform OS support. Called once at VM startup.
Ben Murdochc7cc0282012-03-05 14:35:55 +0000120 static void SetUp();
Steve Blocka7e24c12009-10-30 11:49:00 +0000121
122 // Returns the accumulated user time for thread. This routine
123 // can be used for profiling. The implementation should
124 // strive for high-precision timer resolution, preferable
125 // micro-second resolution.
126 static int GetUserTime(uint32_t* secs, uint32_t* usecs);
127
128 // Get a tick counter normalized to one tick per microsecond.
129 // Used for calculating time intervals.
130 static int64_t Ticks();
131
132 // Returns current time as the number of milliseconds since
133 // 00:00:00 UTC, January 1, 1970.
134 static double TimeCurrentMillis();
135
136 // Returns a string identifying the current time zone. The
137 // timestamp is used for determining if DST is in effect.
138 static const char* LocalTimezone(double time);
139
140 // Returns the local time offset in milliseconds east of UTC without
141 // taking daylight savings time into account.
142 static double LocalTimeOffset();
143
144 // Returns the daylight savings offset for the given time.
145 static double DaylightSavingsOffset(double time);
146
Iain Merrick75681382010-08-19 15:07:18 +0100147 // Returns last OS error.
148 static int GetLastError();
149
Steve Blocka7e24c12009-10-30 11:49:00 +0000150 static FILE* FOpen(const char* path, const char* mode);
Steve Block1e0659c2011-05-24 12:43:12 +0100151 static bool Remove(const char* path);
Steve Blocka7e24c12009-10-30 11:49:00 +0000152
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000153 // Opens a temporary file, the file is auto removed on close.
154 static FILE* OpenTemporaryFile();
155
Steve Blocka7e24c12009-10-30 11:49:00 +0000156 // Log file open mode is platform-dependent due to line ends issues.
Steve Block44f0eee2011-05-26 01:26:41 +0100157 static const char* const LogFileOpenMode;
Steve Blocka7e24c12009-10-30 11:49:00 +0000158
159 // Print output to console. This is mostly used for debugging output.
160 // On platforms that has standard terminal output, the output
161 // should go to stdout.
162 static void Print(const char* format, ...);
163 static void VPrint(const char* format, va_list args);
164
Ben Murdochb0fe1622011-05-05 13:52:32 +0100165 // Print output to a file. This is mostly used for debugging output.
166 static void FPrint(FILE* out, const char* format, ...);
167 static void VFPrint(FILE* out, const char* format, va_list args);
168
Steve Blocka7e24c12009-10-30 11:49:00 +0000169 // Print error output to console. This is mostly used for error message
170 // output. On platforms that has standard terminal output, the output
171 // should go to stderr.
172 static void PrintError(const char* format, ...);
173 static void VPrintError(const char* format, va_list args);
174
175 // Allocate/Free memory used by JS heap. Pages are readable/writable, but
176 // they are not guaranteed to be executable unless 'executable' is true.
177 // Returns the address of allocated memory, or NULL if failed.
178 static void* Allocate(const size_t requested,
179 size_t* allocated,
180 bool is_executable);
181 static void Free(void* address, const size_t size);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000182
Ben Murdochc7cc0282012-03-05 14:35:55 +0000183 // This is the granularity at which the ProtectCode(...) call can set page
184 // permissions.
185 static intptr_t CommitPageSize();
186
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000187 // Mark code segments non-writable.
188 static void ProtectCode(void* address, const size_t size);
189
190 // Assign memory as a guard page so that access will cause an exception.
191 static void Guard(void* address, const size_t size);
192
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000193 // Generate a random address to be used for hinting mmap().
194 static void* GetRandomMmapAddr();
195
Steve Blocka7e24c12009-10-30 11:49:00 +0000196 // Get the Alignment guaranteed by Allocate().
197 static size_t AllocateAlignment();
198
Steve Blocka7e24c12009-10-30 11:49:00 +0000199 // Returns an indication of whether a pointer is in a space that
200 // has been allocated by Allocate(). This method may conservatively
201 // always return false, but giving more accurate information may
202 // improve the robustness of the stack dump code in the presence of
203 // heap corruption.
204 static bool IsOutsideAllocatedSpace(void* pointer);
205
206 // Sleep for a number of milliseconds.
207 static void Sleep(const int milliseconds);
208
209 // Abort the current process.
210 static void Abort();
211
212 // Debug break.
213 static void DebugBreak();
214
215 // Walk the stack.
216 static const int kStackWalkError = -1;
217 static const int kStackWalkMaxNameLen = 256;
218 static const int kStackWalkMaxTextLen = 256;
219 struct StackFrame {
220 void* address;
221 char text[kStackWalkMaxTextLen];
222 };
223
224 static int StackWalk(Vector<StackFrame> frames);
225
226 // Factory method for creating platform dependent Mutex.
227 // Please use delete to reclaim the storage for the returned Mutex.
228 static Mutex* CreateMutex();
229
230 // Factory method for creating platform dependent Semaphore.
231 // Please use delete to reclaim the storage for the returned Semaphore.
232 static Semaphore* CreateSemaphore(int count);
233
234 // Factory method for creating platform dependent Socket.
235 // Please use delete to reclaim the storage for the returned Socket.
236 static Socket* CreateSocket();
237
238 class MemoryMappedFile {
239 public:
Steve Block1e0659c2011-05-24 12:43:12 +0100240 static MemoryMappedFile* open(const char* name);
Steve Blocka7e24c12009-10-30 11:49:00 +0000241 static MemoryMappedFile* create(const char* name, int size, void* initial);
242 virtual ~MemoryMappedFile() { }
243 virtual void* memory() = 0;
Steve Block1e0659c2011-05-24 12:43:12 +0100244 virtual int size() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000245 };
246
247 // Safe formatting print. Ensures that str is always null-terminated.
248 // Returns the number of chars written, or -1 if output was truncated.
249 static int SNPrintF(Vector<char> str, const char* format, ...);
250 static int VSNPrintF(Vector<char> str,
251 const char* format,
252 va_list args);
253
254 static char* StrChr(char* str, int c);
255 static void StrNCpy(Vector<char> dest, const char* src, size_t n);
256
Ben Murdochf87a2032010-10-22 12:50:53 +0100257 // Support for the profiler. Can do nothing, in which case ticks
258 // occuring in shared libraries will not be properly accounted for.
Steve Blocka7e24c12009-10-30 11:49:00 +0000259 static void LogSharedLibraryAddresses();
260
Ben Murdochf87a2032010-10-22 12:50:53 +0100261 // Support for the profiler. Notifies the external profiling
262 // process that a code moving garbage collection starts. Can do
263 // nothing, in which case the code objects must not move (e.g., by
264 // using --never-compact) if accurate profiling is desired.
265 static void SignalCodeMovingGC();
266
Steve Blockd0582a62009-12-15 09:54:21 +0000267 // The return value indicates the CPU features we are sure of because of the
268 // OS. For example MacOSX doesn't run on any x86 CPUs that don't have SSE2
269 // instructions.
270 // This is a little messy because the interpretation is subject to the cross
271 // of the CPU and the OS. The bits in the answer correspond to the bit
272 // positions indicated by the members of the CpuFeature enum from globals.h
273 static uint64_t CpuFeaturesImpliedByPlatform();
274
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000275 // Maximum size of the virtual memory. 0 means there is no artificial
276 // limit.
277 static intptr_t MaxVirtualMemory();
278
Steve Blocka7e24c12009-10-30 11:49:00 +0000279 // Returns the double constant NAN
280 static double nan_value();
281
Steve Blockd0582a62009-12-15 09:54:21 +0000282 // Support runtime detection of VFP3 on ARM CPUs.
283 static bool ArmCpuHasFeature(CpuFeature feature);
284
Ben Murdoch257744e2011-11-30 15:57:28 +0000285 // Support runtime detection of whether the hard float option of the
286 // EABI is used.
287 static bool ArmUsingHardFloat();
288
Steve Block44f0eee2011-05-26 01:26:41 +0100289 // Support runtime detection of FPU on MIPS CPUs.
290 static bool MipsCpuHasFeature(CpuFeature feature);
291
Steve Blocka7e24c12009-10-30 11:49:00 +0000292 // Returns the activation frame alignment constraint or zero if
293 // the platform doesn't care. Guaranteed to be a power of two.
294 static int ActivationFrameAlignment();
295
Leon Clarkef7060e22010-06-03 12:02:55 +0100296 static void ReleaseStore(volatile AtomicWord* ptr, AtomicWord value);
297
Ben Murdoch8b112d22011-06-08 16:22:53 +0100298#if defined(V8_TARGET_ARCH_IA32)
299 // Copy memory area to disjoint memory area.
300 static void MemCopy(void* dest, const void* src, size_t size);
301 // Limit below which the extra overhead of the MemCopy function is likely
302 // to outweigh the benefits of faster copying.
303 static const int kMinComplexMemCopy = 64;
304 typedef void (*MemCopyFunction)(void* dest, const void* src, size_t size);
305
306#else // V8_TARGET_ARCH_IA32
307 static void MemCopy(void* dest, const void* src, size_t size) {
308 memcpy(dest, src, size);
309 }
310 static const int kMinComplexMemCopy = 256;
311#endif // V8_TARGET_ARCH_IA32
312
Steve Blocka7e24c12009-10-30 11:49:00 +0000313 private:
314 static const int msPerSecond = 1000;
315
316 DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
317};
318
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000319// Represents and controls an area of reserved memory.
320// Control of the reserved memory can be assigned to another VirtualMemory
321// object by assignment or copy-contructing. This removes the reserved memory
322// from the original object.
Steve Blocka7e24c12009-10-30 11:49:00 +0000323class VirtualMemory {
324 public:
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000325 // Empty VirtualMemory object, controlling no reserved memory.
326 VirtualMemory();
327
Steve Blocka7e24c12009-10-30 11:49:00 +0000328 // Reserves virtual memory with size.
329 explicit VirtualMemory(size_t size);
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000330
331 // Reserves virtual memory containing an area of the given size that
332 // is aligned per alignment. This may not be at the position returned
333 // by address().
334 VirtualMemory(size_t size, size_t alignment);
335
336 // Releases the reserved memory, if any, controlled by this VirtualMemory
337 // object.
Steve Blocka7e24c12009-10-30 11:49:00 +0000338 ~VirtualMemory();
339
340 // Returns whether the memory has been reserved.
341 bool IsReserved();
342
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000343 // Initialize or resets an embedded VirtualMemory object.
344 void Reset();
345
Steve Blocka7e24c12009-10-30 11:49:00 +0000346 // Returns the start address of the reserved memory.
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000347 // If the memory was reserved with an alignment, this address is not
348 // necessarily aligned. The user might need to round it up to a multiple of
349 // the alignment to get the start of the aligned block.
Steve Blocka7e24c12009-10-30 11:49:00 +0000350 void* address() {
351 ASSERT(IsReserved());
352 return address_;
Iain Merrick9ac36c92010-09-13 15:29:50 +0100353 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000354
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000355 // Returns the size of the reserved memory. The returned value is only
356 // meaningful when IsReserved() returns true.
357 // If the memory was reserved with an alignment, this size may be larger
358 // than the requested size.
Steve Blocka7e24c12009-10-30 11:49:00 +0000359 size_t size() { return size_; }
360
361 // Commits real memory. Returns whether the operation succeeded.
362 bool Commit(void* address, size_t size, bool is_executable);
363
364 // Uncommit real memory. Returns whether the operation succeeded.
365 bool Uncommit(void* address, size_t size);
366
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000367 // Creates a single guard page at the given address.
368 bool Guard(void* address);
369
370 void Release() {
371 ASSERT(IsReserved());
372 // Notice: Order is important here. The VirtualMemory object might live
373 // inside the allocated region.
374 void* address = address_;
375 size_t size = size_;
376 Reset();
377 bool result = ReleaseRegion(address, size);
378 USE(result);
379 ASSERT(result);
380 }
381
382 // Assign control of the reserved region to a different VirtualMemory object.
383 // The old object is no longer functional (IsReserved() returns false).
384 void TakeControl(VirtualMemory* from) {
385 ASSERT(!IsReserved());
386 address_ = from->address_;
387 size_ = from->size_;
388 from->Reset();
389 }
390
391 static void* ReserveRegion(size_t size);
392
393 static bool CommitRegion(void* base, size_t size, bool is_executable);
394
395 static bool UncommitRegion(void* base, size_t size);
396
397 // Must be called with a base pointer that has been returned by ReserveRegion
398 // and the same size it was reserved with.
399 static bool ReleaseRegion(void* base, size_t size);
400
Steve Blocka7e24c12009-10-30 11:49:00 +0000401 private:
402 void* address_; // Start address of the virtual memory.
403 size_t size_; // Size of the virtual memory.
404};
405
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000406
Steve Blocka7e24c12009-10-30 11:49:00 +0000407// ----------------------------------------------------------------------------
408// Thread
409//
410// Thread objects are used for creating and running threads. When the start()
411// method is called the new thread starts running the run() method in the new
412// thread. The Thread object should not be deallocated before the thread has
413// terminated.
414
Ben Murdoch8b112d22011-06-08 16:22:53 +0100415class Thread {
Steve Blocka7e24c12009-10-30 11:49:00 +0000416 public:
417 // Opaque data type for thread-local storage keys.
Iain Merrick75681382010-08-19 15:07:18 +0100418 // LOCAL_STORAGE_KEY_MIN_VALUE and LOCAL_STORAGE_KEY_MAX_VALUE are specified
419 // to ensure that enumeration type has correct value range (see Issue 830 for
420 // more details).
421 enum LocalStorageKey {
422 LOCAL_STORAGE_KEY_MIN_VALUE = kMinInt,
423 LOCAL_STORAGE_KEY_MAX_VALUE = kMaxInt
424 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000425
Ben Murdochc7cc0282012-03-05 14:35:55 +0000426 class Options {
427 public:
428 Options() : name_("v8:<unknown>"), stack_size_(0) {}
429 Options(const char* name, int stack_size = 0)
430 : name_(name), stack_size_(stack_size) {}
Steve Block44f0eee2011-05-26 01:26:41 +0100431
Ben Murdochc7cc0282012-03-05 14:35:55 +0000432 const char* name() const { return name_; }
433 int stack_size() const { return stack_size_; }
434
435 private:
436 const char* name_;
437 int stack_size_;
Steve Block44f0eee2011-05-26 01:26:41 +0100438 };
439
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000440 // Create new thread.
441 explicit Thread(const Options& options);
Steve Blocka7e24c12009-10-30 11:49:00 +0000442 virtual ~Thread();
443
444 // Start new thread by calling the Run() method in the new thread.
445 void Start();
446
447 // Wait until thread terminates.
448 void Join();
449
Steve Block9fac8402011-05-12 15:51:54 +0100450 inline const char* name() const {
451 return name_;
452 }
453
Steve Blocka7e24c12009-10-30 11:49:00 +0000454 // Abstract method for run handler.
455 virtual void Run() = 0;
456
457 // Thread-local storage.
458 static LocalStorageKey CreateThreadLocalKey();
459 static void DeleteThreadLocalKey(LocalStorageKey key);
460 static void* GetThreadLocal(LocalStorageKey key);
461 static int GetThreadLocalInt(LocalStorageKey key) {
462 return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
463 }
464 static void SetThreadLocal(LocalStorageKey key, void* value);
465 static void SetThreadLocalInt(LocalStorageKey key, int value) {
466 SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
467 }
468 static bool HasThreadLocal(LocalStorageKey key) {
469 return GetThreadLocal(key) != NULL;
470 }
471
Steve Block44f0eee2011-05-26 01:26:41 +0100472#ifdef V8_FAST_TLS_SUPPORTED
473 static inline void* GetExistingThreadLocal(LocalStorageKey key) {
474 void* result = reinterpret_cast<void*>(
475 InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
476 ASSERT(result == GetThreadLocal(key));
477 return result;
478 }
479#else
480 static inline void* GetExistingThreadLocal(LocalStorageKey key) {
481 return GetThreadLocal(key);
482 }
483#endif
484
Steve Blocka7e24c12009-10-30 11:49:00 +0000485 // A hint to the scheduler to let another thread run.
486 static void YieldCPU();
487
Steve Block44f0eee2011-05-26 01:26:41 +0100488
Steve Block9fac8402011-05-12 15:51:54 +0100489 // The thread name length is limited to 16 based on Linux's implementation of
490 // prctl().
491 static const int kMaxThreadNameLength = 16;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100492
493 class PlatformData;
494 PlatformData* data() { return data_; }
495
Steve Blocka7e24c12009-10-30 11:49:00 +0000496 private:
Ben Murdochc7cc0282012-03-05 14:35:55 +0000497 void set_name(const char* name);
Steve Block9fac8402011-05-12 15:51:54 +0100498
Steve Blocka7e24c12009-10-30 11:49:00 +0000499 PlatformData* data_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100500
Steve Block9fac8402011-05-12 15:51:54 +0100501 char name_[kMaxThreadNameLength];
Steve Block44f0eee2011-05-26 01:26:41 +0100502 int stack_size_;
Steve Block9fac8402011-05-12 15:51:54 +0100503
Steve Blocka7e24c12009-10-30 11:49:00 +0000504 DISALLOW_COPY_AND_ASSIGN(Thread);
505};
506
507
508// ----------------------------------------------------------------------------
509// Mutex
510//
511// Mutexes are used for serializing access to non-reentrant sections of code.
512// The implementations of mutex should allow for nested/recursive locking.
513
514class Mutex {
515 public:
516 virtual ~Mutex() {}
517
518 // Locks the given mutex. If the mutex is currently unlocked, it becomes
519 // locked and owned by the calling thread, and immediately. If the mutex
520 // is already locked by another thread, suspends the calling thread until
521 // the mutex is unlocked.
522 virtual int Lock() = 0;
523
524 // Unlocks the given mutex. The mutex is assumed to be locked and owned by
525 // the calling thread on entrance.
526 virtual int Unlock() = 0;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100527
528 // Tries to lock the given mutex. Returns whether the mutex was
529 // successfully locked.
530 virtual bool TryLock() = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000531};
532
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100533struct CreateMutexTrait {
534 static Mutex* Create() {
535 return OS::CreateMutex();
536 }
537};
538
539// POD Mutex initialized lazily (i.e. the first time Pointer() is called).
540// Usage:
541// static LazyMutex my_mutex = LAZY_MUTEX_INITIALIZER;
542//
543// void my_function() {
544// ScopedLock my_lock(my_mutex.Pointer());
545// // Do something.
546// }
547//
548typedef LazyDynamicInstance<Mutex, CreateMutexTrait>::type LazyMutex;
549
550#define LAZY_MUTEX_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER
Steve Blocka7e24c12009-10-30 11:49:00 +0000551
552// ----------------------------------------------------------------------------
Ben Murdoch8b112d22011-06-08 16:22:53 +0100553// ScopedLock
Steve Blocka7e24c12009-10-30 11:49:00 +0000554//
Ben Murdoch8b112d22011-06-08 16:22:53 +0100555// Stack-allocated ScopedLocks provide block-scoped locking and
556// unlocking of a mutex.
Steve Blocka7e24c12009-10-30 11:49:00 +0000557class ScopedLock {
558 public:
559 explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
Steve Block44f0eee2011-05-26 01:26:41 +0100560 ASSERT(mutex_ != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000561 mutex_->Lock();
562 }
563 ~ScopedLock() {
564 mutex_->Unlock();
565 }
566
567 private:
568 Mutex* mutex_;
569 DISALLOW_COPY_AND_ASSIGN(ScopedLock);
570};
571
572
573// ----------------------------------------------------------------------------
574// Semaphore
575//
576// A semaphore object is a synchronization object that maintains a count. The
577// count is decremented each time a thread completes a wait for the semaphore
578// object and incremented each time a thread signals the semaphore. When the
579// count reaches zero, threads waiting for the semaphore blocks until the
580// count becomes non-zero.
581
582class Semaphore {
583 public:
584 virtual ~Semaphore() {}
585
586 // Suspends the calling thread until the semaphore counter is non zero
587 // and then decrements the semaphore counter.
588 virtual void Wait() = 0;
589
590 // Suspends the calling thread until the counter is non zero or the timeout
Ben Murdochc7cc0282012-03-05 14:35:55 +0000591 // time has passed. If timeout happens the return value is false and the
Steve Blocka7e24c12009-10-30 11:49:00 +0000592 // counter is unchanged. Otherwise the semaphore counter is decremented and
593 // true is returned. The timeout value is specified in microseconds.
594 virtual bool Wait(int timeout) = 0;
595
596 // Increments the semaphore counter.
597 virtual void Signal() = 0;
598};
599
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100600template <int InitialValue>
601struct CreateSemaphoreTrait {
602 static Semaphore* Create() {
603 return OS::CreateSemaphore(InitialValue);
604 }
605};
606
607// POD Semaphore initialized lazily (i.e. the first time Pointer() is called).
608// Usage:
609// // The following semaphore starts at 0.
610// static LazySemaphore<0>::type my_semaphore = LAZY_SEMAPHORE_INITIALIZER;
611//
612// void my_function() {
613// // Do something with my_semaphore.Pointer().
614// }
615//
616template <int InitialValue>
617struct LazySemaphore {
618 typedef typename LazyDynamicInstance<
619 Semaphore, CreateSemaphoreTrait<InitialValue> >::type type;
620};
621
622#define LAZY_SEMAPHORE_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER
623
Steve Blocka7e24c12009-10-30 11:49:00 +0000624
625// ----------------------------------------------------------------------------
626// Socket
627//
628
629class Socket {
630 public:
631 virtual ~Socket() {}
632
633 // Server initialization.
634 virtual bool Bind(const int port) = 0;
635 virtual bool Listen(int backlog) const = 0;
636 virtual Socket* Accept() const = 0;
637
638 // Client initialization.
639 virtual bool Connect(const char* host, const char* port) = 0;
640
641 // Shutdown socket for both read and write. This causes blocking Send and
642 // Receive calls to exit. After Shutdown the Socket object cannot be used for
643 // any communication.
644 virtual bool Shutdown() = 0;
645
646 // Data Transimission
647 virtual int Send(const char* data, int len) const = 0;
648 virtual int Receive(char* data, int len) const = 0;
649
650 // Set the value of the SO_REUSEADDR socket option.
651 virtual bool SetReuseAddress(bool reuse_address) = 0;
652
653 virtual bool IsValid() const = 0;
654
Ben Murdochc7cc0282012-03-05 14:35:55 +0000655 static bool SetUp();
Steve Blocka7e24c12009-10-30 11:49:00 +0000656 static int LastError();
657 static uint16_t HToN(uint16_t value);
658 static uint16_t NToH(uint16_t value);
659 static uint32_t HToN(uint32_t value);
660 static uint32_t NToH(uint32_t value);
661};
662
663
Steve Blocka7e24c12009-10-30 11:49:00 +0000664// ----------------------------------------------------------------------------
665// Sampler
666//
667// A sampler periodically samples the state of the VM and optionally
668// (if used for profiling) the program counter and stack pointer for
669// the thread that created it.
670
671// TickSample captures the information collected for each sample.
672class TickSample {
673 public:
Leon Clarked91b9f72010-01-27 17:25:45 +0000674 TickSample()
Steve Block6ded16b2010-05-10 14:33:55 +0100675 : state(OTHER),
676 pc(NULL),
Leon Clarked91b9f72010-01-27 17:25:45 +0000677 sp(NULL),
678 fp(NULL),
Ben Murdoche0cee9b2011-05-25 10:26:03 +0100679 tos(NULL),
Ben Murdoch8b112d22011-06-08 16:22:53 +0100680 frames_count(0),
681 has_external_callback(false) {}
Steve Block6ded16b2010-05-10 14:33:55 +0100682 StateTag state; // The state of the VM.
Steve Block44f0eee2011-05-26 01:26:41 +0100683 Address pc; // Instruction pointer.
684 Address sp; // Stack pointer.
685 Address fp; // Frame pointer.
686 union {
687 Address tos; // Top stack value (*sp).
688 Address external_callback;
689 };
Steve Block6ded16b2010-05-10 14:33:55 +0100690 static const int kMaxFramesCount = 64;
691 Address stack[kMaxFramesCount]; // Call stack.
Steve Block44f0eee2011-05-26 01:26:41 +0100692 int frames_count : 8; // Number of captured frames.
693 bool has_external_callback : 1;
Steve Blocka7e24c12009-10-30 11:49:00 +0000694};
695
Steve Blocka7e24c12009-10-30 11:49:00 +0000696class Sampler {
697 public:
698 // Initialize sampler.
Steve Block44f0eee2011-05-26 01:26:41 +0100699 Sampler(Isolate* isolate, int interval);
Steve Blocka7e24c12009-10-30 11:49:00 +0000700 virtual ~Sampler();
701
Steve Block44f0eee2011-05-26 01:26:41 +0100702 int interval() const { return interval_; }
703
Steve Blocka7e24c12009-10-30 11:49:00 +0000704 // Performs stack sampling.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800705 void SampleStack(TickSample* sample) {
706 DoSampleStack(sample);
707 IncSamplesTaken();
708 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000709
710 // This method is called for each sampling period with the current
711 // program counter.
712 virtual void Tick(TickSample* sample) = 0;
713
714 // Start and stop sampler.
715 void Start();
716 void Stop();
717
Ben Murdochf87a2032010-10-22 12:50:53 +0100718 // Is the sampler used for profiling?
Ben Murdochb0fe1622011-05-05 13:52:32 +0100719 bool IsProfiling() const { return NoBarrier_Load(&profiling_) > 0; }
720 void IncreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, 1); }
721 void DecreaseProfilingDepth() { NoBarrier_AtomicIncrement(&profiling_, -1); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000722
723 // Whether the sampler is running (that is, consumes resources).
Ben Murdochb0fe1622011-05-05 13:52:32 +0100724 bool IsActive() const { return NoBarrier_Load(&active_); }
Steve Blocka7e24c12009-10-30 11:49:00 +0000725
Steve Block44f0eee2011-05-26 01:26:41 +0100726 Isolate* isolate() { return isolate_; }
727
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800728 // Used in tests to make sure that stack sampling is performed.
729 int samples_taken() const { return samples_taken_; }
730 void ResetSamplesTaken() { samples_taken_ = 0; }
731
Steve Blocka7e24c12009-10-30 11:49:00 +0000732 class PlatformData;
Steve Block44f0eee2011-05-26 01:26:41 +0100733 PlatformData* data() { return data_; }
734
735 PlatformData* platform_data() { return data_; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000736
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800737 protected:
738 virtual void DoSampleStack(TickSample* sample) = 0;
739
Steve Blocka7e24c12009-10-30 11:49:00 +0000740 private:
Ben Murdochb0fe1622011-05-05 13:52:32 +0100741 void SetActive(bool value) { NoBarrier_Store(&active_, value); }
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800742 void IncSamplesTaken() { if (++samples_taken_ < 0) samples_taken_ = 0; }
743
Steve Block44f0eee2011-05-26 01:26:41 +0100744 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000745 const int interval_;
Ben Murdochb0fe1622011-05-05 13:52:32 +0100746 Atomic32 profiling_;
747 Atomic32 active_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000748 PlatformData* data_; // Platform specific data.
Shimeng (Simon) Wang8a31eba2010-12-06 19:01:33 -0800749 int samples_taken_; // Counts stack samples taken.
Steve Blocka7e24c12009-10-30 11:49:00 +0000750 DISALLOW_IMPLICIT_CONSTRUCTORS(Sampler);
751};
752
Steve Block44f0eee2011-05-26 01:26:41 +0100753
Steve Blocka7e24c12009-10-30 11:49:00 +0000754} } // namespace v8::internal
755
756#endif // V8_PLATFORM_H_