mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 10:18:41 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			111 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			111 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- 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);
 | 
						|
}
 |