10e3f88bd850f46930aa95684377fab02a394ae41ulan@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// This module contains the platform-specific code. This make the rest of the
643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// code less dependent on operating system, compilers and runtime libraries.
743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// This module does specifically not deal with differences between different
843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// processor architecture.
943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// The platform classes have the same definition for all platforms. The
1043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// implementation for a particular platform is put in platform_<os>.cc.
1143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// The build system then uses the implementation for the target platform.
1243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
133291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org// This design has been chosen because it is simple and fast. Alternatively,
1443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// the platform dependent classes could have been implemented using abstract
1543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// superclasses with virtual methods and having specializations for each
1643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// platform. This design was rejected because it was more complicated and
1743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// slower. It would require factory methods for selecting the right
1843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// implementation and the overhead of virtual methods for performance
1943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// sensitive like mutex locking/unlocking.
2043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
215de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#ifndef V8_BASE_PLATFORM_PLATFORM_H_
225de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#define V8_BASE_PLATFORM_PLATFORM_H_
2343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
24e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org#include <stdarg.h>
251845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org#include <string>
261845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org#include <vector>
27662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org
288ddb15e9094939a28890ee8bbc7f7fa246ecea49machenbach@chromium.org#include "src/base/build_config.h"
295de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/mutex.h"
305de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/semaphore.h"
31662436e7b124b3535773535c671c53db322070b5verwaest@chromium.org
3255ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.org#ifdef __sun
3355ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.org# ifndef signbit
3477ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.orgnamespace std {
3555ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.orgint signbit(double x);
3677ca49ac05d25684c89442029c22f5b2bce94395ulan@chromium.org}
3755ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.org# endif
3855ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.org#endif
3955ee80713569ab0324fc8dcedcb5518501daa6a6ricow@chromium.org
409ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#if V8_OS_QNX
415de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/qnx-math.h"
429ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org#endif
439ca3017c616a778baff6d57c68d6d4746a130036ulan@chromium.org
44245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org// Microsoft Visual C++ specific stuff.
4505150ab746caefd8e734c394ecc7863200ca04cfmachenbach@chromium.org#if V8_LIBC_MSVCRT
46245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org
471e2d50cf3d94ff48285da107b7a9da1ad0fc873dmachenbach@chromium.org#include "src/base/win32-headers.h"
485de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/win32-math.h"
4943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
50245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.orgint strncasecmp(const char* s1, const char* s2, int n);
51245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org
52528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org// Visual C++ 2013 and higher implement this function.
53528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org#if (_MSC_VER < 1800)
5446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.orginline int lrint(double flt) {
5546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  int intgr;
56864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
5746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  __asm {
5846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    fld flt
5946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    fistp intgr
6046839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  };
6146839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org#else
6246839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  intgr = static_cast<int>(flt + 0.5);
6346839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  if ((intgr & 1) != 0 && intgr - flt == 0.5) {
6446839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    // If the number is halfway between two integers, round to the even one.
6546839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org    intgr--;
6646839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  }
6746839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org#endif
6846839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org  return intgr;
6946839fbbdee40a3d2d924e8b5b13c4139b0b24f2yangguo@chromium.org}
70528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org#endif  // _MSC_VER < 1800
71528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org
7205150ab746caefd8e734c394ecc7863200ca04cfmachenbach@chromium.org#endif  // V8_LIBC_MSVCRT
73245aa859d34fd516161c48ef4c69d38d9b889284iposva@chromium.org
7471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgnamespace v8 {
755de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.orgnamespace base {
7643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
7743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// ----------------------------------------------------------------------------
78fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org// Fast TLS support
79fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org
80fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org#ifndef V8_NO_FAST_TLS
81fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org
82864abd7677f434b5aef191e3388e71cd4dd1e6c8machenbach@chromium.org#if defined(_MSC_VER) && (V8_HOST_ARCH_IA32)
83fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org
84fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org#define V8_FAST_TLS_SUPPORTED 1
85fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org
86fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.orgINLINE(intptr_t InternalGetExistingThreadLocal(intptr_t index));
87fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org
88fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.orginline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
89fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  const intptr_t kTibInlineTlsOffset = 0xE10;
90fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  const intptr_t kTibExtraTlsOffset = 0xF94;
91fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  const intptr_t kMaxInlineSlots = 64;
92fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  const intptr_t kMaxSlots = kMaxInlineSlots + 1024;
9370ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org  const intptr_t kPointerSize = sizeof(void*);
94e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(0 <= index && index < kMaxSlots);
95fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  if (index < kMaxInlineSlots) {
96fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org    return static_cast<intptr_t>(__readfsdword(kTibInlineTlsOffset +
97fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org                                               kPointerSize * index));
98fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  }
99fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  intptr_t extra = static_cast<intptr_t>(__readfsdword(kTibExtraTlsOffset));
100e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(extra != 0);
101fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  return *reinterpret_cast<intptr_t*>(extra +
102fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org                                      kPointerSize * (index - kMaxInlineSlots));
103fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org}
104fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org
105fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org#elif defined(__APPLE__) && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
106fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org
107fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org#define V8_FAST_TLS_SUPPORTED 1
108fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org
109fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.orgextern intptr_t kMacTlsBaseOffset;
110fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org
111fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.orgINLINE(intptr_t InternalGetExistingThreadLocal(intptr_t index));
112fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org
113fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.orginline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
114fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  intptr_t result;
115fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org#if V8_HOST_ARCH_IA32
116fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  asm("movl %%gs:(%1,%2,4), %0;"
117fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org      :"=r"(result)  // Output must be a writable register.
118fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org      :"r"(kMacTlsBaseOffset), "r"(index));
119fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org#else
120fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  asm("movq %%gs:(%1,%2,8), %0;"
121fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org      :"=r"(result)
122fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org      :"r"(kMacTlsBaseOffset), "r"(index));
123fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org#endif
124fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org  return result;
125fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org}
126fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org
127fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org#endif
128fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org
129fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org#endif  // V8_NO_FAST_TLS
130fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org
131fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org
1326b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgclass TimezoneCache;
1336b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
1346b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
135fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.org// ----------------------------------------------------------------------------
13643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// OS
13743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
13843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// This class has static methods for the different platform specific
13943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// functions. Add methods here to cope with differences between the
14043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// supported platforms.
14143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
14243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenclass OS {
14343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen public:
144248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org  // Initialize the OS class.
145248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org  // - random_seed: Used for the GetRandomMmapAddress() if non-zero.
146248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org  // - hard_abort: If true, OS::Abort() will crash instead of aborting.
147248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org  // - gc_fake_mmap: Name of the file for fake gc mmap used in ll_prof.
148248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org  static void Initialize(int64_t random_seed,
149248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org                         bool hard_abort,
150248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org                         const char* const gc_fake_mmap);
151248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org
15243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Returns the accumulated user time for thread. This routine
15343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // can be used for profiling. The implementation should
15443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // strive for high-precision timer resolution, preferable
15543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // micro-second resolution.
15643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static int GetUserTime(uint32_t* secs,  uint32_t* usecs);
15743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
15843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Returns current time as the number of milliseconds since
15943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // 00:00:00 UTC, January 1, 1970.
16043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static double TimeCurrentMillis();
16143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
1626b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  static TimezoneCache* CreateTimezoneCache();
1636b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  static void DisposeTimezoneCache(TimezoneCache* cache);
1646b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  static void ClearTimezoneCache(TimezoneCache* cache);
1656b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
16643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Returns a string identifying the current time zone. The
16743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // timestamp is used for determining if DST is in effect.
1686b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  static const char* LocalTimezone(double time, TimezoneCache* cache);
16943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
17043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Returns the local time offset in milliseconds east of UTC without
17143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // taking daylight savings time into account.
1726b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  static double LocalTimeOffset(TimezoneCache* cache);
17343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
17443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Returns the daylight savings offset for the given time.
1756b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  static double DaylightSavingsOffset(double time, TimezoneCache* cache);
176486536df718553960f9700559e80e5b10b0d5994dslomov@chromium.org
177ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org  // Returns last OS error.
178ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org  static int GetLastError();
179ea4f62e1df22417fc8dc2c2425485dca98b13d07ager@chromium.org
180b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org  static FILE* FOpen(const char* path, const char* mode);
1810a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org  static bool Remove(const char* path);
182b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
183030d38ee536bc25856546e75fdac60d1a0c42bddwhesse@chromium.org  // Opens a temporary file, the file is auto removed on close.
184030d38ee536bc25856546e75fdac60d1a0c42bddwhesse@chromium.org  static FILE* OpenTemporaryFile();
185030d38ee536bc25856546e75fdac60d1a0c42bddwhesse@chromium.org
18671daaf639544be2a6638e3566f78e0b14f05cd7bager@chromium.org  // Log file open mode is platform-dependent due to line ends issues.
187ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  static const char* const LogFileOpenMode;
18871daaf639544be2a6638e3566f78e0b14f05cd7bager@chromium.org
18943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Print output to console. This is mostly used for debugging output.
19043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // On platforms that has standard terminal output, the output
19143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // should go to stdout.
19243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static void Print(const char* format, ...);
19343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static void VPrint(const char* format, va_list args);
19443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
195023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  // Print output to a file. This is mostly used for debugging output.
196023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  static void FPrint(FILE* out, const char* format, ...);
197023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org  static void VFPrint(FILE* out, const char* format, va_list args);
198023421e6892b2ba6dcd2bbee117e0bfb24545cf7whesse@chromium.org
19943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Print error output to console. This is mostly used for error message
20043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // output. On platforms that has standard terminal output, the output
20143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // should go to stderr.
20243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static void PrintError(const char* format, ...);
20343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static void VPrintError(const char* format, va_list args);
20443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2053291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Allocate/Free memory used by JS heap. Pages are readable/writable, but
2067276f14ca716596e0a0d17539516370c1f453847kasper.lund  // they are not guaranteed to be executable unless 'executable' is true.
20743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Returns the address of allocated memory, or NULL if failed.
2087276f14ca716596e0a0d17539516370c1f453847kasper.lund  static void* Allocate(const size_t requested,
2097276f14ca716596e0a0d17539516370c1f453847kasper.lund                        size_t* allocated,
210f5aa83707f1db5aecb22f6c3bfd5042f629d5fcfkasperl@chromium.org                        bool is_executable);
211f5aa83707f1db5aecb22f6c3bfd5042f629d5fcfkasperl@chromium.org  static void Free(void* address, const size_t size);
212d4e9e2260ea982962098fd5ccae7593549f7686elrn@chromium.org
21364e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // This is the granularity at which the ProtectCode(...) call can set page
21464e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  // permissions.
21564e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org  static intptr_t CommitPageSize();
21664e3a4be4a99f31920128de34573c8ac9038de42ricow@chromium.org
217d4e9e2260ea982962098fd5ccae7593549f7686elrn@chromium.org  // Mark code segments non-writable.
218d4e9e2260ea982962098fd5ccae7593549f7686elrn@chromium.org  static void ProtectCode(void* address, const size_t size);
219717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org
220717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org  // Assign memory as a guard page so that access will cause an exception.
221717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org  static void Guard(void* address, const size_t size);
222717967fd64e99e759ff094df6f069440cc866266rossberg@chromium.org
223b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org  // Generate a random address to be used for hinting mmap().
224b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org  static void* GetRandomMmapAddr();
225b4b2aa69a9f12525fca190287f47a66d7bdcb3aerossberg@chromium.org
22643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Get the Alignment guaranteed by Allocate().
22743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static size_t AllocateAlignment();
22843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2293291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  // Sleep for a number of milliseconds.
2303291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org  static void Sleep(const int milliseconds);
23143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
23243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Abort the current process.
23343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static void Abort();
23443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2357276f14ca716596e0a0d17539516370c1f453847kasper.lund  // Debug break.
2367276f14ca716596e0a0d17539516370c1f453847kasper.lund  static void DebugBreak();
2377276f14ca716596e0a0d17539516370c1f453847kasper.lund
23843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Walk the stack.
23943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static const int kStackWalkError = -1;
24043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static const int kStackWalkMaxNameLen = 256;
24143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static const int kStackWalkMaxTextLen = 256;
24243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  struct StackFrame {
24343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    void* address;
24443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    char text[kStackWalkMaxTextLen];
24543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  };
24643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
24743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  class MemoryMappedFile {
24843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen   public:
2490a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    static MemoryMappedFile* open(const char* name);
25043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    static MemoryMappedFile* create(const char* name, int size, void* initial);
25143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    virtual ~MemoryMappedFile() { }
25243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    virtual void* memory() = 0;
2530a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org    virtual int size() = 0;
25443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  };
25543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2567276f14ca716596e0a0d17539516370c1f453847kasper.lund  // Safe formatting print. Ensures that str is always null-terminated.
2577276f14ca716596e0a0d17539516370c1f453847kasper.lund  // Returns the number of chars written, or -1 if output was truncated.
25870ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org  static int SNPrintF(char* str, int length, const char* format, ...);
25970ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org  static int VSNPrintF(char* str,
26070ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org                       int length,
26143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                       const char* format,
26243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen                       va_list args);
26343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
264381abbb58260f2fc7d346d0e2f83d0f132a4c14bager@chromium.org  static char* StrChr(char* str, int c);
26570ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org  static void StrNCpy(char* dest, int length, const char* src, size_t n);
266b912362e2b2e704d09faac4290e027fd744bf587kasperl@chromium.org
2674a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  // Support for the profiler.  Can do nothing, in which case ticks
2684a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  // occuring in shared libraries will not be properly accounted for.
2691845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  struct SharedLibraryAddress {
2701845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    SharedLibraryAddress(
2711845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org        const std::string& library_path, uintptr_t start, uintptr_t end)
2721845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org        : library_path(library_path), start(start), end(end) {}
2731845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org
2741845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    std::string library_path;
2751845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    uintptr_t start;
2761845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org    uintptr_t end;
2771845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  };
2781845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org
2791845eb0120c7a870d7388de091246a7d1b48a4f8machenbach@chromium.org  static std::vector<SharedLibraryAddress> GetSharedLibraryAddresses();
28043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2814a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  // Support for the profiler.  Notifies the external profiling
2824a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  // process that a code moving garbage collection starts.  Can do
2834a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  // nothing, in which case the code objects must not move (e.g., by
2844a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  // using --never-compact) if accurate profiling is desired.
2854a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org  static void SignalCodeMovingGC();
2864a5224e84636d192e82f288bfab0d308bdae5c37whesse@chromium.org
28743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Returns the double constant NAN
28843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static double nan_value();
28943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
2908e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  // Support runtime detection of whether the hard float option of the
2918e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  // EABI is used.
2928e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org  static bool ArmUsingHardFloat();
2938e8294a88dc7d58f579aee0ba08c19fc8a616e2dsgjesse@chromium.org
294236ad9617a7359a463144a6ebeb5431a70f769cfager@chromium.org  // Returns the activation frame alignment constraint or zero if
295236ad9617a7359a463144a6ebeb5431a70f769cfager@chromium.org  // the platform doesn't care. Guaranteed to be a power of two.
296236ad9617a7359a463144a6ebeb5431a70f769cfager@chromium.org  static int ActivationFrameAlignment();
297236ad9617a7359a463144a6ebeb5431a70f769cfager@chromium.org
298657d53b99cb4d261f8245bcb4248c39eb0a2b10frossberg@chromium.org  static int GetCurrentProcessId();
299657d53b99cb4d261f8245bcb4248c39eb0a2b10frossberg@chromium.org
300d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org  static int GetCurrentThreadId();
301d0bddc653152f270a27fe32d5d7b0f5c0fa3b00cmachenbach@chromium.org
30243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen private:
30343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static const int msPerSecond = 1000;
30431e7138e1a05e29ceefa8919ae12cb621a48ca7fmads.s.ager
305248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org#if V8_OS_POSIX
306248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org  static const char* GetGCFakeMMapFile();
307248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org#endif
308248dd43badb99ffce44eae2d767cda3cefaad521machenbach@chromium.org
30931e7138e1a05e29ceefa8919ae12cb621a48ca7fmads.s.ager  DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
31043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
31143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
312c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Represents and controls an area of reserved memory.
313c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// Control of the reserved memory can be assigned to another VirtualMemory
314c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// object by assignment or copy-contructing. This removes the reserved memory
315c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com// from the original object.
31643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansenclass VirtualMemory {
31743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen public:
318c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Empty VirtualMemory object, controlling no reserved memory.
319c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  VirtualMemory();
320c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
32143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Reserves virtual memory with size.
3229258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  explicit VirtualMemory(size_t size);
323c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
324c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Reserves virtual memory containing an area of the given size that
325c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // is aligned per alignment. This may not be at the position returned
326c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // by address().
327c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  VirtualMemory(size_t size, size_t alignment);
328c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
329c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Releases the reserved memory, if any, controlled by this VirtualMemory
330c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // object.
33143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  ~VirtualMemory();
33243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
33343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Returns whether the memory has been reserved.
33443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool IsReserved();
33543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
336c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Initialize or resets an embedded VirtualMemory object.
337c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void Reset();
338c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
33943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Returns the start address of the reserved memory.
340c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // If the memory was reserved with an alignment, this address is not
341c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // necessarily aligned. The user might need to round it up to a multiple of
342c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // the alignment to get the start of the aligned block.
34343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  void* address() {
344e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(IsReserved());
34543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen    return address_;
3463cdd9e13bac71e7c5b63da6962f8d30f6622db14kmillikin@chromium.org  }
34743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
348c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Returns the size of the reserved memory. The returned value is only
349c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // meaningful when IsReserved() returns true.
350c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // If the memory was reserved with an alignment, this size may be larger
351c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // than the requested size.
35243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  size_t size() { return size_; }
35343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
35443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Commits real memory. Returns whether the operation succeeded.
355f5aa83707f1db5aecb22f6c3bfd5042f629d5fcfkasperl@chromium.org  bool Commit(void* address, size_t size, bool is_executable);
35643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
35743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Uncommit real memory.  Returns whether the operation succeeded.
35843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  bool Uncommit(void* address, size_t size);
35943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
360ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org  // Creates a single guard page at the given address.
361ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org  bool Guard(void* address);
362ab30bb83bf3dae0053739c57b1db9ad13c1f9e3ayangguo@chromium.org
363c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void Release() {
364e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(IsReserved());
365c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // Notice: Order is important here. The VirtualMemory object might live
366c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    // inside the allocated region.
367c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    void* address = address_;
368c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    size_t size = size_;
369c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    Reset();
370c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    bool result = ReleaseRegion(address, size);
371c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    USE(result);
372e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(result);
373c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
374c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
375c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Assign control of the reserved region to a different VirtualMemory object.
376c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // The old object is no longer functional (IsReserved() returns false).
377c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  void TakeControl(VirtualMemory* from) {
378e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!IsReserved());
379c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    address_ = from->address_;
380c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    size_ = from->size_;
381c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    from->Reset();
382c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
383c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
384c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  static void* ReserveRegion(size_t size);
385c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
386c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  static bool CommitRegion(void* base, size_t size, bool is_executable);
387c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
388c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  static bool UncommitRegion(void* base, size_t size);
389c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
390c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // Must be called with a base pointer that has been returned by ReserveRegion
391c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  // and the same size it was reserved with.
392c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  static bool ReleaseRegion(void* base, size_t size);
393c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
39472204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org  // Returns true if OS performs lazy commits, i.e. the memory allocation call
39572204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org  // defers actual physical memory allocation till the first memory access.
39672204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org  // Otherwise returns false.
39772204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org  static bool HasLazyCommits();
39872204d59e7fb1b8a0e9012e1fac5ef160351e8e4danno@chromium.org
39943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen private:
40043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  void* address_;  // Start address of the virtual memory.
40143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  size_t size_;  // Size of the virtual memory.
40243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
40343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
404c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
40543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// ----------------------------------------------------------------------------
40643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Thread
40743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen//
40843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// Thread objects are used for creating and running threads. When the start()
40943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// method is called the new thread starts running the run() method in the new
41043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// thread. The Thread object should not be deallocated before the thread has
41143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen// terminated.
41243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
413a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.orgclass Thread {
41443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen public:
41543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Opaque data type for thread-local storage keys.
41670ec1a2160dd946b9578d04d97d631a6d4ab4f8cbmeurer@chromium.org  typedef int32_t LocalStorageKey;
41743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
418659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org  class Options {
419659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org   public:
420659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org    Options() : name_("v8:<unknown>"), stack_size_(0) {}
4215e57059e20217fd540b60c237d326414afe2171emachenbach@chromium.org    explicit Options(const char* name, int stack_size = 0)
422659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org        : name_(name), stack_size_(stack_size) {}
423659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org
424659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org    const char* name() const { return name_; }
425659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org    int stack_size() const { return stack_size_; }
426ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
427659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org   private:
428659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org    const char* name_;
429659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org    int stack_size_;
430ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  };
431ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
4326d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  // Create new thread.
4336d786c9805481bd13ecb29c3155540f2f32950e1svenpanne@chromium.org  explicit Thread(const Options& options);
43443d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  virtual ~Thread();
43543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
436e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Start new thread by calling the Run() method on the new thread.
43743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  void Start();
43843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
439e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Start new thread and wait until Run() method is called on the new thread.
440e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  void StartSynchronously() {
441e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    start_semaphore_ = new Semaphore(0);
442e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    Start();
443e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    start_semaphore_->Wait();
444e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    delete start_semaphore_;
445e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    start_semaphore_ = NULL;
446e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
447e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
44843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Wait until thread terminates.
44943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  void Join();
45043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4515d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  inline const char* name() const {
4525d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org    return name_;
4535d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  }
4545d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
45543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Abstract method for run handler.
45643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  virtual void Run() = 0;
45743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
45843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // Thread-local storage.
45943d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static LocalStorageKey CreateThreadLocalKey();
46043d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static void DeleteThreadLocalKey(LocalStorageKey key);
46143d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static void* GetThreadLocal(LocalStorageKey key);
4629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  static int GetThreadLocalInt(LocalStorageKey key) {
4639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    return static_cast<int>(reinterpret_cast<intptr_t>(GetThreadLocal(key)));
4649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
46543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static void SetThreadLocal(LocalStorageKey key, void* value);
4669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  static void SetThreadLocalInt(LocalStorageKey key, int value) {
4679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    SetThreadLocal(key, reinterpret_cast<void*>(static_cast<intptr_t>(value)));
4689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
4699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  static bool HasThreadLocal(LocalStorageKey key) {
4709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org    return GetThreadLocal(key) != NULL;
4719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org  }
47243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
4737979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org#ifdef V8_FAST_TLS_SUPPORTED
4747979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  static inline void* GetExistingThreadLocal(LocalStorageKey key) {
4757979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    void* result = reinterpret_cast<void*>(
4767979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org        InternalGetExistingThreadLocal(static_cast<intptr_t>(key)));
477e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(result == GetThreadLocal(key));
4787979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    return result;
4797979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  }
4807979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org#else
4817979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  static inline void* GetExistingThreadLocal(LocalStorageKey key) {
4827979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    return GetThreadLocal(key);
4837979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  }
4847979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org#endif
4857979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
48643d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  // A hint to the scheduler to let another thread run.
48743d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  static void YieldCPU();
48843d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
489ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
4905d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // The thread name length is limited to 16 based on Linux's implementation of
4915d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  // prctl().
4925d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  static const int kMaxThreadNameLength = 16;
493a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org
494a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org  class PlatformData;
495a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org  PlatformData* data() { return data_; }
496a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org
497e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  void NotifyStartedAndRun() {
498e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    if (start_semaphore_) start_semaphore_->Signal();
499e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    Run();
500e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
501e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
50243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen private:
503f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  void set_name(const char* name);
5045d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
50543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen  PlatformData* data_;
506a9aa5fa8ae2a2b43a94e6462ded2cd51445e9ee3ager@chromium.org
5075d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org  char name_[kMaxThreadNameLength];
508ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org  int stack_size_;
509e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Semaphore* start_semaphore_;
5105d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org
5119a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  DISALLOW_COPY_AND_ASSIGN(Thread);
51243d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen};
51343d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
5145de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org} }  // namespace v8::base
51543d26ecc3563a46f62a0224030667c8f8f3f6cebchristian.plesner.hansen
5165de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#endif  // V8_BASE_PLATFORM_PLATFORM_H_
517