13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Redistribution and use in source and binary forms, with or without
3d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// modification, are permitted provided that the following conditions are
4d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// met:
5d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//
6d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//     * Redistributions of source code must retain the above copyright
7d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       notice, this list of conditions and the following disclaimer.
8d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//     * Redistributions in binary form must reproduce the above
9d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       copyright notice, this list of conditions and the following
10d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       disclaimer in the documentation and/or other materials provided
11d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       with the distribution.
12d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//     * Neither the name of Google Inc. nor the names of its
13d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       contributors may be used to endorse or promote products derived
14d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//       from this software without specific prior written permission.
15d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke//
16d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
28d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Platform specific code for Solaris 10 goes here. For the POSIX comaptible
29d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// parts the implementation is in platform-posix.cc.
30d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
31d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#ifdef __sparc
32d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke# error "V8 does not support the SPARC CPU architecture."
33d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#endif
34d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
35d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <sys/stack.h>  // for stack alignment
36d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <unistd.h>  // getpagesize(), usleep()
37d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <sys/mman.h>  // mmap()
38f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#include <ucontext.h>  // walkstack(), getcontext()
39f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#include <dlfcn.h>     // dladdr
40d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <pthread.h>
41d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <sched.h>  // for sched_yield
42d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <semaphore.h>
43d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <time.h>
44d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <sys/time.h>  // gettimeofday(), timeradd()
45d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <errno.h>
46d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <ieeefp.h>  // finite()
47d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include <signal.h>  // sigemptyset(), etc
4844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include <sys/regset.h>
49d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
50d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
51d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#undef MAP_TYPE
52d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
53d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "v8.h"
54d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "platform-posix.h"
56d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#include "platform.h"
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "v8threads.h"
58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "vm-state-inl.h"
59d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
60d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
61f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// It seems there is a bug in some Solaris distributions (experienced in
62f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// SunOS 5.10 Generic_141445-09) which make it difficult or impossible to
63f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// access signbit() despite the availability of other C99 math functions.
64f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#ifndef signbit
65f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke// Test sign - usually defined in math.h
66f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkeint signbit(double x) {
67f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // We need to take care of the special case of both positive and negative
68f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // versions of zero.
69f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (x == 0) {
70f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return fpclass(x) & FP_NZERO;
71f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
72f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // This won't detect negative NaN but that should be okay since we don't
73f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // assume that behavior.
74f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return x < 0;
75f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
76f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
77f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif  // signbit
78f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
79d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkenamespace v8 {
80d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkenamespace internal {
81d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
82d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
83d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// 0 is never a valid thread id on Solaris since the main thread is 1 and
84d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// subsequent have their ids incremented from there
85d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic const pthread_t kNoThread = (pthread_t) 0;
86d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
87d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
88d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkedouble ceiling(double x) {
89d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return ceil(x);
90d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
91d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
92d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstatic Mutex* limit_mutex = NULL;
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::SetUp() {
95d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Seed the random number generator.
96d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Convert the current time to a 64-bit integer first, before converting it
97d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // to an unsigned. Going directly will cause an overflow and the seed to be
98d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // set to all ones. The seed will be identical for different instances that
99d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // call this setup code within the same millisecond.
100d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
101d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  srandom(static_cast<unsigned int>(seed));
1023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  limit_mutex = CreateMutex();
103d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
104d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
105d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid OS::PostSetUp() {
1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Math functions depend on CPU features therefore they are initialized after
1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // CPU.
1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MathSetup();
1103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
113d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeuint64_t OS::CpuFeaturesImpliedByPlatform() {
114d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return 0;  // Solaris runs on a lot of things.
115d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
116d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
117d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
118d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeint OS::ActivationFrameAlignment() {
1197d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  // GCC generates code that requires 16 byte alignment such as movdqa.
1207d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch  return Max(STACK_ALIGN, 16);
121d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
122d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
123d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdochvoid OS::ReleaseStore(volatile AtomicWord* ptr, AtomicWord value) {
1257f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  __asm__ __volatile__("" : : : "memory");
1267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  *ptr = value;
1277f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
1287f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
1297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
130d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeconst char* OS::LocalTimezone(double time) {
131d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (isnan(time)) return "";
132d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  time_t tv = static_cast<time_t>(floor(time/msPerSecond));
133d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  struct tm* t = localtime(&tv);
134d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (NULL == t) return "";
135d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return tzname[0];  // The location of the timezone string on Solaris.
136d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
137d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
138d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
139d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkedouble OS::LocalTimeOffset() {
140d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // On Solaris, struct tm does not contain a tm_gmtoff field.
141d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  time_t utc = time(NULL);
142d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT(utc != -1);
143d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  struct tm* loc = localtime(&utc);
144d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT(loc != NULL);
145d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return static_cast<double>((mktime(loc) - utc) * msPerSecond);
146d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
147d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
148d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
149d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// We keep the lowest and highest addresses mapped as a quick way of
150d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// determining that pointers are outside the heap (used mostly in assertions
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// and verification).  The estimate is conservative, i.e., not all addresses in
152d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// 'allocated' space are actually allocated to our heap.  The range is
153d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// [lowest, highest), inclusive on the low and and exclusive on the high end.
154d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic void* lowest_ever_allocated = reinterpret_cast<void*>(-1);
155d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic void* highest_ever_allocated = reinterpret_cast<void*>(0);
156d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
157d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
158d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic void UpdateAllocatedSpaceLimits(void* address, int size) {
1593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(limit_mutex != NULL);
1603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ScopedLock lock(limit_mutex);
1613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
162d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  lowest_ever_allocated = Min(lowest_ever_allocated, address);
163d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  highest_ever_allocated =
164d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      Max(highest_ever_allocated,
165d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke          reinterpret_cast<void*>(reinterpret_cast<char*>(address) + size));
166d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
167d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
168d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
169d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkebool OS::IsOutsideAllocatedSpace(void* address) {
170d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return address < lowest_ever_allocated || address >= highest_ever_allocated;
171d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
172d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
173d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
174d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkesize_t OS::AllocateAlignment() {
175d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return static_cast<size_t>(getpagesize());
176d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
177d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
178d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
179d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid* OS::Allocate(const size_t requested,
180d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                   size_t* allocated,
181d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                   bool is_executable) {
182d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const size_t msize = RoundUp(requested, getpagesize());
183d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
184d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
185d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
186d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (mbase == MAP_FAILED) {
18744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    LOG(ISOLATE, StringEvent("OS::Allocate", "mmap failed"));
188d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return NULL;
189d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
190d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  *allocated = msize;
191d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  UpdateAllocatedSpaceLimits(mbase, msize);
192d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return mbase;
193d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
194d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
195d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
196d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid OS::Free(void* address, const size_t size) {
197d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // TODO(1240712): munmap has a return value which is ignored here.
198d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int result = munmap(address, size);
199d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  USE(result);
200d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT(result == 0);
201d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
202d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
203d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
204d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid OS::Sleep(int milliseconds) {
205d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  useconds_t ms = static_cast<useconds_t>(milliseconds);
206d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  usleep(1000 * ms);
207d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
208d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
209d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
210d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid OS::Abort() {
211d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Redirect to std abort to signal abnormal program termination.
212d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  abort();
213d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
214d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
215d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
216d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid OS::DebugBreak() {
217d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  asm("int $3");
218d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
219d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
220d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
221d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass PosixMemoryMappedFile : public OS::MemoryMappedFile {
222d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public:
223d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  PosixMemoryMappedFile(FILE* file, void* memory, int size)
224d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    : file_(file), memory_(memory), size_(size) { }
225d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual ~PosixMemoryMappedFile();
226d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual void* memory() { return memory_; }
2271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  virtual int size() { return size_; }
228d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private:
229d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  FILE* file_;
230d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void* memory_;
231d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int size_;
232d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke};
233d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
234d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2351e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockOS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  FILE* file = fopen(name, "r+");
2371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (file == NULL) return NULL;
2381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  fseek(file, 0, SEEK_END);
2401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int size = ftell(file);
2411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  void* memory =
2431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
2441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return new PosixMemoryMappedFile(file, memory, size);
2451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
2461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
248d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeOS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
249d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    void* initial) {
250d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  FILE* file = fopen(name, "w+");
251d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (file == NULL) return NULL;
252d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int result = fwrite(initial, size, 1, file);
253d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (result < 1) {
254d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    fclose(file);
255d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return NULL;
256d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
257d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  void* memory =
258d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
259d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return new PosixMemoryMappedFile(file, memory, size);
260d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
261d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
262d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
263d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkePosixMemoryMappedFile::~PosixMemoryMappedFile() {
264d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (memory_) munmap(memory_, size_);
265d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  fclose(file_);
266d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
267d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
268d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
269d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid OS::LogSharedLibraryAddresses() {
270d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
271d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
272d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
273f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochvoid OS::SignalCodeMovingGC() {
274f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch}
275f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
276f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch
277f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkestruct StackWalker {
278f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Vector<OS::StackFrame>& frames;
279f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int index;
280f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke};
281d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
282d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
283f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkestatic int StackWalkCallback(uintptr_t pc, int signo, void* data) {
284f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  struct StackWalker* walker = static_cast<struct StackWalker*>(data);
285f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Dl_info info;
286f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
287f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  int i = walker->index;
288f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
289f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  walker->frames[i].address = reinterpret_cast<void*>(pc);
290d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
291f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  // Make sure line termination is in place.
292f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  walker->frames[i].text[OS::kStackWalkMaxTextLen - 1] = '\0';
293f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
294f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  Vector<char> text = MutableCStrVector(walker->frames[i].text,
295f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                                        OS::kStackWalkMaxTextLen);
296f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
297f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (dladdr(reinterpret_cast<void*>(pc), &info) == 0) {
298f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    OS::SNPrintF(text, "[0x%p]", pc);
299f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else if ((info.dli_fname != NULL && info.dli_sname != NULL)) {
300f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // We have symbol info.
301f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    OS::SNPrintF(text, "%s'%s+0x%x", info.dli_fname, info.dli_sname, pc);
302f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  } else {
303f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    // No local symbol info.
304f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    OS::SNPrintF(text,
305f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 "%s'0x%p [0x%p]",
306f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 info.dli_fname,
307f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 pc - reinterpret_cast<uintptr_t>(info.dli_fbase),
308f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke                 pc);
309d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
310f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  walker->index++;
311f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return 0;
312f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke}
313d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
314d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
315f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarkeint OS::StackWalk(Vector<OS::StackFrame> frames) {
316f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  ucontext_t ctx;
317f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  struct StackWalker walker = { frames, 0 };
318f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
319f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (getcontext(&ctx) < 0) return kStackWalkError;
320f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
321f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  if (!walkcontext(&ctx, StackWalkCallback, &walker)) {
322f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke    return kStackWalkError;
323f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  }
324f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke
325f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke  return walker.index;
326d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
327d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
328d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
329d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Constants used for mmap.
330d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic const int kMmapFd = -1;
331d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic const int kMmapFdOffset = 0;
332d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
333d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVirtualMemory::VirtualMemory() : address_(NULL), size_(0) { }
3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
336d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeVirtualMemory::VirtualMemory(size_t size) {
3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  address_ = ReserveRegion(size);
338d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  size_ = size;
339d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
340d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
341d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochVirtualMemory::VirtualMemory(size_t size, size_t alignment)
3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    : address_(NULL), size_(0) {
3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(IsAligned(alignment, static_cast<intptr_t>(OS::AllocateAlignment())));
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  size_t request_size = RoundUp(size + alignment,
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                static_cast<intptr_t>(OS::AllocateAlignment()));
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void* reservation = mmap(OS::GetRandomMmapAddr(),
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           request_size,
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           PROT_NONE,
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           kMmapFd,
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                           kMmapFdOffset);
3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (reservation == MAP_FAILED) return;
3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address base = static_cast<Address>(reservation);
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address aligned_base = RoundUp(base, alignment);
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_LE(base, aligned_base);
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Unmap extra memory reserved before and after the desired block.
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (aligned_base != base) {
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    size_t prefix_size = static_cast<size_t>(aligned_base - base);
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    OS::Free(base, prefix_size);
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    request_size -= prefix_size;
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT_LE(aligned_size, request_size);
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (aligned_size != request_size) {
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    size_t suffix_size = request_size - aligned_size;
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    OS::Free(aligned_base + aligned_size, suffix_size);
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    request_size -= suffix_size;
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(aligned_size == request_size);
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  address_ = static_cast<void*>(aligned_base);
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  size_ = aligned_size;
3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
382d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeVirtualMemory::~VirtualMemory() {
383d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (IsReserved()) {
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    bool result = ReleaseRegion(address(), size());
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(result);
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    USE(result);
387d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
388d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
389d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
390d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
391d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkebool VirtualMemory::IsReserved() {
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return address_ != NULL;
3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid VirtualMemory::Reset() {
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  address_ = NULL;
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  size_ = 0;
399d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
400d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
401d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return CommitRegion(address, size, is_executable);
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Uncommit(void* address, size_t size) {
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return UncommitRegion(address, size);
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::Guard(void* address) {
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  OS::Guard(address, OS::CommitPageSize());
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return true;
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid* VirtualMemory::ReserveRegion(size_t size) {
4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  void* result = mmap(OS::GetRandomMmapAddr(),
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      size,
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      PROT_NONE,
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE,
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kMmapFd,
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                      kMmapFdOffset);
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (result == MAP_FAILED) return NULL;
4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return result;
4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (MAP_FAILED == mmap(base,
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         size,
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         prot,
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         kMmapFd,
4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                         kMmapFdOffset)) {
440d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return false;
441d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
442d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  UpdateAllocatedSpaceLimits(base, size);
444d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return true;
445d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
446d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
447d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::UncommitRegion(void* base, size_t size) {
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return mmap(base,
4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              size,
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              PROT_NONE,
4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED,
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              kMmapFd,
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              kMmapFdOffset) != MAP_FAILED;
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool VirtualMemory::ReleaseRegion(void* base, size_t size) {
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return munmap(base, size) == 0;
460d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
461d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
462d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
4638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochclass Thread::PlatformData : public Malloced {
464d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public:
4658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  PlatformData() : thread_(kNoThread) {  }
466d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
467d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  pthread_t thread_;  // Thread handle for pthread.
468d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke};
469d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
47085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochThread::Thread(const Options& options)
47285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch    : data_(new PlatformData()),
4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      stack_size_(options.stack_size()) {
4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  set_name(options.name());
475d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
476d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
477d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
478d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeThread::~Thread() {
4798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  delete data_;
480d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
481d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
482d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
483d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic void* ThreadEntry(void* arg) {
484d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Thread* thread = reinterpret_cast<Thread*>(arg);
485d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // This is also initialized by the first argument to pthread_create() but we
486d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // don't know which thread will run first (the original thread or the new
487d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // one) so we initialize it here too.
4888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  thread->data()->thread_ = pthread_self();
4898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(thread->data()->thread_ != kNoThread);
490d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  thread->Run();
491d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return NULL;
492d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
493d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
494d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
4959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid Thread::set_name(const char* name) {
4969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  strncpy(name_, name, sizeof(name_));
4979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block  name_[sizeof(name_) - 1] = '\0';
4989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block}
4999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
5009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block
501d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Thread::Start() {
50244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  pthread_attr_t* attr_ptr = NULL;
50344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  pthread_attr_t attr;
50444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (stack_size_ > 0) {
50544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    pthread_attr_init(&attr);
50644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
50744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    attr_ptr = &attr;
50844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
5098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  pthread_create(&data_->thread_, NULL, ThreadEntry, this);
5108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(data_->thread_ != kNoThread);
511d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
512d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
513d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
514d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Thread::Join() {
5158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  pthread_join(data_->thread_, NULL);
516d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
517d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
518d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
519d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeThread::LocalStorageKey Thread::CreateThreadLocalKey() {
520d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  pthread_key_t key;
521d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int result = pthread_key_create(&key, NULL);
522d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  USE(result);
523d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT(result == 0);
524d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return static_cast<LocalStorageKey>(key);
525d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
526d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
527d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
528d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Thread::DeleteThreadLocalKey(LocalStorageKey key) {
529d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
530d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int result = pthread_key_delete(pthread_key);
531d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  USE(result);
532d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT(result == 0);
533d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
534d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
535d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
536d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid* Thread::GetThreadLocal(LocalStorageKey key) {
537d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
538d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return pthread_getspecific(pthread_key);
539d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
540d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
541d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
542d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Thread::SetThreadLocal(LocalStorageKey key, void* value) {
543d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  pthread_key_t pthread_key = static_cast<pthread_key_t>(key);
544d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  pthread_setspecific(pthread_key, value);
545d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
546d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
547d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
548d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Thread::YieldCPU() {
549d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  sched_yield();
550d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
551d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
552d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
553d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass SolarisMutex : public Mutex {
554d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public:
555d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  SolarisMutex() {
556d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    pthread_mutexattr_t attr;
557d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    pthread_mutexattr_init(&attr);
558d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
559d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    pthread_mutex_init(&mutex_, &attr);
560d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
561d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
562d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ~SolarisMutex() { pthread_mutex_destroy(&mutex_); }
563d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
564d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int Lock() { return pthread_mutex_lock(&mutex_); }
565d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
566d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int Unlock() { return pthread_mutex_unlock(&mutex_); }
567d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
568b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  virtual bool TryLock() {
569b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    int result = pthread_mutex_trylock(&mutex_);
570b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    // Return false if the lock is busy and locking failed.
571b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    if (result == EBUSY) {
572b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      return false;
573b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    }
574b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    ASSERT(result == 0);  // Verify no other errors.
575b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    return true;
576b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
577b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
578d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private:
579d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  pthread_mutex_t mutex_;
580d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke};
581d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
582d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
583d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeMutex* OS::CreateMutex() {
584d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return new SolarisMutex();
585d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
586d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
587d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
588d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass SolarisSemaphore : public Semaphore {
589d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public:
590d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  explicit SolarisSemaphore(int count) {  sem_init(&sem_, 0, count); }
591d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual ~SolarisSemaphore() { sem_destroy(&sem_); }
592d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
593d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual void Wait();
594d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual bool Wait(int timeout);
595d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  virtual void Signal() { sem_post(&sem_); }
596d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke private:
597d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  sem_t sem_;
598d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke};
599d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
600d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
601d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid SolarisSemaphore::Wait() {
602d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  while (true) {
603d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    int result = sem_wait(&sem_);
604d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (result == 0) return;  // Successfully got semaphore.
605d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CHECK(result == -1 && errno == EINTR);  // Signal caused spurious wakeup.
606d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
607d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
608d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
609d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
610d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#ifndef TIMEVAL_TO_TIMESPEC
611d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#define TIMEVAL_TO_TIMESPEC(tv, ts) do {                            \
612d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    (ts)->tv_sec = (tv)->tv_sec;                                    \
613d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    (ts)->tv_nsec = (tv)->tv_usec * 1000;                           \
614d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} while (false)
615d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#endif
616d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
617d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
618d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#ifndef timeradd
619d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#define timeradd(a, b, result) \
620d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  do { \
621d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    (result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
622d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    (result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
623d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if ((result)->tv_usec >= 1000000) { \
624d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      ++(result)->tv_sec; \
625d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      (result)->tv_usec -= 1000000; \
626d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    } \
627d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } while (0)
628d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#endif
629d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
630d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
631d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkebool SolarisSemaphore::Wait(int timeout) {
632d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  const long kOneSecondMicros = 1000000;  // NOLINT
633d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
634d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Split timeout into second and nanosecond parts.
635d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  struct timeval delta;
636d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  delta.tv_usec = timeout % kOneSecondMicros;
637d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  delta.tv_sec = timeout / kOneSecondMicros;
638d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
639d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  struct timeval current_time;
640d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Get the current time.
641d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (gettimeofday(&current_time, NULL) == -1) {
642d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    return false;
643d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
644d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
645d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Calculate time for end of timeout.
646d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  struct timeval end_time;
647d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  timeradd(&current_time, &delta, &end_time);
648d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
649d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  struct timespec ts;
650d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  TIMEVAL_TO_TIMESPEC(&end_time, &ts);
651d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Wait for semaphore signalled or timeout.
652d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  while (true) {
653d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    int result = sem_timedwait(&sem_, &ts);
654d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (result == 0) return true;  // Successfully got semaphore.
655d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (result == -1 && errno == ETIMEDOUT) return false;  // Timeout.
656d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CHECK(result == -1 && errno == EINTR);  // Signal caused spurious wakeup.
657d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
658d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
659d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
660d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
661d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeSemaphore* OS::CreateSemaphore(int count) {
662d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return new SolarisSemaphore(count);
663d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
664d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
665d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
66644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstatic pthread_t GetThreadID() {
66744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return pthread_self();
66844f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
66944f0eee88ff00398ff7f715fab053374d808c90dSteve Block
670d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
671d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  USE(info);
672d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  if (signal != SIGPROF) return;
6733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Isolate* isolate = Isolate::UncheckedCurrent();
6743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
6753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // We require a fully initialized and entered isolate.
6763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return;
6773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
6783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (v8::Locker::IsActive() &&
6793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      !isolate->thread_manager()->IsLockedByCurrentThread()) {
6803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return;
6813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
6823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
6833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Sampler* sampler = isolate->logger()->sampler();
6843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (sampler == NULL || !sampler->IsActive()) return;
685b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
686b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  TickSample sample_obj;
6873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
688b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (sample == NULL) sample = &sample_obj;
689b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
690b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Extracting the sample from the context is extremely machine dependent.
691b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
692b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  mcontext_t& mcontext = ucontext->uc_mcontext;
6933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  sample->state = isolate->current_vm_state();
694b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
69544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]);
69644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
69744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
69844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
6993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  sampler->SampleStack(sample);
7003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  sampler->Tick(sample);
701d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
702d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
703d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkeclass Sampler::PlatformData : public Malloced {
704d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke public:
7053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  PlatformData() : vm_tid_(GetThreadID()) {}
7063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  pthread_t vm_tid() const { return vm_tid_; }
7083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private:
7103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  pthread_t vm_tid_;
7113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch};
7123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochclass SignalSender : public Thread {
7153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public:
71644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  enum SleepInterval {
7173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    HALF_INTERVAL,
7183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    FULL_INTERVAL
71944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  };
72044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static const int kSignalSenderStackSize = 64 * KB;
7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  explicit SignalSender(int interval)
7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)),
7253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        interval_(interval) {}
7263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static void InstallSignalHandler() {
7283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    struct sigaction sa;
7293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    sa.sa_sigaction = ProfilerSignalHandler;
7303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    sigemptyset(&sa.sa_mask);
7313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    sa.sa_flags = SA_RESTART | SA_SIGINFO;
7323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    signal_handler_installed_ =
7333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0);
7343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
7353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static void RestoreSignalHandler() {
7373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (signal_handler_installed_) {
7383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      sigaction(SIGPROF, &old_signal_handler_, 0);
7393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      signal_handler_installed_ = false;
7403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
7413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
7423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static void AddActiveSampler(Sampler* sampler) {
7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ScopedLock lock(mutex_.Pointer());
7453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    SamplerRegistry::AddActiveSampler(sampler);
7463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (instance_ == NULL) {
7473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // Start a thread that will send SIGPROF signal to VM threads,
7483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // when CPU profiling will be enabled.
7493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      instance_ = new SignalSender(sampler->interval());
7503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      instance_->Start();
7513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    } else {
7523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(instance_->interval_ == sampler->interval());
7533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
7543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
7553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static void RemoveActiveSampler(Sampler* sampler) {
7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ScopedLock lock(mutex_.Pointer());
7583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    SamplerRegistry::RemoveActiveSampler(sampler);
7593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
7603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
7613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      delete instance_;
7623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      instance_ = NULL;
7633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      RestoreSignalHandler();
7643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
76544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
76644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
7673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Implement Thread::Run().
7683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  virtual void Run() {
7693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    SamplerRegistry::State state;
7703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    while ((state = SamplerRegistry::GetState()) !=
7713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch           SamplerRegistry::HAS_NO_SAMPLERS) {
7723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bool cpu_profiling_enabled =
7733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS);
7743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled();
7753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (cpu_profiling_enabled && !signal_handler_installed_) {
7763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        InstallSignalHandler();
7773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      } else if (!cpu_profiling_enabled && signal_handler_installed_) {
7783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        RestoreSignalHandler();
7793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
7803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // When CPU profiling is enabled both JavaScript and C++ code is
7823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      // profiled. We must not suspend.
7833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (!cpu_profiling_enabled) {
7843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (rate_limiter_.SuspendIfNecessary()) continue;
7853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
7863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (cpu_profiling_enabled && runtime_profiler_enabled) {
7873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
7883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          return;
7893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
79044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Sleep(HALF_INTERVAL);
7913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
7923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          return;
7933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Sleep(HALF_INTERVAL);
79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      } else {
7963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (cpu_profiling_enabled) {
7973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile,
7983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      this)) {
7993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            return;
8003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          }
8013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
8023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (runtime_profiler_enabled) {
8033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile,
8043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                                                      NULL)) {
8053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch            return;
8063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          }
8073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        }
80844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Sleep(FULL_INTERVAL);
80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
81144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static void DoCpuProfile(Sampler* sampler, void* raw_sender) {
8143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (!sampler->IsProfiling()) return;
8153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender);
8163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    sender->SendProfilingSignal(sampler->platform_data()->vm_tid());
8173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
8183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static void DoRuntimeProfile(Sampler* sampler, void* ignored) {
8203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    if (!sampler->isolate()->IsInitialized()) return;
8213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    sampler->isolate()->runtime_profiler()->NotifyTick();
8223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
8233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  void SendProfilingSignal(pthread_t tid) {
82544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (!signal_handler_installed_) return;
8263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    pthread_kill(tid, SIGPROF);
827d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
828d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
82944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  void Sleep(SleepInterval full_or_half) {
83044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Convert ms to us and subtract 100 us to compensate delays
83144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // occuring during signal delivery.
8323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    useconds_t interval = interval_ * 1000 - 100;
83344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (full_or_half == HALF_INTERVAL) interval /= 2;
83444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int result = usleep(interval);
83544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
83644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (result != 0 && errno != EINTR) {
83744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      fprintf(stderr,
83844f0eee88ff00398ff7f715fab053374d808c90dSteve Block              "SignalSender usleep error; interval = %u, errno = %d\n",
83944f0eee88ff00398ff7f715fab053374d808c90dSteve Block              interval,
84044f0eee88ff00398ff7f715fab053374d808c90dSteve Block              errno);
84144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      ASSERT(result == 0 || errno == EINTR);
84244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
84344f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
84444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    USE(result);
84544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
84644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int interval_;
84844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  RuntimeProfilerRateLimiter rate_limiter_;
849d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
8503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Protects the process wide state below.
8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static LazyMutex mutex_;
8523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static SignalSender* instance_;
8533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static bool signal_handler_installed_;
8543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static struct sigaction old_signal_handler_;
855d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch private:
8573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(SignalSender);
8583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch};
8593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochLazyMutex SignalSender::mutex_ = LAZY_MUTEX_INITIALIZER;
8613fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochSignalSender* SignalSender::instance_ = NULL;
8623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochstruct sigaction SignalSender::old_signal_handler_;
8633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochbool SignalSender::signal_handler_installed_ = false;
86444f0eee88ff00398ff7f715fab053374d808c90dSteve Block
86544f0eee88ff00398ff7f715fab053374d808c90dSteve Block
86644f0eee88ff00398ff7f715fab053374d808c90dSteve BlockSampler::Sampler(Isolate* isolate, int interval)
86744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : isolate_(isolate),
86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      interval_(interval),
869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      profiling_(false),
8708a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      active_(false),
8718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      samples_taken_(0) {
8723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  data_ = new PlatformData;
873d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
874d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
875d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
876d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeSampler::~Sampler() {
8773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(!IsActive());
878d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  delete data_;
879d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
880d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
881d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
882d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Sampler::Start() {
88344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!IsActive());
88444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SetActive(true);
8853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SignalSender::AddActiveSampler(this);
886d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
887d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
888d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
889d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkevoid Sampler::Stop() {
8903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(IsActive());
8913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  SignalSender::RemoveActiveSampler(this);
89244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  SetActive(false);
893d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
894d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
895d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke} }  // namespace v8::internal
896