From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- ipc/glue/CrossProcessSemaphore_posix.cpp | 164 +++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 ipc/glue/CrossProcessSemaphore_posix.cpp (limited to 'ipc/glue/CrossProcessSemaphore_posix.cpp') diff --git a/ipc/glue/CrossProcessSemaphore_posix.cpp b/ipc/glue/CrossProcessSemaphore_posix.cpp new file mode 100644 index 0000000000..3b32a897ee --- /dev/null +++ b/ipc/glue/CrossProcessSemaphore_posix.cpp @@ -0,0 +1,164 @@ +/* -*- 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 "mozilla/Unused.h" +#include "nsDebug.h" +#include "nsISupportsImpl.h" +#include + +static const uint64_t kNsPerMs = 1000000; +static const uint64_t kNsPerSec = 1000000000; + +namespace { + +struct SemaphoreData { + sem_t mSemaphore; + mozilla::Atomic mRefCount; + uint32_t mInitialValue; +}; + +} // namespace + +namespace mozilla { + +/* static */ +CrossProcessSemaphore* CrossProcessSemaphore::Create(const char*, + uint32_t aInitialValue) { + RefPtr sharedBuffer = new ipc::SharedMemoryBasic; + if (!sharedBuffer->Create(sizeof(SemaphoreData))) { + return nullptr; + } + + if (!sharedBuffer->Map(sizeof(SemaphoreData))) { + return nullptr; + } + + SemaphoreData* data = static_cast(sharedBuffer->memory()); + + if (!data) { + return nullptr; + } + + if (sem_init(&data->mSemaphore, 1, aInitialValue)) { + return nullptr; + } + + CrossProcessSemaphore* sem = new CrossProcessSemaphore; + sem->mSharedBuffer = sharedBuffer; + sem->mSemaphore = &data->mSemaphore; + sem->mRefCount = &data->mRefCount; + *sem->mRefCount = 1; + + data->mInitialValue = aInitialValue; + + return sem; +} + +/* static */ +CrossProcessSemaphore* CrossProcessSemaphore::Create( + CrossProcessSemaphoreHandle aHandle) { + RefPtr sharedBuffer = new ipc::SharedMemoryBasic; + + if (!sharedBuffer->IsHandleValid(aHandle)) { + return nullptr; + } + + if (!sharedBuffer->SetHandle(std::move(aHandle), + ipc::SharedMemory::RightsReadWrite)) { + return nullptr; + } + + if (!sharedBuffer->Map(sizeof(SemaphoreData))) { + return nullptr; + } + + sharedBuffer->CloseHandle(); + + SemaphoreData* data = static_cast(sharedBuffer->memory()); + + if (!data) { + return nullptr; + } + + int32_t oldCount = data->mRefCount++; + if (oldCount == 0) { + // The other side has already let go of their CrossProcessSemaphore, so now + // mSemaphore is garbage. We need to re-initialize it. + if (sem_init(&data->mSemaphore, 1, data->mInitialValue)) { + data->mRefCount--; + return nullptr; + } + } + + CrossProcessSemaphore* sem = new CrossProcessSemaphore; + sem->mSharedBuffer = sharedBuffer; + sem->mSemaphore = &data->mSemaphore; + sem->mRefCount = &data->mRefCount; + return sem; +} + +CrossProcessSemaphore::CrossProcessSemaphore() + : mSemaphore(nullptr), mRefCount(nullptr) { + MOZ_COUNT_CTOR(CrossProcessSemaphore); +} + +CrossProcessSemaphore::~CrossProcessSemaphore() { + int32_t oldCount = --(*mRefCount); + + if (oldCount == 0) { + // Nothing can be done if the destroy fails so ignore return code. + Unused << sem_destroy(mSemaphore); + } + + MOZ_COUNT_DTOR(CrossProcessSemaphore); +} + +bool CrossProcessSemaphore::Wait(const Maybe& aWaitTime) { + MOZ_ASSERT(*mRefCount > 0, + "Attempting to wait on a semaphore with zero ref count"); + int ret; + if (aWaitTime.isSome()) { + struct timespec ts; + if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { + return false; + } + + uint64_t ns = uint64_t(kNsPerMs * aWaitTime->ToMilliseconds()) + ts.tv_nsec; + ts.tv_sec += ns / kNsPerSec; + ts.tv_nsec = ns % kNsPerSec; + + while ((ret = sem_timedwait(mSemaphore, &ts)) == -1 && errno == EINTR) { + } + } else { + while ((ret = sem_wait(mSemaphore)) == -1 && errno == EINTR) { + } + } + return ret == 0; +} + +void CrossProcessSemaphore::Signal() { + MOZ_ASSERT(*mRefCount > 0, + "Attempting to signal a semaphore with zero ref count"); + sem_post(mSemaphore); +} + +CrossProcessSemaphoreHandle CrossProcessSemaphore::CloneHandle() { + CrossProcessSemaphoreHandle result = ipc::SharedMemoryBasic::NULLHandle(); + + if (mSharedBuffer) { + result = mSharedBuffer->CloneHandle(); + if (!result) { + MOZ_CRASH(); + } + } + + return result; +} + +void CrossProcessSemaphore::CloseHandle() { mSharedBuffer->CloseHandle(); } + +} // namespace mozilla -- cgit v1.2.3