diff --git a/nx/source/services/nv.c b/nx/source/services/nv.c index f3240bff..85c43562 100644 --- a/nx/source/services/nv.c +++ b/nx/source/services/nv.c @@ -1,34 +1,26 @@ #define NX_SERVICE_ASSUME_NON_DOMAIN #include -#include "types.h" -#include "result.h" -#include "arm/atomics.h" +#include "service_guard.h" #include "kernel/tmem.h" -#include "sf/service.h" #include "services/applet.h" -#include "nvidia/ioctl.h" #include "services/nv.h" -#include "services/sm.h" +#include "nvidia/ioctl.h" __attribute__((weak)) u32 __nx_nv_transfermem_size = 0x800000; static Service g_nvSrv; static Service g_nvSrvClone; -static u64 g_refCnt; static size_t g_nvIpcBufferSize = 0; static TransferMemory g_nvTransfermem; -static Result _nvInitialize(Handle proc, Handle sharedmem, u32 transfermem_size); +static Result _nvCmdInitialize(Handle proc, Handle sharedmem, u32 transfermem_size); static Result _nvSetClientPID(u64 AppletResourceUserId); -Result nvInitialize(void) +NX_GENERATE_SERVICE_GUARD(nv); + +Result _nvInitialize(void) { - atomicIncrement64(&g_refCnt); - - if (serviceIsActive(&g_nvSrv)) - return 0; - Result rc = 0; u64 AppletResourceUserId = 0; @@ -58,7 +50,7 @@ Result nvInitialize(void) rc = tmemCreate(&g_nvTransfermem, __nx_nv_transfermem_size, Perm_None); if (R_SUCCEEDED(rc)) - rc = _nvInitialize(CUR_PROCESS_HANDLE, g_nvTransfermem.handle, __nx_nv_transfermem_size); + rc = _nvCmdInitialize(CUR_PROCESS_HANDLE, g_nvTransfermem.handle, __nx_nv_transfermem_size); // Clone the session handle - the cloned session is used to execute certain commands in parallel if (R_SUCCEEDED(rc)) @@ -80,16 +72,14 @@ Result nvInitialize(void) return rc; } -void nvExit(void) +void _nvCleanup(void) { - if (atomicDecrement64(&g_refCnt) == 0) { - serviceClose(&g_nvSrvClone); - serviceClose(&g_nvSrv); - tmemClose(&g_nvTransfermem); - } + serviceClose(&g_nvSrvClone); + serviceClose(&g_nvSrv); + tmemClose(&g_nvTransfermem); } -static Result _nvInitialize(Handle proc, Handle sharedmem, u32 transfermem_size) +static Result _nvCmdInitialize(Handle proc, Handle sharedmem, u32 transfermem_size) { return serviceDispatchIn(&g_nvSrv, 3, transfermem_size, .in_num_handles = 2, diff --git a/nx/source/services/service_guard.h b/nx/source/services/service_guard.h new file mode 100644 index 00000000..03c68e9b --- /dev/null +++ b/nx/source/services/service_guard.h @@ -0,0 +1,58 @@ +#pragma once +#include "types.h" +#include "result.h" +#include "kernel/mutex.h" +#include "sf/service.h" +#include "services/sm.h" + +typedef struct ServiceGuard +{ + Mutex mutex; + u32 refCount; +} ServiceGuard; + +NX_INLINE bool serviceGuardBeginInit(ServiceGuard* g) +{ + mutexLock(&g->mutex); + return (g->refCount++) == 0; +} + +NX_INLINE Result serviceGuardEndInit(ServiceGuard* g, Result rc, void (*cleanupFunc)(void)) +{ + if (R_FAILED(rc)) + { + cleanupFunc(); + --g->refCount; + } + mutexUnlock(&g->mutex); + return rc; +} + +NX_INLINE void serviceGuardExit(ServiceGuard* g, void (*cleanupFunc)(void)) +{ + mutexLock(&g->mutex); + if (g->refCount && (--g->refCount) == 0) + cleanupFunc(); + mutexUnlock(&g->mutex); +} + +#define NX_GENERATE_SERVICE_GUARD_PARAMS(name, _paramdecl, _parampass) \ +\ +static ServiceGuard g_##name##Guard; \ +NX_INLINE Result _##name##Initialize _paramdecl; \ +static void _##name##Cleanup(void); \ +\ +Result name##Initialize _paramdecl \ +{ \ + Result rc = 0; \ + if (serviceGuardBeginInit(&g_##name##Guard)) \ + rc = _##name##Initialize _parampass; \ + return serviceGuardEndInit(&g_##name##Guard, rc, _##name##Cleanup); \ +} \ +\ +void name##Exit(void) \ +{ \ + serviceGuardExit(&g_##name##Guard, _##name##Cleanup); \ +} + +#define NX_GENERATE_SERVICE_GUARD(name) NX_GENERATE_SERVICE_GUARD_PARAMS(name, (void), ()) diff --git a/nx/source/services/sm.c b/nx/source/services/sm.c index daa329b0..3a0eac43 100644 --- a/nx/source/services/sm.c +++ b/nx/source/services/sm.c @@ -1,14 +1,9 @@ // Copyright 2017 plutoo #define NX_SERVICE_ASSUME_NON_DOMAIN -#include "types.h" -#include "result.h" -#include "arm/atomics.h" -#include "sf/service.h" +#include "service_guard.h" #include "services/fatal.h" -#include "services/sm.h" static Service g_smSrv; -static u64 g_refCnt; #define MAX_OVERRIDES 32 @@ -45,14 +40,10 @@ Handle smGetServiceOverride(u64 name) return INVALID_HANDLE; } +NX_GENERATE_SERVICE_GUARD(sm); -Result smInitialize(void) +Result _smInitialize(void) { - atomicIncrement64(&g_refCnt); - - if (smHasInitialized()) - return 0; - Handle sm_handle; Result rc = svcConnectToNamedPort(&sm_handle, "sm:"); while (R_VALUE(rc) == KERNELRESULT(NotFound)) { @@ -73,18 +64,12 @@ Result smInitialize(void) rc = serviceDispatchIn(&g_smSrv, 0, in, .in_send_pid = true); } - if (R_FAILED(rc)) - smExit(); - return rc; } -void smExit(void) +void _smCleanup(void) { - if (atomicDecrement64(&g_refCnt) == 0) - { - serviceClose(&g_smSrv); - } + serviceClose(&g_smSrv); } Service *smGetServiceSession(void)