1e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org// Copyright 2013 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.
4e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
55de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/condition-variable.h"
6e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
7e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org#include <errno.h>
8e31286d471eb2e656a1809383fa16b76053dd673machenbach@chromium.org#include <time.h>
9e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
105de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org#include "src/base/platform/time.h"
11e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
12e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgnamespace v8 {
135de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.orgnamespace base {
14e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
15e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#if V8_OS_POSIX
16e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
17e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgConditionVariable::ConditionVariable() {
18e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // TODO(bmeurer): The test for V8_LIBRT_NOT_AVAILABLE is a temporary
19e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // hack to support cross-compiling Chrome for Android in AOSP. Remove
20e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // this once AOSP is fixed.
213d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org#if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || \
223d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org     (V8_OS_LINUX && V8_LIBC_GLIBC)) && !V8_LIBRT_NOT_AVAILABLE
23e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // On Free/Net/OpenBSD and Linux with glibc we can change the time
24e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // source for pthread_cond_timedwait() to use the monotonic clock.
25e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  pthread_condattr_t attr;
26e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  int result = pthread_condattr_init(&attr);
27e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, result);
28e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  result = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
29e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, result);
30e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  result = pthread_cond_init(&native_handle_, &attr);
31e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, result);
32e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  result = pthread_condattr_destroy(&attr);
33e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#else
34e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  int result = pthread_cond_init(&native_handle_, NULL);
35e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#endif
36e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, result);
37e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  USE(result);
38e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
39e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
40e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
41e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgConditionVariable::~ConditionVariable() {
42e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  int result = pthread_cond_destroy(&native_handle_);
43e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, result);
44e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  USE(result);
45e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
46e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
47e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
48e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgvoid ConditionVariable::NotifyOne() {
49e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  int result = pthread_cond_signal(&native_handle_);
50e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, result);
51e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  USE(result);
52e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
53e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
54e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
55e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgvoid ConditionVariable::NotifyAll() {
56e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  int result = pthread_cond_broadcast(&native_handle_);
57e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, result);
58e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  USE(result);
59e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
60e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
61e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
62e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgvoid ConditionVariable::Wait(Mutex* mutex) {
63e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  mutex->AssertHeldAndUnmark();
64e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  int result = pthread_cond_wait(&native_handle_, &mutex->native_handle());
65e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, result);
66e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  USE(result);
67e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  mutex->AssertUnheldAndMark();
68e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
69e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
70e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
71e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgbool ConditionVariable::WaitFor(Mutex* mutex, const TimeDelta& rel_time) {
72e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  struct timespec ts;
73e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  int result;
74e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  mutex->AssertHeldAndUnmark();
75e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#if V8_OS_MACOSX
76e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Mac OS X provides pthread_cond_timedwait_relative_np(), which does
77e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // not depend on the real time clock, which is what you really WANT here!
78e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  ts = rel_time.ToTimespec();
79e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_GE(ts.tv_sec, 0);
80e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_GE(ts.tv_nsec, 0);
81e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  result = pthread_cond_timedwait_relative_np(
82e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      &native_handle_, &mutex->native_handle(), &ts);
83e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#else
84e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // TODO(bmeurer): The test for V8_LIBRT_NOT_AVAILABLE is a temporary
85e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // hack to support cross-compiling Chrome for Android in AOSP. Remove
86e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // this once AOSP is fixed.
873d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org#if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || \
883d00d0a753cf5e5091f883517e6612ece769f999jkummerow@chromium.org     (V8_OS_LINUX && V8_LIBC_GLIBC)) && !V8_LIBRT_NOT_AVAILABLE
89e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // On Free/Net/OpenBSD and Linux with glibc we can change the time
90e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // source for pthread_cond_timedwait() to use the monotonic clock.
91e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  result = clock_gettime(CLOCK_MONOTONIC, &ts);
92e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, result);
93e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  Time now = Time::FromTimespec(ts);
94e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#else
95e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // The timeout argument to pthread_cond_timedwait() is in absolute time.
96e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  Time now = Time::NowFromSystemTime();
97e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#endif
98e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  Time end_time = now + rel_time;
99e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_GE(end_time, now);
100e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  ts = end_time.ToTimespec();
101e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  result = pthread_cond_timedwait(
102e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      &native_handle_, &mutex->native_handle(), &ts);
103e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#endif  // V8_OS_MACOSX
104e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  mutex->AssertUnheldAndMark();
105e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  if (result == ETIMEDOUT) {
106e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    return false;
107e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
108e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK_EQ(0, result);
109e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  return true;
110e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
111e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
112e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#elif V8_OS_WIN
113e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
114e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgstruct ConditionVariable::Event {
115e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  Event() : handle_(::CreateEventA(NULL, true, false, NULL)) {
116e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(handle_ != NULL);
117e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
118e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
119e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  ~Event() {
120e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    BOOL ok = ::CloseHandle(handle_);
121e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(ok);
122e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    USE(ok);
123e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
124e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
125e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  bool WaitFor(DWORD timeout_ms) {
126e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    DWORD result = ::WaitForSingleObject(handle_, timeout_ms);
127e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    if (result == WAIT_OBJECT_0) {
128e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      return true;
129e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    }
130e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(result == WAIT_TIMEOUT);
131e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    return false;
132e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
133e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
134e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  HANDLE handle_;
135e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  Event* next_;
136e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  HANDLE thread_;
137e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  volatile bool notified_;
138e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org};
139e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
140e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
141e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgConditionVariable::NativeHandle::~NativeHandle() {
142e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(waitlist_ == NULL);
143e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
144e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  while (freelist_ != NULL) {
145e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    Event* event = freelist_;
146e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    freelist_ = event->next_;
147e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    delete event;
148e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
149e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
150e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
151e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
152e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgConditionVariable::Event* ConditionVariable::NativeHandle::Pre() {
153e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  LockGuard<Mutex> lock_guard(&mutex_);
154e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
155e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Grab an event from the free list or create a new one.
156e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  Event* event = freelist_;
157e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  if (event != NULL) {
158e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    freelist_ = event->next_;
159e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  } else {
160e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    event = new Event;
161e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
162e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  event->thread_ = GetCurrentThread();
163e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  event->notified_ = false;
164e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
165e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#ifdef DEBUG
166e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // The event must not be on the wait list.
167e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  for (Event* we = waitlist_; we != NULL; we = we->next_) {
168e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_NE(event, we);
169e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
170e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#endif
171e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
172e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Prepend the event to the wait list.
173e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  event->next_ = waitlist_;
174e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  waitlist_ = event;
175e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
176e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  return event;
177e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
178e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
179e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
180e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgvoid ConditionVariable::NativeHandle::Post(Event* event, bool result) {
181e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  LockGuard<Mutex> lock_guard(&mutex_);
182e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
183e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Remove the event from the wait list.
184e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  for (Event** wep = &waitlist_;; wep = &(*wep)->next_) {
185e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_NE(NULL, *wep);
186e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    if (*wep == event) {
187e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      *wep = event->next_;
188e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      break;
189e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    }
190e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
191e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
192e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#ifdef DEBUG
193e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // The event must not be on the free list.
194e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  for (Event* fe = freelist_; fe != NULL; fe = fe->next_) {
195e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_NE(event, fe);
196e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
197e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#endif
198e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
199e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Reset the event.
200e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  BOOL ok = ::ResetEvent(event->handle_);
201e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(ok);
202e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  USE(ok);
203e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
204e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Insert the event into the free list.
205e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  event->next_ = freelist_;
206e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  freelist_ = event;
207e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
208e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Forward signals delivered after the timeout to the next waiting event.
209e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  if (!result && event->notified_ && waitlist_ != NULL) {
210e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    ok = ::SetEvent(waitlist_->handle_);
211e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(ok);
212e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    USE(ok);
213e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    waitlist_->notified_ = true;
214e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
215e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
216e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
217e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
218e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgConditionVariable::ConditionVariable() {}
219e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
220e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
221e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgConditionVariable::~ConditionVariable() {}
222e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
223e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
224e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgvoid ConditionVariable::NotifyOne() {
225e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Notify the thread with the highest priority in the waitlist
226e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // that was not already signalled.
227e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  LockGuard<Mutex> lock_guard(native_handle_.mutex());
228e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  Event* highest_event = NULL;
229e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  int highest_priority = std::numeric_limits<int>::min();
230e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  for (Event* event = native_handle().waitlist();
231e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org       event != NULL;
232e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org       event = event->next_) {
233e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    if (event->notified_) {
234e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      continue;
235e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    }
236e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    int priority = GetThreadPriority(event->thread_);
237e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_NE(THREAD_PRIORITY_ERROR_RETURN, priority);
238e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    if (priority >= highest_priority) {
239e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      highest_priority = priority;
240e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      highest_event = event;
241e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    }
242e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
243e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  if (highest_event != NULL) {
244e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(!highest_event->notified_);
245e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    ::SetEvent(highest_event->handle_);
246e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    highest_event->notified_ = true;
247e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
248e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
249e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
250e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
251e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgvoid ConditionVariable::NotifyAll() {
252e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Notify all threads on the waitlist.
253e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  LockGuard<Mutex> lock_guard(native_handle_.mutex());
254e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  for (Event* event = native_handle().waitlist();
255e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org       event != NULL;
256e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org       event = event->next_) {
257e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    if (!event->notified_) {
258e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      ::SetEvent(event->handle_);
259e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      event->notified_ = true;
260e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    }
261e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
262e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
263e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
264e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
265e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgvoid ConditionVariable::Wait(Mutex* mutex) {
266e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Create and setup the wait event.
267e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  Event* event = native_handle_.Pre();
268e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
269e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Release the user mutex.
270e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  mutex->Unlock();
271e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
272e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Wait on the wait event.
273e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  while (!event->WaitFor(INFINITE))
274e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    ;
275e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
276e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Reaquire the user mutex.
277e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  mutex->Lock();
278e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
279e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Release the wait event (we must have been notified).
280e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(event->notified_);
281e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  native_handle_.Post(event, true);
282e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
283e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
284e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
285e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.orgbool ConditionVariable::WaitFor(Mutex* mutex, const TimeDelta& rel_time) {
286e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Create and setup the wait event.
287e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  Event* event = native_handle_.Pre();
288e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
289e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Release the user mutex.
290e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  mutex->Unlock();
291e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
292e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Wait on the wait event.
293e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  TimeTicks now = TimeTicks::Now();
294e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  TimeTicks end = now + rel_time;
295e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  bool result = false;
296e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  while (true) {
297e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    int64_t msec = (end - now).InMilliseconds();
298e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    if (msec >= static_cast<int64_t>(INFINITE)) {
299e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      result = event->WaitFor(INFINITE - 1);
300e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      if (result) {
301e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org        break;
302e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      }
303e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      now = TimeTicks::Now();
304e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    } else {
305e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      result = event->WaitFor((msec < 0) ? 0 : static_cast<DWORD>(msec));
306e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org      break;
307e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org    }
308e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  }
309e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
310e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Reaquire the user mutex.
311e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  mutex->Lock();
312e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
313e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  // Release the wait event.
314e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(!result || event->notified_);
315e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  native_handle_.Post(event, result);
316e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
317e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org  return result;
318e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org}
319e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
320e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org#endif  // V8_OS_POSIX
321e900018c7a2a695fde788911564da37535c7e736mstarzinger@chromium.org
3225de0074a922429f5e0ec2cf140c2d2989bf88140yangguo@chromium.org} }  // namespace v8::base
323