diff --git a/nx/include/switch/kernel/tmem.h b/nx/include/switch/kernel/tmem.h index a5993ea3..d0a28da1 100644 --- a/nx/include/switch/kernel/tmem.h +++ b/nx/include/switch/kernel/tmem.h @@ -72,9 +72,26 @@ static inline void* tmemGetAddr(TransferMemory* t){ return t->map_addr; } +/** + * @brief Closes handle of a transfer memory object. + * @param t Transfer memory information structure. + * @return Result code. + */ +Result tmemCloseHandle(TransferMemory* t); + + +/** + * @brief Waits until source backing memory permissions match perm. + * @param t Transfer memory information structure. + * @param perm Permissions which the source backing memory is expected to have before return. + * @return Result code. + */ +Result tmemWaitForPermission(TransferMemory* t, Permission perm); + + /** * @brief Frees up resources used by a transfer memory object, unmapping and closing handles, etc. * @param t Transfer memory information structure. * @return Result code. */ -Result tmemClose(TransferMemory* t); +Result tmemClose(TransferMemory* t); \ No newline at end of file diff --git a/nx/source/kernel/tmem.c b/nx/source/kernel/tmem.c index 8bdc1dd8..06a7f8c5 100644 --- a/nx/source/kernel/tmem.c +++ b/nx/source/kernel/tmem.c @@ -100,6 +100,45 @@ Result tmemUnmap(TransferMemory* t) return rc; } +Result tmemCloseHandle(TransferMemory* t) +{ + Result rc = 0; + + if (t->handle != INVALID_HANDLE) { + rc = svcCloseHandle(t->handle); + t->handle = INVALID_HANDLE; + } + + return rc; +} + +Result tmemWaitForPermission(TransferMemory* t, Permission perm) +{ + Result rc = 0; + + if ((t->perm & perm) != perm) { + MemoryInfo m = {0}; + u32 p = 0; + rc = svcQueryMemory(&m, &p, (u64)(t->src_addr)); + + if (R_FAILED(rc)) { + return rc; + } + + while ((m.perm & perm) != perm) { + rc = svcQueryMemory(&m, &p, (u64)(t->src_addr)); + + if (R_FAILED(rc)) { + return rc; + } + + svcSleepThread(100000); + } + } + + return rc; +} + Result tmemClose(TransferMemory* t) { Result rc = 0; @@ -114,21 +153,6 @@ Result tmemClose(TransferMemory* t) } if (t->src_addr != NULL) { - if ((t->perm & Perm_Rw) != Perm_Rw) { - MemoryInfo m = {0}; - u32 p = 0; - rc = svcQueryMemory(&m, &p, (u64)(t->src_addr)); - if (R_FAILED(rc)) { - return rc; - } - while ((m.perm & Perm_Rw) != Perm_Rw) { - rc = svcQueryMemory(&m, &p, (u64)(t->src_addr)); - if (R_FAILED(rc)) { - return rc; - } - svcSleepThread(100000); - } - } __libnx_free(t->src_addr); } @@ -137,4 +161,4 @@ Result tmemClose(TransferMemory* t) } return rc; -} +} \ No newline at end of file diff --git a/nx/source/services/nv.c b/nx/source/services/nv.c index 037619ab..136ca901 100644 --- a/nx/source/services/nv.c +++ b/nx/source/services/nv.c @@ -54,6 +54,9 @@ Result _nvInitialize(void) { if (R_SUCCEEDED(rc)) rc = _nvCmdInitialize(CUR_PROCESS_HANDLE, g_nvTransfermem.handle, tmem_size); + + if (R_SUCCEEDED(rc)) + rc = tmemCloseHandle(&g_nvTransfermem); // Clone the session handle - the cloned session is used to execute certain commands in parallel if (R_SUCCEEDED(rc)) @@ -73,6 +76,7 @@ Result _nvInitialize(void) { void _nvCleanup(void) { serviceClose(&g_nvSrvClone); serviceClose(&g_nvSrv); + tmemWaitForPermission(&g_nvTransfermem, Perm_Rw); tmemClose(&g_nvTransfermem); }