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/. */
7 #include "CrossProcessSemaphore.h"
9 #include "nsISupportsImpl.h"
10 #include <mach/mach_time.h>
12 static const uint64_t kNsPerUs
= 1000;
13 static const uint64_t kNsPerSec
= 1000000000;
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
));
30 CrossProcessSemaphore
* CrossProcessSemaphore::Create(
31 CrossProcessSemaphoreHandle aHandle
) {
35 return new CrossProcessSemaphore(std::move(aHandle
));
38 CrossProcessSemaphore::CrossProcessSemaphore(
39 CrossProcessSemaphoreHandle aSemaphore
)
40 : mSemaphore(std::move(aSemaphore
)) {
41 MOZ_COUNT_CTOR(CrossProcessSemaphore
);
44 CrossProcessSemaphore::~CrossProcessSemaphore() {
45 MOZ_ASSERT(mSemaphore
, "Improper construction of semaphore or double free.");
46 MOZ_COUNT_DTOR(CrossProcessSemaphore
);
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()) {
56 kr
= semaphore_wait(mSemaphore
.get());
57 } while (kr
== KERN_ABORTED
);
59 mach_timebase_info_data_t tb
;
60 if (mach_timebase_info(&tb
) != KERN_SUCCESS
) {
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
;
68 ts
.tv_sec
= ns
/ kNsPerSec
;
69 ts
.tv_nsec
= ns
% kNsPerSec
;
70 kr
= semaphore_timedwait(mSemaphore
.get(), ts
);
71 if (kr
!= KERN_ABORTED
) {
74 now
= (mach_absolute_time() * tb
.numer
) / tb
.denom
;
77 return kr
== KERN_SUCCESS
;
80 void CrossProcessSemaphore::Signal() {
81 MOZ_ASSERT(mSemaphore
, "Improper construction of semaphore.");
82 semaphore_signal(mSemaphore
.get());
85 CrossProcessSemaphoreHandle
CrossProcessSemaphore::CloneHandle() {
86 // Transfer the mach port backing the semaphore.
87 return mozilla::RetainMachSendRight(mSemaphore
.get());
90 void CrossProcessSemaphore::CloseHandle() {}
92 } // namespace mozilla