tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

CrossProcessSemaphore_mach.cpp (3011B)


      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 "nsDebug.h"
      9 #include "nsISupportsImpl.h"
     10 #include <mach/mach_time.h>
     11 
     12 static const uint64_t kNsPerUs = 1000;
     13 static const uint64_t kNsPerSec = 1000000000;
     14 
     15 namespace mozilla {
     16 
     17 /* static */
     18 CrossProcessSemaphore* CrossProcessSemaphore::Create(const char*,
     19                                                     uint32_t aInitialValue) {
     20  semaphore_t sem = SEMAPHORE_NULL;
     21  if (semaphore_create(mach_task_self(), &sem, SYNC_POLICY_FIFO,
     22                       aInitialValue) == KERN_SUCCESS &&
     23      sem != SEMAPHORE_NULL) {
     24    return new CrossProcessSemaphore(CrossProcessSemaphoreHandle(sem));
     25  }
     26  return nullptr;
     27 }
     28 
     29 /* static */
     30 CrossProcessSemaphore* CrossProcessSemaphore::Create(
     31    CrossProcessSemaphoreHandle aHandle) {
     32  if (!aHandle) {
     33    return nullptr;
     34  }
     35  return new CrossProcessSemaphore(std::move(aHandle));
     36 }
     37 
     38 CrossProcessSemaphore::CrossProcessSemaphore(
     39    CrossProcessSemaphoreHandle aSemaphore)
     40    : mSemaphore(std::move(aSemaphore)) {
     41  MOZ_COUNT_CTOR(CrossProcessSemaphore);
     42 }
     43 
     44 CrossProcessSemaphore::~CrossProcessSemaphore() {
     45  MOZ_ASSERT(mSemaphore, "Improper construction of semaphore or double free.");
     46  MOZ_COUNT_DTOR(CrossProcessSemaphore);
     47 }
     48 
     49 bool CrossProcessSemaphore::Wait(const Maybe<TimeDuration>& aWaitTime) {
     50  MOZ_ASSERT(mSemaphore, "Improper construction of semaphore.");
     51  int kr = KERN_OPERATION_TIMED_OUT;
     52  // semaphore_(timed)wait may be interrupted by KERN_ABORTED. Carefully restart
     53  // the wait until it either succeeds or times out.
     54  if (aWaitTime.isNothing()) {
     55    do {
     56      kr = semaphore_wait(mSemaphore.get());
     57    } while (kr == KERN_ABORTED);
     58  } else {
     59    mach_timebase_info_data_t tb;
     60    if (mach_timebase_info(&tb) != KERN_SUCCESS) {
     61      return false;
     62    }
     63    uint64_t now = (mach_absolute_time() * tb.numer) / tb.denom;
     64    uint64_t deadline = now + uint64_t(kNsPerUs * aWaitTime->ToMicroseconds());
     65    while (now <= deadline) {
     66      uint64_t ns = deadline - now;
     67      mach_timespec_t ts;
     68      ts.tv_sec = ns / kNsPerSec;
     69      ts.tv_nsec = ns % kNsPerSec;
     70      kr = semaphore_timedwait(mSemaphore.get(), ts);
     71      if (kr != KERN_ABORTED) {
     72        break;
     73      }
     74      now = (mach_absolute_time() * tb.numer) / tb.denom;
     75    }
     76  }
     77  return kr == KERN_SUCCESS;
     78 }
     79 
     80 void CrossProcessSemaphore::Signal() {
     81  MOZ_ASSERT(mSemaphore, "Improper construction of semaphore.");
     82  semaphore_signal(mSemaphore.get());
     83 }
     84 
     85 CrossProcessSemaphoreHandle CrossProcessSemaphore::CloneHandle() {
     86  // Transfer the mach port backing the semaphore.
     87  return mozilla::RetainMachSendRight(mSemaphore.get());
     88 }
     89 
     90 void CrossProcessSemaphore::CloseHandle() {}
     91 
     92 }  // namespace mozilla