Atmosphere/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_pooled_buffer.hpp

115 lines
3.9 KiB
C++
Raw Normal View History

2020-04-06 12:15:24 +02:00
/*
* Copyright (c) Atmosphère-NX
2020-04-06 12:15:24 +02:00
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/fs/impl/fs_newable.hpp>
namespace ams::fssystem {
/* ACCURATE_TO_VERSION: Unknown */
2020-04-06 12:15:24 +02:00
constexpr inline size_t BufferPoolAlignment = 4_KB;
constexpr inline size_t BufferPoolWorkSize = 320;
class PooledBuffer {
NON_COPYABLE(PooledBuffer);
private:
2021-10-10 09:14:06 +02:00
char *m_buffer;
size_t m_size;
2020-04-06 12:15:24 +02:00
private:
static size_t GetAllocatableSizeMaxCore(bool large);
public:
static size_t GetAllocatableSizeMax() { return GetAllocatableSizeMaxCore(false); }
static size_t GetAllocatableParticularlyLargeSizeMax() { return GetAllocatableSizeMaxCore(true); }
private:
void Swap(PooledBuffer &rhs) {
2021-10-10 09:14:06 +02:00
std::swap(m_buffer, rhs.m_buffer);
std::swap(m_size, rhs.m_size);
2020-04-06 12:15:24 +02:00
}
public:
/* Constructor/Destructor. */
2021-10-10 09:14:06 +02:00
constexpr PooledBuffer() : m_buffer(), m_size() { /* ... */ }
2020-04-06 12:15:24 +02:00
2021-10-10 09:14:06 +02:00
PooledBuffer(size_t ideal_size, size_t required_size) : m_buffer(), m_size() {
2020-04-06 12:15:24 +02:00
this->Allocate(ideal_size, required_size);
}
~PooledBuffer() {
this->Deallocate();
}
/* Move and assignment. */
2021-10-10 09:14:06 +02:00
explicit PooledBuffer(PooledBuffer &&rhs) : m_buffer(rhs.m_buffer), m_size(rhs.m_size) {
rhs.m_buffer = nullptr;
rhs.m_size = 0;
2020-04-06 12:15:24 +02:00
}
PooledBuffer &operator=(PooledBuffer &&rhs) {
PooledBuffer(std::move(rhs)).Swap(*this);
return *this;
}
/* Allocation API. */
void Allocate(size_t ideal_size, size_t required_size) {
return this->AllocateCore(ideal_size, required_size, false);
}
void AllocateParticularlyLarge(size_t ideal_size, size_t required_size) {
return this->AllocateCore(ideal_size, required_size, true);
}
void Shrink(size_t ideal_size);
void Deallocate() {
/* Shrink the buffer to empty. */
this->Shrink(0);
2021-10-10 09:14:06 +02:00
AMS_ASSERT(m_buffer == nullptr);
2020-04-06 12:15:24 +02:00
}
char *GetBuffer() const {
2021-10-10 09:14:06 +02:00
AMS_ASSERT(m_buffer != nullptr);
return m_buffer;
2020-04-06 12:15:24 +02:00
}
size_t GetSize() const {
2021-10-10 09:14:06 +02:00
AMS_ASSERT(m_buffer != nullptr);
return m_size;
2020-04-06 12:15:24 +02:00
}
private:
void AllocateCore(size_t ideal_size, size_t required_size, bool large);
};
Result InitializeBufferPool(char *buffer, size_t size);
Result InitializeBufferPool(char *buffer, size_t size, char *work, size_t work_size);
bool IsPooledBuffer(const void *buffer);
size_t GetPooledBufferRetriedCount();
size_t GetPooledBufferReduceAllocationCount();
size_t GetPooledBufferFreeSizePeak();
void ClearPooledBufferPeak();
void RegisterAdditionalDeviceAddress(uintptr_t address, size_t size);
void UnregisterAdditionalDeviceAddress(uintptr_t address);
bool IsAdditionalDeviceAddress(const void *ptr);
2020-04-06 12:58:52 +02:00
inline bool IsDeviceAddress(const void *buffer) {
return IsPooledBuffer(buffer) || IsAdditionalDeviceAddress(buffer);
}
2020-04-06 12:15:24 +02:00
}