// Copyright 2021 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/memory/unsafe_shared_memory_pool.h" #include "base/logging.h" namespace { constexpr size_t kMaxStoredBuffers = 32; } // namespace namespace base { UnsafeSharedMemoryPool::UnsafeSharedMemoryPool() = default; UnsafeSharedMemoryPool::~UnsafeSharedMemoryPool() = default; UnsafeSharedMemoryPool::Handle::Handle( PassKey, UnsafeSharedMemoryRegion region, WritableSharedMemoryMapping mapping, scoped_refptr pool) : region_(std::move(region)), mapping_(std::move(mapping)), pool_(std::move(pool)) { CHECK(pool_); DCHECK(region_.IsValid()); DCHECK(mapping_.IsValid()); } UnsafeSharedMemoryPool::Handle::~Handle() { pool_->ReleaseBuffer(std::move(region_), std::move(mapping_)); } const UnsafeSharedMemoryRegion& UnsafeSharedMemoryPool::Handle::GetRegion() const { return region_; } const WritableSharedMemoryMapping& UnsafeSharedMemoryPool::Handle::GetMapping() const { return mapping_; } std::unique_ptr UnsafeSharedMemoryPool::MaybeAllocateBuffer(size_t region_size) { AutoLock lock(lock_); DCHECK_GE(region_size, 0u); if (is_shutdown_) return nullptr; // Only change the configured size if bigger region is requested to avoid // unncecessary reallocations. if (region_size > region_size_) { regions_.clear(); region_size_ = region_size; } if (!regions_.empty()) { auto region = std::move(regions_.back()); regions_.pop_back(); DCHECK_GE(region.first.GetSize(), region_size_); auto handle = std::make_unique(PassKey(), std::move(region.first), std::move(region.second), this); return handle; } auto region = UnsafeSharedMemoryRegion::Create(region_size_); if (!region.IsValid()) return nullptr; WritableSharedMemoryMapping mapping = region.Map(); if (!mapping.IsValid()) return nullptr; return std::make_unique(PassKey(), std::move(region), std::move(mapping), this); } void UnsafeSharedMemoryPool::Shutdown() { AutoLock lock(lock_); DCHECK(!is_shutdown_); is_shutdown_ = true; regions_.clear(); } void UnsafeSharedMemoryPool::ReleaseBuffer( UnsafeSharedMemoryRegion region, WritableSharedMemoryMapping mapping) { AutoLock lock(lock_); // Only return regions which are at least as big as the current configuration. if (is_shutdown_ || regions_.size() >= kMaxStoredBuffers || !region.IsValid() || region.GetSize() < region_size_) { DLOG(WARNING) << "Not returning SharedMemoryRegion to the pool:" << " is_shutdown: " << (is_shutdown_ ? "true" : "false") << " stored regions: " << regions_.size() << " configured size: " << region_size_ << " this region size: " << region.GetSize() << " valid: " << (region.IsValid() ? "true" : "false"); return; } regions_.emplace_back(std::move(region), std::move(mapping)); } } // namespace base