LCOV - code coverage report
Current view: top level - src/base/platform - semaphore.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 19 20 95.0 %
Date: 2019-04-18 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      736581 : Semaphore::Semaphore(int count) {
      76             :   DCHECK_GE(count, 0);
      77      736581 :   int result = sem_init(&native_handle_, 0, count);
      78             :   DCHECK_EQ(0, result);
      79             :   USE(result);
      80      736582 : }
      81             : 
      82             : 
      83     1471959 : Semaphore::~Semaphore() {
      84      735978 :   int result = sem_destroy(&native_handle_);
      85             :   DCHECK_EQ(0, result);
      86             :   USE(result);
      87      735981 : }
      88             : 
      89     1233216 : void Semaphore::Signal() {
      90     1233216 :   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     1232788 :   if (result != 0) {
      95           0 :     FATAL("Error when signaling semaphore, errno: %d", errno);
      96             :   }
      97     1232788 : }
      98             : 
      99             : 
     100     1227265 : void Semaphore::Wait() {
     101             :   while (true) {
     102     1227271 :     int result = sem_wait(&native_handle_);
     103     1228381 :     if (result == 0) return;  // Semaphore was signalled.
     104             :     // Signal caused spurious wakeup.
     105             :     DCHECK_EQ(-1, result);
     106             :     DCHECK_EQ(EINTR, errno);
     107             :   }
     108             : }
     109             : 
     110             : 
     111         215 : bool Semaphore::WaitFor(const TimeDelta& rel_time) {
     112             :   // Compute the time for end of timeout.
     113         430 :   const Time time = Time::NowFromSystemTime() + rel_time;
     114         215 :   const struct timespec ts = time.ToTimespec();
     115             : 
     116             :   // Wait for semaphore signalled or timeout.
     117             :   while (true) {
     118         215 :     int result = sem_timedwait(&native_handle_, &ts);
     119         215 :     if (result == 0) return true;  // Semaphore was signalled.
     120             : #if V8_LIBC_GLIBC && !V8_GLIBC_PREREQ(2, 4)
     121             :     if (result > 0) {
     122             :       // sem_timedwait in glibc prior to 2.3.4 returns the errno instead of -1.
     123             :       errno = result;
     124             :       result = -1;
     125             :     }
     126             : #endif
     127         206 :     if (result == -1 && errno == ETIMEDOUT) {
     128             :       // Timed out while waiting for semaphore.
     129             :       return false;
     130             :     }
     131             :     // Signal caused spurious wakeup.
     132             :     DCHECK_EQ(-1, result);
     133             :     DCHECK_EQ(EINTR, errno);
     134             :   }
     135             : }
     136             : 
     137             : #elif V8_OS_WIN
     138             : 
     139             : Semaphore::Semaphore(int count) {
     140             :   DCHECK_GE(count, 0);
     141             :   native_handle_ = ::CreateSemaphoreA(nullptr, count, 0x7FFFFFFF, nullptr);
     142             :   DCHECK_NOT_NULL(native_handle_);
     143             : }
     144             : 
     145             : 
     146             : Semaphore::~Semaphore() {
     147             :   BOOL result = CloseHandle(native_handle_);
     148             :   DCHECK(result);
     149             :   USE(result);
     150             : }
     151             : 
     152             : void Semaphore::Signal() {
     153             :   LONG dummy;
     154             :   BOOL result = ReleaseSemaphore(native_handle_, 1, &dummy);
     155             :   DCHECK(result);
     156             :   USE(result);
     157             : }
     158             : 
     159             : 
     160             : void Semaphore::Wait() {
     161             :   DWORD result = WaitForSingleObject(native_handle_, INFINITE);
     162             :   DCHECK(result == WAIT_OBJECT_0);
     163             :   USE(result);
     164             : }
     165             : 
     166             : 
     167             : bool Semaphore::WaitFor(const TimeDelta& rel_time) {
     168             :   TimeTicks now = TimeTicks::Now();
     169             :   TimeTicks end = now + rel_time;
     170             :   while (true) {
     171             :     int64_t msec = (end - now).InMilliseconds();
     172             :     if (msec >= static_cast<int64_t>(INFINITE)) {
     173             :       DWORD result = WaitForSingleObject(native_handle_, INFINITE - 1);
     174             :       if (result == WAIT_OBJECT_0) {
     175             :         return true;
     176             :       }
     177             :       DCHECK(result == WAIT_TIMEOUT);
     178             :       now = TimeTicks::Now();
     179             :     } else {
     180             :       DWORD result = WaitForSingleObject(
     181             :           native_handle_, (msec < 0) ? 0 : static_cast<DWORD>(msec));
     182             :       if (result == WAIT_TIMEOUT) {
     183             :         return false;
     184             :       }
     185             :       DCHECK(result == WAIT_OBJECT_0);
     186             :       return true;
     187             :     }
     188             :   }
     189             : }
     190             : 
     191             : #endif  // V8_OS_MACOSX
     192             : 
     193             : }  // namespace base
     194             : }  // namespace v8

Generated by: LCOV version 1.10