summaryrefslogtreecommitdiffstats
path: root/ipc/glue/CrossProcessSemaphore_mach.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--ipc/glue/CrossProcessSemaphore_mach.cpp92
1 files changed, 92 insertions, 0 deletions
diff --git a/ipc/glue/CrossProcessSemaphore_mach.cpp b/ipc/glue/CrossProcessSemaphore_mach.cpp
new file mode 100644
index 0000000000..d7cccee2a0
--- /dev/null
+++ b/ipc/glue/CrossProcessSemaphore_mach.cpp
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "CrossProcessSemaphore.h"
+#include "nsDebug.h"
+#include "nsISupportsImpl.h"
+#include <mach/mach_time.h>
+
+static const uint64_t kNsPerUs = 1000;
+static const uint64_t kNsPerSec = 1000000000;
+
+namespace mozilla {
+
+/* static */
+CrossProcessSemaphore* CrossProcessSemaphore::Create(const char*,
+ uint32_t aInitialValue) {
+ semaphore_t sem = SEMAPHORE_NULL;
+ if (semaphore_create(mach_task_self(), &sem, SYNC_POLICY_FIFO,
+ aInitialValue) == KERN_SUCCESS &&
+ sem != SEMAPHORE_NULL) {
+ return new CrossProcessSemaphore(CrossProcessSemaphoreHandle(sem));
+ }
+ return nullptr;
+}
+
+/* static */
+CrossProcessSemaphore* CrossProcessSemaphore::Create(
+ CrossProcessSemaphoreHandle aHandle) {
+ if (!aHandle) {
+ return nullptr;
+ }
+ return new CrossProcessSemaphore(std::move(aHandle));
+}
+
+CrossProcessSemaphore::CrossProcessSemaphore(
+ CrossProcessSemaphoreHandle aSemaphore)
+ : mSemaphore(std::move(aSemaphore)) {
+ MOZ_COUNT_CTOR(CrossProcessSemaphore);
+}
+
+CrossProcessSemaphore::~CrossProcessSemaphore() {
+ MOZ_ASSERT(mSemaphore, "Improper construction of semaphore or double free.");
+ MOZ_COUNT_DTOR(CrossProcessSemaphore);
+}
+
+bool CrossProcessSemaphore::Wait(const Maybe<TimeDuration>& aWaitTime) {
+ MOZ_ASSERT(mSemaphore, "Improper construction of semaphore.");
+ int kr = KERN_OPERATION_TIMED_OUT;
+ // semaphore_(timed)wait may be interrupted by KERN_ABORTED. Carefully restart
+ // the wait until it either succeeds or times out.
+ if (aWaitTime.isNothing()) {
+ do {
+ kr = semaphore_wait(mSemaphore.get());
+ } while (kr == KERN_ABORTED);
+ } else {
+ mach_timebase_info_data_t tb;
+ if (mach_timebase_info(&tb) != KERN_SUCCESS) {
+ return false;
+ }
+ uint64_t now = (mach_absolute_time() * tb.numer) / tb.denom;
+ uint64_t deadline = now + uint64_t(kNsPerUs * aWaitTime->ToMicroseconds());
+ while (now <= deadline) {
+ uint64_t ns = deadline - now;
+ mach_timespec_t ts;
+ ts.tv_sec = ns / kNsPerSec;
+ ts.tv_nsec = ns % kNsPerSec;
+ kr = semaphore_timedwait(mSemaphore.get(), ts);
+ if (kr != KERN_ABORTED) {
+ break;
+ }
+ now = (mach_absolute_time() * tb.numer) / tb.denom;
+ }
+ }
+ return kr == KERN_SUCCESS;
+}
+
+void CrossProcessSemaphore::Signal() {
+ MOZ_ASSERT(mSemaphore, "Improper construction of semaphore.");
+ semaphore_signal(mSemaphore.get());
+}
+
+CrossProcessSemaphoreHandle CrossProcessSemaphore::CloneHandle() {
+ // Transfer the mach port backing the semaphore.
+ return mozilla::RetainMachSendRight(mSemaphore.get());
+}
+
+void CrossProcessSemaphore::CloseHandle() {}
+
+} // namespace mozilla