mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-29 06:16:55 +01:00
Report NP Web API memory pool statistics for active library contexts
This commit is contained in:
+42
-2
@@ -3139,9 +3139,21 @@ namespace LibNpWebApi2 {
|
|||||||
LIB_VERSION("NpWebApi2", 1, "NpWebApi2", 1, 1);
|
LIB_VERSION("NpWebApi2", 1, "NpWebApi2", 1, 1);
|
||||||
|
|
||||||
constexpr int NP_WEBAPI2_ERROR_INVALID_ARGUMENT = -2141899774; /* 0x80553402 */
|
constexpr int NP_WEBAPI2_ERROR_INVALID_ARGUMENT = -2141899774; /* 0x80553402 */
|
||||||
|
constexpr int NP_WEBAPI2_ERROR_INVALID_LIB_CONTEXT_ID = -2141899773; /* 0x80553403 */
|
||||||
|
constexpr int NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND = -2141899772; /* 0x80553404 */
|
||||||
constexpr int NP_WEBAPI2_ERROR_REQUEST_NOT_FOUND = -2141899770; /* 0x80553406 */
|
constexpr int NP_WEBAPI2_ERROR_REQUEST_NOT_FOUND = -2141899770; /* 0x80553406 */
|
||||||
constexpr int NP_WEBAPI2_ERROR_NOT_SIGNED_IN = -2141899769; /* 0x80553407 */
|
constexpr int NP_WEBAPI2_ERROR_NOT_SIGNED_IN = -2141899769; /* 0x80553407 */
|
||||||
|
|
||||||
|
struct NpWebApi2MemoryPoolStats {
|
||||||
|
size_t pool_size;
|
||||||
|
size_t max_inuse_size;
|
||||||
|
size_t current_inuse_size;
|
||||||
|
int32_t reserved;
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::mutex g_np_webapi2_context_mutex;
|
||||||
|
static std::map<int, size_t> g_np_webapi2_contexts;
|
||||||
|
|
||||||
struct NpWebApi2ResponseInformationOption {
|
struct NpWebApi2ResponseInformationOption {
|
||||||
int32_t http_status;
|
int32_t http_status;
|
||||||
char* error_object;
|
char* error_object;
|
||||||
@@ -3171,7 +3183,30 @@ static int KYTY_SYSV_ABI NpWebApi2Initialize(int lib_http_ctx_id, size_t pool_si
|
|||||||
|
|
||||||
static int id = 0;
|
static int id = 0;
|
||||||
|
|
||||||
return ++id;
|
if (pool_size > std::numeric_limits<size_t>::max() - 0x3fff) {
|
||||||
|
return NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
std::lock_guard lock(g_np_webapi2_context_mutex);
|
||||||
|
g_np_webapi2_contexts[++id] = (pool_size + 0x3fff) & ~size_t {0x3fff};
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int KYTY_SYSV_ABI NpWebApi2GetMemoryPoolStats(int lib_ctx_id,
|
||||||
|
NpWebApi2MemoryPoolStats* stats) {
|
||||||
|
if (stats == nullptr) {
|
||||||
|
return NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
|
||||||
|
}
|
||||||
|
if (lib_ctx_id <= 0) {
|
||||||
|
return NP_WEBAPI2_ERROR_INVALID_LIB_CONTEXT_ID;
|
||||||
|
}
|
||||||
|
std::lock_guard lock(g_np_webapi2_context_mutex);
|
||||||
|
const auto context = g_np_webapi2_contexts.find(lib_ctx_id);
|
||||||
|
if (context == g_np_webapi2_contexts.end()) {
|
||||||
|
return NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||||
|
}
|
||||||
|
// Requests currently use host storage, not allocations from the library pool.
|
||||||
|
*stats = {context->second, 0, 0, 0};
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int KYTY_SYSV_ABI NpWebApi2PushEventCreateHandle(int lib_ctx_id) {
|
static int KYTY_SYSV_ABI NpWebApi2PushEventCreateHandle(int lib_ctx_id) {
|
||||||
@@ -3438,11 +3473,16 @@ static int KYTY_SYSV_ABI NpWebApi2Terminate(int lib_ctx_id) {
|
|||||||
|
|
||||||
LOGF("\t lib_ctx_id = %d\n", lib_ctx_id);
|
LOGF("\t lib_ctx_id = %d\n", lib_ctx_id);
|
||||||
|
|
||||||
return 0;
|
if (lib_ctx_id <= 0) {
|
||||||
|
return NP_WEBAPI2_ERROR_INVALID_LIB_CONTEXT_ID;
|
||||||
|
}
|
||||||
|
std::lock_guard lock(g_np_webapi2_context_mutex);
|
||||||
|
return g_np_webapi2_contexts.erase(lib_ctx_id) != 0 ? OK : NP_WEBAPI2_ERROR_LIB_CONTEXT_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
LIB_DEFINE(InitNet_1_NpWebApi2) {
|
LIB_DEFINE(InitNet_1_NpWebApi2) {
|
||||||
LIB_FUNC("+o9816YQhqQ", LibNpWebApi2::NpWebApi2Initialize);
|
LIB_FUNC("+o9816YQhqQ", LibNpWebApi2::NpWebApi2Initialize);
|
||||||
|
LIB_FUNC("Xweb+naPZ8Y", LibNpWebApi2::NpWebApi2GetMemoryPoolStats);
|
||||||
LIB_FUNC("WV1GwM32NgY", LibNpWebApi2::NpWebApi2PushEventCreateHandle);
|
LIB_FUNC("WV1GwM32NgY", LibNpWebApi2::NpWebApi2PushEventCreateHandle);
|
||||||
LIB_FUNC("sk54bi6FtYM", LibNpWebApi2::NpWebApi2CreateUserContext);
|
LIB_FUNC("sk54bi6FtYM", LibNpWebApi2::NpWebApi2CreateUserContext);
|
||||||
LIB_FUNC("9X9+cneTGUU", LibNpWebApi2::NpWebApi2DeleteUserContext);
|
LIB_FUNC("9X9+cneTGUU", LibNpWebApi2::NpWebApi2DeleteUserContext);
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ namespace Libs::LibNet {
|
|||||||
void InitNet_1_Net(Loader::SymbolDatabase *symbols);
|
void InitNet_1_Net(Loader::SymbolDatabase *symbols);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Libs::LibNpWebApi2 {
|
||||||
|
void InitNet_1_NpWebApi2(Loader::SymbolDatabase *symbols);
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
namespace FileSystem = Libs::LibKernel::FileSystem;
|
namespace FileSystem = Libs::LibKernel::FileSystem;
|
||||||
@@ -212,6 +216,43 @@ void TestAioBatches() {
|
|||||||
Check(FileSystem::KernelClose(fd) == OK, "close AIO read fixture");
|
Check(FileSystem::KernelClose(fd) == OK, "close AIO read fixture");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestNpWebApi2Memory() {
|
||||||
|
Loader::SymbolDatabase symbols;
|
||||||
|
Libs::LibNpWebApi2::InitNet_1_NpWebApi2(&symbols);
|
||||||
|
const auto find = [&](const char *nid) {
|
||||||
|
const auto *symbol = symbols.FindByNid(nid, Loader::SymbolType::Func);
|
||||||
|
Check(symbol != nullptr, "NpWebApi2 library and memory exports resolve");
|
||||||
|
return symbol->vaddr;
|
||||||
|
};
|
||||||
|
struct Stats { size_t pool, maximum, current; int32_t reserved; };
|
||||||
|
static_assert(sizeof(Stats) == 32 && offsetof(Stats, reserved) == 24);
|
||||||
|
using Initialize = int (KYTY_SYSV_ABI *)(int, size_t);
|
||||||
|
using GetStats = int (KYTY_SYSV_ABI *)(int, Stats *);
|
||||||
|
using Terminate = int (KYTY_SYSV_ABI *)(int);
|
||||||
|
const auto initialize = reinterpret_cast<Initialize>(find("+o9816YQhqQ"));
|
||||||
|
const auto get_stats = reinterpret_cast<GetStats>(find("Xweb+naPZ8Y"));
|
||||||
|
const auto terminate = reinterpret_cast<Terminate>(find("bEvXpcEk200"));
|
||||||
|
const int first = initialize(1, 65537);
|
||||||
|
const int second = initialize(1, 16384);
|
||||||
|
Stats stats {1, 2, 3, 4};
|
||||||
|
Check(first > 0 && second > 0 && first != second &&
|
||||||
|
get_stats(first, &stats) == OK && stats.pool == 81920 &&
|
||||||
|
stats.maximum == 0 && stats.current == 0 && stats.reserved == 0 &&
|
||||||
|
get_stats(second, &stats) == OK && stats.pool == 16384,
|
||||||
|
"NpWebApi2 statistics retain each context's rounded pool capacity");
|
||||||
|
Check(get_stats(first, nullptr) == static_cast<int32_t>(0x80553402) &&
|
||||||
|
get_stats(0, &stats) == static_cast<int32_t>(0x80553403) &&
|
||||||
|
initialize(1, std::numeric_limits<size_t>::max()) == static_cast<int32_t>(0x80553402),
|
||||||
|
"NpWebApi2 statistics validate output, context ID, and pool rounding");
|
||||||
|
Check(terminate(first) == OK &&
|
||||||
|
get_stats(first, &stats) == static_cast<int32_t>(0x80553404) &&
|
||||||
|
terminate(first) == static_cast<int32_t>(0x80553404) &&
|
||||||
|
terminate(-1) == static_cast<int32_t>(0x80553403) &&
|
||||||
|
get_stats(second, &stats) == OK && stats.pool == 16384 &&
|
||||||
|
terminate(second) == OK,
|
||||||
|
"NpWebApi2 termination removes only the selected library context");
|
||||||
|
}
|
||||||
|
|
||||||
void CheckMountRoot(const std::filesystem::path &root) {
|
void CheckMountRoot(const std::filesystem::path &root) {
|
||||||
Common::File cache;
|
Common::File cache;
|
||||||
Check(cache.Create(root / "rpf.cache"), "create directory listing fixture");
|
Check(cache.Create(root / "rpf.cache"), "create directory listing fixture");
|
||||||
@@ -921,6 +962,7 @@ int main(int, char**) {
|
|||||||
CheckSaveRename(temporary.Path(), "replacement-save");
|
CheckSaveRename(temporary.Path(), "replacement-save");
|
||||||
FileSystem::Shutdown();
|
FileSystem::Shutdown();
|
||||||
CheckSocketWakeup();
|
CheckSocketWakeup();
|
||||||
|
TestNpWebApi2Memory();
|
||||||
graphics.reset();
|
graphics.reset();
|
||||||
subsystems.Destroy();
|
subsystems.Destroy();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user