LCOV - code coverage report
Current view: top level - src/base/platform - semaphore.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 19 19 100.0 %
Date: 2017-04-26 Functions: 5 5 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/semaphore.h"
       6             : 
       7             : #if V8_OS_MACOSX
       8             : #include <mach/mach_init.h>
       9             : #include <mach/task.h>
      10             : #endif
      11             : 
      12             : #include <errno.h>
      13             : 
      14             : #include "src/base/logging.h"
      15             : #include "src/base/platform/elapsed-timer.h"
      16             : #include "src/base/platform/time.h"
      17             : 
      18             : namespace v8 {
      19             : namespace base {
      20             : 
      21             : #if V8_OS_MACOSX
      22             : 
      23             : Semaphore::Semaphore(int count) {
      24             :   kern_return_t result = semaphore_create(
      25             :       mach_task_self(), &native_handle_, SYNC_POLICY_FIFO, count);
      26             :   DCHECK_EQ(KERN_SUCCESS, result);
      27             :   USE(result);
      28             : }
      29             : 
      30             : 
      31             : Semaphore::~Semaphore() {
      32             :   kern_return_t result = semaphore_destroy(mach_task_self(), native_handle_);
      33             :   DCHECK_EQ(KERN_SUCCESS, result);
      34             :   USE(result);
      35             : }
      36             : 
      37             : void Semaphore::Signal() {
      38             :   kern_return_t result = semaphore_signal(native_handle_);
      39             :   DCHECK_EQ(KERN_SUCCESS, result);
      40             :   USE(result);
      41             : }
      42             : 
      43             : 
      44             : void Semaphore::Wait() {
      45             :   while (true) {
      46             :     kern_return_t result = semaphore_wait(native_handle_);
      47             :     if (result == KERN_SUCCESS) return;  // Semaphore was signalled.
      48             :     DCHECK_EQ(KERN_ABORTED, result);
      49             :   }
      50             : }
      51             : 
      52             : 
      53             : bool Semaphore::WaitFor(const TimeDelta& rel_time) {
      54             :   TimeTicks now = TimeTicks::Now();
      55             :   TimeTicks end = now + rel_time;
      56             :   while (true) {
      57             :     mach_timespec_t ts;
      58             :     if (now >= end) {
      59             :       // Return immediately if semaphore was not signalled.
      60             :       ts.tv_sec = 0;
      61             :       ts.tv_nsec = 0;
      62             :     } else {
      63             :       ts = (end - now).ToMachTimespec();
      64             :     }
      65             :     kern_return_t result = semaphore_timedwait(native_handle_, ts);
      66             :     if (result == KERN_SUCCESS) return true;  // Semaphore was signalled.
      67             :     if (result == KERN_OPERATION_TIMED_OUT) return false;  // Timeout.
      68             :     DCHECK_EQ(KERN_ABORTED, result);
      69             :     now = TimeTicks::Now();
      70             :   }
      71             : }
      72             : 
      73             : #elif V8_OS_POSIX
      74             : 
      75      693144 : Semaphore::Semaphore(int count) {
      76             :   DCHECK(count >= 0);
      77      693144 :   int result = sem_init(&native_handle_, 0, count);
      78             :   DCHECK_EQ(0, result);
      79             :   USE(result);
      80      693146 : }
      81             : 
      82             : 
      83      546738 : Semaphore::~Semaphore() {
      84      546738 :   int result = sem_destroy(&native_handle_);
      85             :   DCHECK_EQ(0, result);
      86             :   USE(result);
      87      546738 : }
      88             : 
      89     2095835 : void Semaphore::Signal() {
      90     2095835 :   int result = sem_post(&native_handle_);
      91             :   // This check may fail with <libc-2.21, which we use on the try bots, if the
      92             :   // semaphore is destroyed while sem_post is still executed. A work around is
      93             :   // to extend the lifetime of the semaphore.
      94     2096273 :   CHECK_EQ(0, result);
      95     2096273 : }
      96             : 
      97             : 
      98     1980377 : void Semaphore::Wait() {
      99             :   while (true) {
     100     1980384 :     int result = sem_wait(&native_handle_);
     101     1975064 :     if (result == 0) return;  // Semaphore was signalled.
     102             :     // Signal caused spurious wakeup.
     103             :     DCHECK_EQ(-1, result);
     104             :     DCHECK_EQ(EINTR, errno);
     105             :   }
     106             : }
     107             : 
     108             : 
     109         213 : bool Semaphore::WaitFor(const TimeDelta& rel_time) {
     110             :   // Compute the time for end of timeout.
     111         426 :   const Time time = Time::NowFromSystemTime() + rel_time;
     112         213 :   const struct timespec ts = time.ToTimespec();
     113             : 
     114             :   // Wait for semaphore signalled or timeout.
     115             :   while (true) {
     116         213 :     int result = sem_timedwait(&native_handle_, &ts);
     117         213 :     if (result == 0) return true;  // Semaphore was signalled.
     118             : #if V8_LIBC_GLIBC && !V8_GLIBC_PREREQ(2, 4)
     119             :     if (result > 0) {
     120             :       // sem_timedwait in glibc prior to 2.3.4 returns the errno instead of -1.
     121             :       errno = result;
     122             :       result = -1;
     123             :     }
     124             : #endif
     125         204 :     if (result == -1 && errno == ETIMEDOUT) {
     126             :       // Timed out while waiting for semaphore.
     127             :       return false;
     128             :     }
     129             :     // Signal caused spurious wakeup.
     130             :     DCHECK_EQ(-1, result);
     131             :     DCHECK_EQ(EINTR, errno);
     132             :   }
     133             : }
     134             : 
     135             : #elif V8_OS_WIN
     136             : 
     137             : Semaphore::Semaphore(int count) {
     138             :   DCHECK(count >= 0);
     139             :   native_handle_ = ::CreateSemaphoreA(NULL, count, 0x7fffffff, NULL);
     140             :   DCHECK(native_handle_ != NULL);
     141             : }
     142             : 
     143             : 
     144             : Semaphore::~Semaphore() {
     145             :   BOOL result = CloseHandle(native_handle_);
     146             :   DCHECK(result);
     147             :   USE(result);
     148             : }
     149             : 
     150             : void Semaphore::Signal() {
     151             :   LONG dummy;
     152             :   BOOL result = ReleaseSemaphore(native_handle_, 1, &dummy);
     153             :   DCHECK(result);
     154             :   USE(result);
     155             : }
     156             : 
     157             : 
     158             : void Semaphore::Wait() {
     159             :   DWORD result = WaitForSingleObject(native_handle_, INFINITE);
     160             :   DCHECK(result == WAIT_OBJECT_0);
     161             :   USE(result);
     162             : }
     163             : 
     164             : 
     165             : bool Semaphore::WaitFor(const TimeDelta& rel_time) {
     166             :   TimeTicks now = TimeTicks::Now();
     167             :   TimeTicks end = now + rel_time;
     168             :   while (true) {
     169             :     int64_t msec = (end - now).InMilliseconds();
     170             :     if (msec >= static_cast<int64_t>(INFINITE)) {
     171             :       DWORD result = WaitForSingleObject(native_handle_, INFINITE - 1);
     172             :       if (result == WAIT_OBJECT_0) {
     173             :         return true;
     174             :       }
     175             :       DCHECK(result == WAIT_TIMEOUT);
     176             :       now = TimeTicks::Now();
     177             :     } else {
     178             :       DWORD result = WaitForSingleObject(
     179             :           native_handle_, (msec < 0) ? 0 : static_cast<DWORD>(msec));
     180             :       if (result == WAIT_TIMEOUT) {
     181             :         return false;
     182             :       }
     183             :       DCHECK(result == WAIT_OBJECT_0);
     184             :       return true;
     185             :     }
     186             :   }
     187             : }
     188             : 
     189             : #endif  // V8_OS_MACOSX
     190             : 
     191             : }  // namespace base
     192             : }  // namespace v8

Generated by: LCOV version 1.10