LCOV - code coverage report
Current view: top level - src/base/platform - condition-variable.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 27 27 100.0 %
Date: 2019-04-17 Functions: 6 6 100.0 %

          Line data    Source code
       1             : // Copyright 2013 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/base/platform/condition-variable.h"
       6             : 
       7             : #include <errno.h>
       8             : #include <time.h>
       9             : 
      10             : #include "src/base/platform/time.h"
      11             : 
      12             : namespace v8 {
      13             : namespace base {
      14             : 
      15             : #if V8_OS_POSIX
      16             : 
      17      589551 : ConditionVariable::ConditionVariable() {
      18             : #if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || \
      19             :      (V8_OS_LINUX && V8_LIBC_GLIBC))
      20             :   // On Free/Net/OpenBSD and Linux with glibc we can change the time
      21             :   // source for pthread_cond_timedwait() to use the monotonic clock.
      22             :   pthread_condattr_t attr;
      23      589551 :   int result = pthread_condattr_init(&attr);
      24             :   DCHECK_EQ(0, result);
      25      589551 :   result = pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
      26             :   DCHECK_EQ(0, result);
      27      589551 :   result = pthread_cond_init(&native_handle_, &attr);
      28             :   DCHECK_EQ(0, result);
      29      589550 :   result = pthread_condattr_destroy(&attr);
      30             : #else
      31             :   int result = pthread_cond_init(&native_handle_, nullptr);
      32             : #endif
      33             :   DCHECK_EQ(0, result);
      34             :   USE(result);
      35      589551 : }
      36             : 
      37             : 
      38     1167841 : ConditionVariable::~ConditionVariable() {
      39             : #if defined(V8_OS_MACOSX)
      40             :   // This hack is necessary to avoid a fatal pthreads subsystem bug in the
      41             :   // Darwin kernel. http://crbug.com/517681.
      42             :   {
      43             :     Mutex lock;
      44             :     MutexGuard l(&lock);
      45             :     struct timespec ts;
      46             :     ts.tv_sec = 0;
      47             :     ts.tv_nsec = 1;
      48             :     pthread_cond_timedwait_relative_np(&native_handle_, &lock.native_handle(),
      49             :                                        &ts);
      50             :   }
      51             : #endif
      52      583917 :   int result = pthread_cond_destroy(&native_handle_);
      53             :   DCHECK_EQ(0, result);
      54             :   USE(result);
      55      583924 : }
      56             : 
      57             : 
      58     4617251 : void ConditionVariable::NotifyOne() {
      59     4617251 :   int result = pthread_cond_signal(&native_handle_);
      60             :   DCHECK_EQ(0, result);
      61             :   USE(result);
      62     4619138 : }
      63             : 
      64             : 
      65     1104715 : void ConditionVariable::NotifyAll() {
      66     1104715 :   int result = pthread_cond_broadcast(&native_handle_);
      67             :   DCHECK_EQ(0, result);
      68             :   USE(result);
      69     1104715 : }
      70             : 
      71             : 
      72     1873543 : void ConditionVariable::Wait(Mutex* mutex) {
      73             :   mutex->AssertHeldAndUnmark();
      74     1873543 :   int result = pthread_cond_wait(&native_handle_, &mutex->native_handle());
      75             :   DCHECK_EQ(0, result);
      76             :   USE(result);
      77             :   mutex->AssertUnheldAndMark();
      78     1852083 : }
      79             : 
      80             : 
      81       84351 : bool ConditionVariable::WaitFor(Mutex* mutex, const TimeDelta& rel_time) {
      82             :   struct timespec ts;
      83             :   int result;
      84             :   mutex->AssertHeldAndUnmark();
      85             : #if V8_OS_MACOSX
      86             :   // Mac OS X provides pthread_cond_timedwait_relative_np(), which does
      87             :   // not depend on the real time clock, which is what you really WANT here!
      88             :   ts = rel_time.ToTimespec();
      89             :   DCHECK_GE(ts.tv_sec, 0);
      90             :   DCHECK_GE(ts.tv_nsec, 0);
      91             :   result = pthread_cond_timedwait_relative_np(
      92             :       &native_handle_, &mutex->native_handle(), &ts);
      93             : #else
      94             : #if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || \
      95             :      (V8_OS_LINUX && V8_LIBC_GLIBC))
      96             :   // On Free/Net/OpenBSD and Linux with glibc we can change the time
      97             :   // source for pthread_cond_timedwait() to use the monotonic clock.
      98       84351 :   result = clock_gettime(CLOCK_MONOTONIC, &ts);
      99             :   DCHECK_EQ(0, result);
     100       84351 :   Time now = Time::FromTimespec(ts);
     101             : #else
     102             :   // The timeout argument to pthread_cond_timedwait() is in absolute time.
     103             :   Time now = Time::NowFromSystemTime();
     104             : #endif
     105       84351 :   Time end_time = now + rel_time;
     106             :   DCHECK_GE(end_time, now);
     107       84351 :   ts = end_time.ToTimespec();
     108       84351 :   result = pthread_cond_timedwait(
     109       84351 :       &native_handle_, &mutex->native_handle(), &ts);
     110             : #endif  // V8_OS_MACOSX
     111             :   mutex->AssertUnheldAndMark();
     112       84351 :   if (result == ETIMEDOUT) {
     113             :     return false;
     114             :   }
     115             :   DCHECK_EQ(0, result);
     116       13360 :   return true;
     117             : }
     118             : 
     119             : #elif V8_OS_WIN
     120             : 
     121             : ConditionVariable::ConditionVariable() {
     122             :   InitializeConditionVariable(&native_handle_);
     123             : }
     124             : 
     125             : 
     126             : ConditionVariable::~ConditionVariable() {}
     127             : 
     128             : void ConditionVariable::NotifyOne() { WakeConditionVariable(&native_handle_); }
     129             : 
     130             : void ConditionVariable::NotifyAll() {
     131             :   WakeAllConditionVariable(&native_handle_);
     132             : }
     133             : 
     134             : 
     135             : void ConditionVariable::Wait(Mutex* mutex) {
     136             :   mutex->AssertHeldAndUnmark();
     137             :   SleepConditionVariableSRW(&native_handle_, &mutex->native_handle(), INFINITE,
     138             :                             0);
     139             :   mutex->AssertUnheldAndMark();
     140             : }
     141             : 
     142             : 
     143             : bool ConditionVariable::WaitFor(Mutex* mutex, const TimeDelta& rel_time) {
     144             :   int64_t msec = rel_time.InMilliseconds();
     145             :   mutex->AssertHeldAndUnmark();
     146             :   BOOL result = SleepConditionVariableSRW(
     147             :       &native_handle_, &mutex->native_handle(), static_cast<DWORD>(msec), 0);
     148             : #ifdef DEBUG
     149             :   if (!result) {
     150             :     // On failure, we only expect the CV to timeout. Any other error value means
     151             :     // that we've unexpectedly woken up.
     152             :     // Note that WAIT_TIMEOUT != ERROR_TIMEOUT. WAIT_TIMEOUT is used with the
     153             :     // WaitFor* family of functions as a direct return value. ERROR_TIMEOUT is
     154             :     // used with GetLastError().
     155             :     DCHECK_EQ(static_cast<DWORD>(ERROR_TIMEOUT), GetLastError());
     156             :   }
     157             : #endif
     158             :   mutex->AssertUnheldAndMark();
     159             :   return result != 0;
     160             : }
     161             : 
     162             : #endif  // V8_OS_POSIX
     163             : 
     164             : }  // namespace base
     165             : }  // namespace v8

Generated by: LCOV version 1.10