summaryrefslogtreecommitdiffstats
path: root/xpcom/base/RLBoxSandboxPool.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--xpcom/base/RLBoxSandboxPool.cpp111
1 files changed, 111 insertions, 0 deletions
diff --git a/xpcom/base/RLBoxSandboxPool.cpp b/xpcom/base/RLBoxSandboxPool.cpp
new file mode 100644
index 0000000000..c3b86f1698
--- /dev/null
+++ b/xpcom/base/RLBoxSandboxPool.cpp
@@ -0,0 +1,111 @@
+/* -*- 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 "nsThreadUtils.h"
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/DebugOnly.h"
+#include "mozilla/RLBoxSandboxPool.h"
+#ifdef MOZ_USING_WASM_SANDBOXING
+# include "wasm2c_rt_mem.h"
+#endif
+
+using namespace mozilla;
+
+NS_IMPL_ISUPPORTS(RLBoxSandboxPool, nsITimerCallback, nsINamed)
+
+void RLBoxSandboxPool::StartTimer() {
+ mMutex.AssertCurrentThreadOwns();
+ MOZ_ASSERT(!mTimer, "timer already initialized");
+ if (NS_IsMainThread() &&
+ PastShutdownPhase(ShutdownPhase::AppShutdownConfirmed)) {
+ // If we're shutting down, setting the time might fail, and we don't need it
+ // (since all the memory will be cleaned up soon anyway). Note that
+ // PastShutdownPhase() can only be called on the main thread, but that's
+ // fine, because other threads will have joined already by the point timers
+ // start failing to register.
+ mPool.Clear();
+ return;
+ }
+ DebugOnly<nsresult> rv = NS_NewTimerWithCallback(
+ getter_AddRefs(mTimer), this, mDelaySeconds * 1000,
+ nsITimer::TYPE_ONE_SHOT, GetMainThreadSerialEventTarget());
+ MOZ_ASSERT(NS_SUCCEEDED(rv), "failed to create timer");
+}
+
+void RLBoxSandboxPool::CancelTimer() {
+ mMutex.AssertCurrentThreadOwns();
+ if (mTimer) {
+ mTimer->Cancel();
+ mTimer = nullptr;
+ }
+}
+
+NS_IMETHODIMP RLBoxSandboxPool::Notify(nsITimer* aTimer) {
+ MutexAutoLock lock(mMutex);
+
+ mPool.Clear();
+ mTimer = nullptr;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP RLBoxSandboxPool::GetName(nsACString& aName) {
+ aName.AssignLiteral("RLBoxSandboxPool");
+ return NS_OK;
+}
+
+void RLBoxSandboxPool::Push(UniquePtr<RLBoxSandboxDataBase> sbxData) {
+ MutexAutoLock lock(mMutex);
+
+ mPool.AppendElement(std::move(sbxData));
+ if (!mTimer) {
+ StartTimer();
+ }
+}
+
+UniquePtr<RLBoxSandboxPoolData> RLBoxSandboxPool::PopOrCreate(
+ uint64_t aMinSize) {
+ MutexAutoLock lock(mMutex);
+
+ UniquePtr<RLBoxSandboxDataBase> sbxData;
+
+ if (!mPool.IsEmpty()) {
+ const int64_t lastIndex = ReleaseAssertedCast<int64_t>(mPool.Length()) - 1;
+ for (int64_t i = lastIndex; i >= 0; i--) {
+ if (mPool[i]->mSize >= aMinSize) {
+ sbxData = std::move(mPool[i]);
+ mPool.RemoveElementAt(i);
+
+ // If we reuse a sandbox from the pool, reset the timer to clear the
+ // pool
+ CancelTimer();
+ if (!mPool.IsEmpty()) {
+ StartTimer();
+ }
+ break;
+ }
+ }
+ }
+
+ if (!sbxData) {
+#ifdef MOZ_USING_WASM_SANDBOXING
+ // RLBox's wasm sandboxes have a limited platform dependent capacity. We
+ // track this capacity in this pool.
+ const w2c_mem_capacity w2c_capacity = get_valid_wasm2c_memory_capacity(
+ aMinSize, true /* 32-bit wasm memory*/);
+ const uint64_t chosenCapacity = w2c_capacity.max_size;
+#else
+ // Note the noop sandboxes have no capacity limit. In this case we simply
+ // specify a value of 4gb. This is not actually enforced by the noop
+ // sandbox.
+ const uint64_t chosenCapacity = static_cast<uint64_t>(1) << 32;
+#endif
+ sbxData = CreateSandboxData(chosenCapacity);
+ NS_ENSURE_TRUE(sbxData, nullptr);
+ }
+
+ return MakeUnique<RLBoxSandboxPoolData>(std::move(sbxData), this);
+}