LCOV - code coverage report
Current view: top level - ipc/glue - CrossProcessSemaphore_posix.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 56 71 78.9 %
Date: 2017-07-14 16:53:18 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "CrossProcessSemaphore.h"
       8             : #include "mozilla/Unused.h"
       9             : #include "nsDebug.h"
      10             : #include "nsISupportsImpl.h"
      11             : #include <errno.h>
      12             : 
      13             : static const uint64_t kNsPerMs = 1000000;
      14             : static const uint64_t kNsPerSec = 1000000000;
      15             : 
      16             : namespace {
      17             : 
      18             : 
      19             : struct SemaphoreData {
      20             :   sem_t mSemaphore;
      21             :   mozilla::Atomic<int32_t> mRefCount;
      22             :   uint32_t mInitialValue;
      23             : };
      24             : 
      25             : } // namespace
      26             : 
      27             : namespace mozilla {
      28             : 
      29             : /* static */ CrossProcessSemaphore*
      30           9 : CrossProcessSemaphore::Create(const char*, uint32_t aInitialValue)
      31             : {
      32          18 :   RefPtr<ipc::SharedMemoryBasic> sharedBuffer = new ipc::SharedMemoryBasic;
      33           9 :   if (!sharedBuffer->Create(sizeof(SemaphoreData))) {
      34           0 :     return nullptr;
      35             :   }
      36             : 
      37           9 :   if (!sharedBuffer->Map(sizeof(SemaphoreData))) {
      38           0 :     return nullptr;
      39             :   }
      40             : 
      41           9 :   SemaphoreData* data = static_cast<SemaphoreData*>(sharedBuffer->memory());
      42             : 
      43           9 :   if (!data) {
      44           0 :     return nullptr;
      45             :   }
      46             : 
      47           9 :   if (sem_init(&data->mSemaphore, 1, aInitialValue)) {
      48           0 :     return nullptr;
      49             :   }
      50             : 
      51           9 :   CrossProcessSemaphore* sem = new CrossProcessSemaphore;
      52           9 :   sem->mSharedBuffer = sharedBuffer;
      53           9 :   sem->mSemaphore = &data->mSemaphore;
      54           9 :   sem->mRefCount = &data->mRefCount;
      55           9 :   *sem->mRefCount = 1;
      56             : 
      57           9 :   data->mInitialValue = aInitialValue;
      58             : 
      59           9 :   return sem;
      60             : }
      61             : 
      62             : /* static */ CrossProcessSemaphore*
      63          33 : CrossProcessSemaphore::Create(CrossProcessSemaphoreHandle aHandle)
      64             : {
      65          66 :   RefPtr<ipc::SharedMemoryBasic> sharedBuffer = new ipc::SharedMemoryBasic;
      66             : 
      67          33 :   if (!sharedBuffer->IsHandleValid(aHandle)) {
      68           0 :     return nullptr;
      69             :   }
      70             : 
      71          33 :   if (!sharedBuffer->SetHandle(aHandle, ipc::SharedMemory::RightsReadWrite)) {
      72           0 :     return nullptr;
      73             :   }
      74             : 
      75          33 :   if (!sharedBuffer->Map(sizeof(SemaphoreData))) {
      76           0 :     return nullptr;
      77             :   }
      78             : 
      79          33 :   SemaphoreData* data = static_cast<SemaphoreData*>(sharedBuffer->memory());
      80             : 
      81          33 :   if (!data) {
      82           0 :     return nullptr;
      83             :   }
      84             : 
      85          33 :   int32_t oldCount = data->mRefCount++;
      86          33 :   if (oldCount == 0) {
      87             :     // The other side has already let go of their CrossProcessSemaphore, so now
      88             :     // mSemaphore is garbage. We need to re-initialize it.
      89           0 :     if (sem_init(&data->mSemaphore, 1, data->mInitialValue)) {
      90           0 :       data->mRefCount--;
      91           0 :       return nullptr;
      92             :     }
      93             :   }
      94             : 
      95          33 :   CrossProcessSemaphore* sem = new CrossProcessSemaphore;
      96          33 :   sem->mSharedBuffer = sharedBuffer;
      97          33 :   sem->mSemaphore = &data->mSemaphore;
      98          33 :   sem->mRefCount = &data->mRefCount;
      99          33 :   return sem;
     100             : }
     101             : 
     102             : 
     103          42 : CrossProcessSemaphore::CrossProcessSemaphore()
     104             :   : mSemaphore(nullptr)
     105          42 :   , mRefCount(nullptr)
     106             : {
     107          42 :   MOZ_COUNT_CTOR(CrossProcessSemaphore);
     108          42 : }
     109             : 
     110          74 : CrossProcessSemaphore::~CrossProcessSemaphore()
     111             : {
     112          37 :   int32_t oldCount = --(*mRefCount);
     113             : 
     114          37 :   if (oldCount == 0) {
     115             :     // Nothing can be done if the destroy fails so ignore return code.
     116           6 :     Unused << sem_destroy(mSemaphore);
     117             :   }
     118             : 
     119          37 :   MOZ_COUNT_DTOR(CrossProcessSemaphore);
     120          37 : }
     121             : 
     122             : bool
     123          67 : CrossProcessSemaphore::Wait(const Maybe<TimeDuration>& aWaitTime)
     124             : {
     125          67 :   MOZ_ASSERT(*mRefCount > 0, "Attempting to wait on a semaphore with zero ref count");
     126             :   int ret;
     127          67 :   if (aWaitTime.isSome()) {
     128             :     struct timespec ts;
     129          34 :     if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
     130           0 :       return false;
     131             :     }
     132             : 
     133          34 :     ts.tv_nsec += (kNsPerMs * aWaitTime->ToMilliseconds());
     134          34 :     ts.tv_sec += ts.tv_nsec / kNsPerSec;
     135          34 :     ts.tv_nsec %= kNsPerSec;
     136             : 
     137          34 :     while ((ret = sem_timedwait(mSemaphore, &ts)) == -1 && errno == EINTR) {
     138           0 :       continue;
     139             :     }
     140             :   } else {
     141          33 :     while ((ret = sem_wait(mSemaphore)) == -1 && errno == EINTR) {
     142           0 :       continue;
     143             :     }
     144             :   }
     145          67 :   return ret == 0;
     146             : }
     147             : 
     148             : void
     149          65 : CrossProcessSemaphore::Signal()
     150             : {
     151          65 :   MOZ_ASSERT(*mRefCount > 0, "Attempting to signal a semaphore with zero ref count");
     152          65 :   sem_post(mSemaphore);
     153          65 : }
     154             : 
     155             : CrossProcessSemaphoreHandle
     156          33 : CrossProcessSemaphore::ShareToProcess(base::ProcessId aTargetPid)
     157             : {
     158          33 :   CrossProcessSemaphoreHandle result = ipc::SharedMemoryBasic::NULLHandle();
     159             : 
     160          33 :   if (mSharedBuffer && !mSharedBuffer->ShareToProcess(aTargetPid, &result)) {
     161           0 :     MOZ_CRASH();
     162             :   }
     163             : 
     164          33 :   return result;
     165             : }
     166             : 
     167             : } // namespace mozilla

Generated by: LCOV version 1.13