ncm: use static memory pools for different allocations
This commit is contained in:
@@ -49,7 +49,7 @@ namespace ams::kvdb {
|
||||
|
||||
void Reset() {
|
||||
if (this->buffer != nullptr) {
|
||||
std::free(this->buffer);
|
||||
delete[] this->buffer;
|
||||
this->buffer = nullptr;
|
||||
this->size = 0;
|
||||
}
|
||||
@@ -68,7 +68,7 @@ namespace ams::kvdb {
|
||||
AMS_ABORT_UNLESS(this->buffer == nullptr);
|
||||
|
||||
/* Allocate a buffer. */
|
||||
this->buffer = static_cast<u8 *>(std::malloc(size));
|
||||
this->buffer = new (std::nothrow) u8[size];
|
||||
R_UNLESS(this->buffer != nullptr, ResultAllocationFailed());
|
||||
|
||||
this->size = size;
|
||||
|
||||
@@ -93,13 +93,14 @@ namespace ams::kvdb {
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
Entry *entries;
|
||||
MemoryResource *memory_resource;
|
||||
public:
|
||||
Index() : count(0), capacity(0), entries(nullptr) { /* ... */ }
|
||||
Index() : count(0), capacity(0), entries(nullptr), memory_resource(nullptr) { /* ... */ }
|
||||
|
||||
~Index() {
|
||||
if (this->entries != nullptr) {
|
||||
this->ResetEntries();
|
||||
std::free(this->entries);
|
||||
this->memory_resource->Deallocate(this->entries, sizeof(Entry) * this->capacity);
|
||||
this->entries = nullptr;
|
||||
}
|
||||
}
|
||||
@@ -114,30 +115,25 @@ namespace ams::kvdb {
|
||||
|
||||
void ResetEntries() {
|
||||
for (size_t i = 0; i < this->count; i++) {
|
||||
std::free(this->entries[i].GetValuePointer());
|
||||
this->memory_resource->Deallocate(this->entries[i].GetValuePointer(), this->entries[i].GetValueSize());
|
||||
}
|
||||
this->count = 0;
|
||||
}
|
||||
|
||||
Result Initialize(size_t capacity) {
|
||||
this->entries = reinterpret_cast<Entry *>(std::malloc(sizeof(Entry) * capacity));
|
||||
Result Initialize(size_t capacity, MemoryResource *mr) {
|
||||
this->entries = reinterpret_cast<Entry *>(mr->Allocate(sizeof(Entry) * capacity));
|
||||
R_UNLESS(this->entries != nullptr, ResultAllocationFailed());
|
||||
this->capacity = capacity;
|
||||
this->memory_resource = mr;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result Set(const Key &key, const void *value, size_t value_size) {
|
||||
/* Allocate new value. */
|
||||
void *new_value = std::malloc(value_size);
|
||||
R_UNLESS(new_value != nullptr, ResultAllocationFailed());
|
||||
auto value_guard = SCOPE_GUARD { std::free(new_value); };
|
||||
std::memcpy(new_value, value, value_size);
|
||||
|
||||
/* Find entry for key. */
|
||||
Entry *it = this->lower_bound(key);
|
||||
if (it != this->end() && it->GetKey() == key) {
|
||||
/* Entry already exists. Free old value. */
|
||||
std::free(it->GetValuePointer());
|
||||
this->memory_resource->Deallocate(it->GetValuePointer(), it->GetValueSize());
|
||||
} else {
|
||||
/* We need to add a new entry. Check we have room, move future keys forward. */
|
||||
R_UNLESS(this->count < this->capacity, ResultOutOfKeyResource());
|
||||
@@ -145,8 +141,12 @@ namespace ams::kvdb {
|
||||
this->count++;
|
||||
}
|
||||
|
||||
/* Allocate new value. */
|
||||
void *new_value = this->memory_resource->Allocate(value_size);
|
||||
R_UNLESS(new_value != nullptr, ResultAllocationFailed());
|
||||
std::memcpy(new_value, value, value_size);
|
||||
|
||||
/* Save the new Entry in the map. */
|
||||
value_guard.Cancel();
|
||||
*it = Entry(key, new_value, value_size);
|
||||
return ResultSuccess();
|
||||
}
|
||||
@@ -164,7 +164,7 @@ namespace ams::kvdb {
|
||||
R_UNLESS(it != this->end(), ResultKeyNotFound());
|
||||
|
||||
/* Free the value, move entries back. */
|
||||
std::free(it->GetValuePointer());
|
||||
this->memory_resource->Deallocate(it->GetValuePointer(), it->GetValueSize());
|
||||
std::memmove(it, it + 1, sizeof(*it) * (this->end() - (it + 1)));
|
||||
this->count--;
|
||||
return ResultSuccess();
|
||||
@@ -258,10 +258,11 @@ namespace ams::kvdb {
|
||||
Index index;
|
||||
Path path;
|
||||
Path temp_path;
|
||||
MemoryResource *memory_resource;
|
||||
public:
|
||||
MemoryKeyValueStore() { /* ... */ }
|
||||
|
||||
Result Initialize(const char *dir, size_t capacity) {
|
||||
Result Initialize(const char *dir, size_t capacity, MemoryResource *mr) {
|
||||
/* Ensure that the passed path is a directory. */
|
||||
fs::DirectoryEntryType entry_type;
|
||||
R_TRY(fs::GetEntryType(std::addressof(entry_type), dir));
|
||||
@@ -272,18 +273,21 @@ namespace ams::kvdb {
|
||||
this->temp_path.SetFormat("%s%s", dir, "/imkvdb.tmp");
|
||||
|
||||
/* Initialize our index. */
|
||||
R_TRY(this->index.Initialize(capacity));
|
||||
R_TRY(this->index.Initialize(capacity, mr));
|
||||
this->memory_resource = mr;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result Initialize(size_t capacity) {
|
||||
Result Initialize(size_t capacity, MemoryResource *mr) {
|
||||
/* This initializes without an archive file. */
|
||||
/* A store initialized this way cannot have its contents loaded from or flushed to disk. */
|
||||
this->path.Set("");
|
||||
this->temp_path.Set("");
|
||||
|
||||
/* Initialize our index. */
|
||||
R_TRY(this->index.Initialize(capacity));
|
||||
R_TRY(this->index.Initialize(capacity, mr));
|
||||
this->memory_resource = mr;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
@@ -319,9 +323,9 @@ namespace ams::kvdb {
|
||||
R_TRY(reader.GetEntrySize(&key_size, &value_size));
|
||||
|
||||
/* Allocate memory for value. */
|
||||
void *new_value = std::malloc(value_size);
|
||||
void *new_value = this->memory_resource->Allocate(value_size);
|
||||
R_UNLESS(new_value != nullptr, ResultAllocationFailed());
|
||||
auto value_guard = SCOPE_GUARD { std::free(new_value); };
|
||||
auto value_guard = SCOPE_GUARD { this->memory_resource->Deallocate(new_value, value_size); };
|
||||
|
||||
/* Read key and value. */
|
||||
Key key;
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace ams::ncm {
|
||||
|
||||
void Reset() {
|
||||
if (this->buffer != nullptr) {
|
||||
std::free(this->buffer);
|
||||
delete[] this->buffer;
|
||||
this->buffer = nullptr;
|
||||
this->size = 0;
|
||||
}
|
||||
@@ -68,7 +68,7 @@ namespace ams::ncm {
|
||||
AMS_ABORT_UNLESS(this->buffer == nullptr);
|
||||
|
||||
/* Allocate a buffer. */
|
||||
this->buffer = static_cast<u8 *>(std::malloc(size));
|
||||
this->buffer = new (std::nothrow) u8[size];
|
||||
R_UNLESS(this->buffer != nullptr, ResultAllocationFailed());
|
||||
|
||||
this->size = size;
|
||||
@@ -85,4 +85,5 @@ namespace ams::ncm {
|
||||
return ResultSuccess();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -30,6 +30,16 @@
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
class ContentMetaMemoryResource {
|
||||
private:
|
||||
mem::StandardAllocator allocator;
|
||||
sf::StandardAllocatorMemoryResource memory_resource;
|
||||
public:
|
||||
ContentMetaMemoryResource(void *heap, size_t heap_size) : allocator(heap, heap_size), memory_resource(std::addressof(allocator)) { /* ... */ }
|
||||
|
||||
MemoryResource *Get() { return std::addressof(this->memory_resource); }
|
||||
};
|
||||
|
||||
struct SystemSaveDataInfo {
|
||||
u64 id;
|
||||
u64 size;
|
||||
@@ -67,6 +77,7 @@ namespace ams::ncm {
|
||||
SystemSaveDataInfo info;
|
||||
std::shared_ptr<IContentMetaDatabase> content_meta_database;
|
||||
std::optional<kvdb::MemoryKeyValueStore<ContentMetaKey>> kvs;
|
||||
ContentMetaMemoryResource *memory_resource;
|
||||
u32 max_content_metas;
|
||||
|
||||
ContentMetaDatabaseRoot() { /* ... */ }
|
||||
@@ -92,8 +103,8 @@ namespace ams::ncm {
|
||||
Result InitializeContentStorageRoot(ContentStorageRoot *out, StorageId storage_id, fs::ContentStorageId content_storage_id);
|
||||
Result InitializeGameCardContentStorageRoot(ContentStorageRoot *out);
|
||||
|
||||
Result InitializeContentMetaDatabaseRoot(ContentMetaDatabaseRoot *out, StorageId storage_id, const SystemSaveDataInfo &info, size_t max_content_metas);
|
||||
Result InitializeGameCardContentMetaDatabaseRoot(ContentMetaDatabaseRoot *out, size_t max_content_metas);
|
||||
Result InitializeContentMetaDatabaseRoot(ContentMetaDatabaseRoot *out, StorageId storage_id, const SystemSaveDataInfo &info, size_t max_content_metas, ContentMetaMemoryResource *mr);
|
||||
Result InitializeGameCardContentMetaDatabaseRoot(ContentMetaDatabaseRoot *out, size_t max_content_metas, ContentMetaMemoryResource *mr);
|
||||
|
||||
Result BuildContentMetaDatabase(StorageId storage_id);
|
||||
Result ImportContentMetaDatabase(StorageId storage_id, bool from_signed_partition);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "sf/sf_common.hpp"
|
||||
#include "sf/sf_mem_utility.hpp"
|
||||
#include "sf/sf_service_object.hpp"
|
||||
#include "sf/hipc/sf_hipc_server_session_manager.hpp"
|
||||
|
||||
|
||||
@@ -16,6 +16,6 @@
|
||||
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include "../ams.hpp"
|
||||
#include "../os.hpp"
|
||||
#include "../sm/sm_types.hpp"
|
||||
#include <stratosphere/ams.hpp>
|
||||
#include <stratosphere/os.hpp>
|
||||
#include <stratosphere/sm/sm_types.hpp>
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* 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 <stratosphere/sf/sf_common.hpp>
|
||||
#include <stratosphere/mem.hpp>
|
||||
|
||||
namespace ams::sf {
|
||||
|
||||
class StandardAllocatorMemoryResource : public MemoryResource {
|
||||
private:
|
||||
mem::StandardAllocator *standard_allocator;
|
||||
public:
|
||||
explicit StandardAllocatorMemoryResource(mem::StandardAllocator *sa) : standard_allocator(sa) { /* ... */ }
|
||||
|
||||
mem::StandardAllocator *GetAllocator() const { return this->standard_allocator; }
|
||||
private:
|
||||
virtual void *AllocateImpl(size_t size, size_t alignment) override {
|
||||
return this->standard_allocator->Allocate(size, alignment);
|
||||
}
|
||||
|
||||
virtual void DeallocateImpl(void *buffer, size_t size, size_t alignment) override {
|
||||
return this->standard_allocator->Free(buffer);
|
||||
}
|
||||
|
||||
virtual bool IsEqualImpl(const MemoryResource &resource) const {
|
||||
return this == std::addressof(resource);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user