diff --git a/nx/include/switch/arm/atomics.h b/nx/include/switch/arm/atomics.h new file mode 100644 index 00000000..a1999104 --- /dev/null +++ b/nx/include/switch/arm/atomics.h @@ -0,0 +1,6 @@ +#include "../types.h" + +u32 atomicIncrement32(u32* p); +u32 atomicDecrement32(u32* p); +u64 atomicIncrement64(u64* p); +u64 atomicDecrement64(u64* p); diff --git a/nx/include/switch/services/pm.h b/nx/include/switch/services/pm.h index a0af0c42..6a1c8e3c 100644 --- a/nx/include/switch/services/pm.h +++ b/nx/include/switch/services/pm.h @@ -8,6 +8,8 @@ #include "../types.h" Result pmdmntInitialize(void); +void pmdmntExit(void); + Result pmdmntStartProcess(u64 pid); Result pmdmntGetTitlePid(u64* pid_out, u64 title_id); Result pmdmntEnableDebugForTitleId(Handle* handle_out, u64 title_id); diff --git a/nx/source/arm/atomics.c b/nx/source/arm/atomics.c new file mode 100644 index 00000000..c05c863d --- /dev/null +++ b/nx/source/arm/atomics.c @@ -0,0 +1,17 @@ +#include "types.h" + +u32 atomicIncrement32(u32* p) { + return __sync_fetch_and_add(p, 1); +} + +u32 atomicDecrement32(u32* p) { + return __sync_sub_and_fetch(p, 1); +} + +u64 atomicIncrement64(u64* p) { + return __sync_fetch_and_add(p, 1); +} + +u64 atomicDecrement64(u64* p) { + return __sync_sub_and_fetch(p, 1); +} diff --git a/nx/source/services/acc.c b/nx/source/services/acc.c index 7a7787c4..49050b62 100644 --- a/nx/source/services/acc.c +++ b/nx/source/services/acc.c @@ -1,19 +1,25 @@ #include "types.h" +#include "arm/atomics.h" #include "services/acc.h" #include "services/sm.h" static Service g_accSrv; +static u64 g_refCnt; Result accountInitialize(void) { + atomicIncrement64(&g_refCnt); + if (serviceIsActive(&g_accSrv)) - return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); + return 0; return smGetService(&g_accSrv, "acc:u1"); } -void accountExit(void) { - serviceClose(&g_accSrv); +void accountExit(void) +{ + if (atomicDecrement64(&g_refCnt) == 0) + serviceClose(&g_accSrv); } Service* accountGetService(void) { diff --git a/nx/source/services/apm.c b/nx/source/services/apm.c index 6cb5e578..00ae5c88 100644 --- a/nx/source/services/apm.c +++ b/nx/source/services/apm.c @@ -1,18 +1,22 @@ #include "types.h" #include "result.h" +#include "arm/atomics.h" #include "kernel/ipc.h" #include "services/apm.h" #include "services/sm.h" static Service g_apmSrv; static Service g_apmISession; +static u64 g_refCnt; static Result _apmGetSession(Service* srv, Service* srv_out, u64 cmd_id); Result apmInitialize(void) { + atomicIncrement64(&g_refCnt); + if (serviceIsActive(&g_apmSrv)) - return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); + return 0; Result rc = 0; @@ -34,8 +38,10 @@ Result apmInitialize(void) void apmExit(void) { - serviceClose(&g_apmISession); - serviceClose(&g_apmSrv); + if (atomicDecrement64(&g_refCnt) == 0) { + serviceClose(&g_apmISession); + serviceClose(&g_apmSrv); + } } static Result _apmGetSession(Service* srv, Service* srv_out, u64 cmd_id) { diff --git a/nx/source/services/applet.c b/nx/source/services/applet.c index d2e41d9f..94ec34a7 100644 --- a/nx/source/services/applet.c +++ b/nx/source/services/applet.c @@ -1,12 +1,13 @@ #include #include "types.h" #include "result.h" +#include "arm/atomics.h" #include "kernel/ipc.h" +#include "kernel/detect.h" #include "services/fatal.h" #include "services/applet.h" #include "services/apm.h" #include "services/sm.h" -#include "kernel/detect.h" __attribute__((weak)) u32 __nx_applet_type = AppletType_Default; __attribute__((weak)) bool __nx_applet_auto_notifyrunning = true; @@ -15,6 +16,7 @@ __attribute__((weak)) u32 __nx_applet_PerformanceConfiguration[2] = {/*0x9222000 static Service g_appletSrv; static Service g_appletProxySession; +static u64 g_refCnt; // From Get*Functions. static Service g_appletIFunctions; @@ -69,8 +71,10 @@ static Result _appletSetPerformanceModeChangedNotification(u8 flag); Result appletInitialize(void) { + atomicIncrement64(&g_refCnt); + if (serviceIsActive(&g_appletSrv)) - return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); + return 0; if (__nx_applet_type == AppletType_None) return 0; @@ -234,36 +238,39 @@ Result appletInitialize(void) void appletExit(void) { - apmExit(); + if (atomicDecrement64(&g_refCnt) == 0) + { + apmExit(); - //TODO: Enable this somehow later with more condition(s)? - /*if (__nx_applet_type == AppletType_LibraryApplet) - _appletExitProcessAndReturn();*/ + //TODO: Enable this somehow later with more condition(s)? + /*if (__nx_applet_type == AppletType_LibraryApplet) + _appletExitProcessAndReturn();*/ - if (g_appletMessageEventHandle != INVALID_HANDLE) { - svcCloseHandle(g_appletMessageEventHandle); - g_appletMessageEventHandle = INVALID_HANDLE; + if (g_appletMessageEventHandle != INVALID_HANDLE) { + svcCloseHandle(g_appletMessageEventHandle); + g_appletMessageEventHandle = INVALID_HANDLE; + } + + serviceClose(&g_appletIDebugFunctions); + serviceClose(&g_appletIDisplayController); + serviceClose(&g_appletIAudioController); + serviceClose(&g_appletIWindowController); + serviceClose(&g_appletISelfController); + serviceClose(&g_appletICommonStateGetter); + serviceClose(&g_appletILibraryAppletCreator); + + if (__nx_applet_type != AppletType_LibraryApplet) + serviceClose(&g_appletIFunctions); + + if (__nx_applet_type == AppletType_LibraryApplet) { + serviceClose(&g_appletIProcessWindingController); + serviceClose(&g_appletILibraryAppletSelfAccessor); + } + + serviceClose(&g_appletProxySession); + serviceClose(&g_appletSrv); + g_appletResourceUserId = 0; } - - serviceClose(&g_appletIDebugFunctions); - serviceClose(&g_appletIDisplayController); - serviceClose(&g_appletIAudioController); - serviceClose(&g_appletIWindowController); - serviceClose(&g_appletISelfController); - serviceClose(&g_appletICommonStateGetter); - serviceClose(&g_appletILibraryAppletCreator); - - if (__nx_applet_type != AppletType_LibraryApplet) - serviceClose(&g_appletIFunctions); - - if (__nx_applet_type == AppletType_LibraryApplet) { - serviceClose(&g_appletIProcessWindingController); - serviceClose(&g_appletILibraryAppletSelfAccessor); - } - - serviceClose(&g_appletProxySession); - serviceClose(&g_appletSrv); - g_appletResourceUserId = 0; } static void appletCallHook(AppletHookType hookType) diff --git a/nx/source/services/audin.c b/nx/source/services/audin.c index 5b2c6abc..1b018c7a 100644 --- a/nx/source/services/audin.c +++ b/nx/source/services/audin.c @@ -1,6 +1,7 @@ #include #include "types.h" #include "result.h" +#include "arm/atomics.h" #include "kernel/ipc.h" #include "services/audin.h" #include "services/sm.h" @@ -11,6 +12,7 @@ static Service g_audinSrv; static Service g_audinIAudioIn; +static u64 g_refCnt; static Handle g_audinBufferEventHandle = INVALID_HANDLE; @@ -23,8 +25,10 @@ static Result _audinRegisterBufferEvent(Handle *BufferEvent); Result audinInitialize(void) { + atomicIncrement64(&g_refCnt); + if (serviceIsActive(&g_audinSrv)) - return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); + return 0; Result rc = 0; rc = smGetService(&g_audinSrv, "audin:u"); @@ -52,18 +56,21 @@ Result audinInitialize(void) void audinExit(void) { - if (g_audinBufferEventHandle != INVALID_HANDLE) { - svcCloseHandle(g_audinBufferEventHandle); - g_audinBufferEventHandle = INVALID_HANDLE; + if (atomicDecrement64(&g_refCnt) == 0) + { + if (g_audinBufferEventHandle != INVALID_HANDLE) { + svcCloseHandle(g_audinBufferEventHandle); + g_audinBufferEventHandle = INVALID_HANDLE; + } + + g_sampleRate = 0; + g_channelCount = 0; + g_pcmFormat = PcmFormat_Invalid; + g_deviceState = AudioInState_Stopped; + + serviceClose(&g_audinIAudioIn); + serviceClose(&g_audinSrv); } - - g_sampleRate = 0; - g_channelCount = 0; - g_pcmFormat = PcmFormat_Invalid; - g_deviceState = AudioInState_Stopped; - - serviceClose(&g_audinIAudioIn); - serviceClose(&g_audinSrv); } u32 audinGetSampleRate(void) { diff --git a/nx/source/services/audout.c b/nx/source/services/audout.c index bd12e900..4fde7f3c 100644 --- a/nx/source/services/audout.c +++ b/nx/source/services/audout.c @@ -1,6 +1,7 @@ #include #include "types.h" #include "result.h" +#include "arm/atomics.h" #include "kernel/ipc.h" #include "services/audout.h" #include "services/sm.h" @@ -11,6 +12,7 @@ static Service g_audoutSrv; static Service g_audoutIAudioOut; +static u64 g_refCnt; static Handle g_audoutBufferEventHandle = INVALID_HANDLE; @@ -23,8 +25,10 @@ static Result _audoutRegisterBufferEvent(Handle *BufferEvent); Result audoutInitialize(void) { + atomicIncrement64(&g_refCnt); + if (serviceIsActive(&g_audoutSrv)) - return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); + return 0; Result rc = 0; rc = smGetService(&g_audoutSrv, "audout:u"); @@ -52,18 +56,21 @@ Result audoutInitialize(void) void audoutExit(void) { - if (g_audoutBufferEventHandle != INVALID_HANDLE) { - svcCloseHandle(g_audoutBufferEventHandle); - g_audoutBufferEventHandle = INVALID_HANDLE; + if (atomicDecrement64(&g_refCnt) == 0) + { + if (g_audoutBufferEventHandle != INVALID_HANDLE) { + svcCloseHandle(g_audoutBufferEventHandle); + g_audoutBufferEventHandle = INVALID_HANDLE; + } + + g_sampleRate = 0; + g_channelCount = 0; + g_pcmFormat = PcmFormat_Invalid; + g_deviceState = AudioOutState_Stopped; + + serviceClose(&g_audoutIAudioOut); + serviceClose(&g_audoutSrv); } - - g_sampleRate = 0; - g_channelCount = 0; - g_pcmFormat = PcmFormat_Invalid; - g_deviceState = AudioOutState_Stopped; - - serviceClose(&g_audoutIAudioOut); - serviceClose(&g_audoutSrv); } u32 audoutGetSampleRate(void) { diff --git a/nx/source/services/fs.c b/nx/source/services/fs.c index 0b81e196..22634b72 100644 --- a/nx/source/services/fs.c +++ b/nx/source/services/fs.c @@ -2,13 +2,18 @@ #include #include "types.h" #include "result.h" +#include "arm/atomics.h" #include "kernel/ipc.h" #include "services/fs.h" #include "services/sm.h" static Service g_fsSrv; +static u64 g_refCnt; + +Result fsInitialize(void) +{ + atomicIncrement64(&g_refCnt); -Result fsInitialize(void) { if (serviceIsActive(&g_fsSrv)) return 0; @@ -49,8 +54,10 @@ Result fsInitialize(void) { return rc; } -void fsExit(void) { - serviceClose(&g_fsSrv); +void fsExit(void) +{ + if (atomicDecrement64(&g_refCnt) == 0) + serviceClose(&g_fsSrv); } Service* fsGetServiceSession(void) { diff --git a/nx/source/services/hid.c b/nx/source/services/hid.c index 3cca0303..24d5e77c 100644 --- a/nx/source/services/hid.c +++ b/nx/source/services/hid.c @@ -1,15 +1,17 @@ #include #include "types.h" #include "result.h" +#include "arm/atomics.h" #include "kernel/ipc.h" +#include "kernel/shmem.h" +#include "kernel/rwlock.h" #include "services/applet.h" #include "services/hid.h" #include "services/sm.h" -#include "kernel/shmem.h" -#include "kernel/rwlock.h" static Service g_hidSrv; static Service g_hidIAppletResource; +static u64 g_refCnt; static SharedMemory g_hidSharedmem; static HidTouchScreenEntry g_touchEntry; @@ -36,8 +38,10 @@ static Result _hidSetDualModeAll(void); Result hidInitialize(void) { + atomicIncrement64(&g_refCnt); + if (serviceIsActive(&g_hidSrv)) - return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); + return 0; Result rc; Handle sharedmem_handle; @@ -75,14 +79,14 @@ Result hidInitialize(void) void hidExit(void) { - if (!serviceIsActive(&g_hidSrv)) - return; + if (atomicDecrement64(&g_refCnt) == 0) + { + _hidSetDualModeAll(); - _hidSetDualModeAll(); - - serviceClose(&g_hidIAppletResource); - serviceClose(&g_hidSrv); - shmemClose(&g_hidSharedmem); + serviceClose(&g_hidIAppletResource); + serviceClose(&g_hidSrv); + shmemClose(&g_hidSharedmem); + } } void hidReset(void) @@ -367,7 +371,7 @@ void hidJoystickRead(JoystickPosition *pos, HidControllerID id, HidControllerJoy } static Result _hidSetDualModeAll(void) { - Result rc=0; + Result rc; int i; for (i=0; i<8; i++) { diff --git a/nx/source/services/irs.c b/nx/source/services/irs.c index 18c8a4a6..9cfb03eb 100644 --- a/nx/source/services/irs.c +++ b/nx/source/services/irs.c @@ -1,6 +1,7 @@ #include #include "types.h" #include "result.h" +#include "arm/atomics.h" #include "kernel/ipc.h" #include "kernel/shmem.h" #include "kernel/tmem.h" @@ -16,6 +17,7 @@ typedef struct { } irsCameraEntry; static Service g_irsSrv; +static u64 g_refCnt; static SharedMemory g_irsSharedmem; static bool g_irsSensorActivated; @@ -25,8 +27,10 @@ static Result _irsGetIrsensorSharedMemoryHandle(Handle* handle_out, u64 AppletRe Result irsInitialize(void) { + atomicIncrement64(&g_refCnt); + if (serviceIsActive(&g_irsSrv)) - return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); + return 0; Result rc; Handle sharedmem_handle; @@ -60,20 +64,23 @@ Result irsInitialize(void) void irsExit(void) { - int i; - size_t entrycount = sizeof(g_irsCameras)/sizeof(irsCameraEntry); - irsCameraEntry *entry; + if (atomicDecrement64(&g_refCnt) == 0) + { + size_t entrycount = sizeof(g_irsCameras)/sizeof(irsCameraEntry); + irsCameraEntry *entry; - for(i=0; iinitialized) continue; - irsStopImageProcessor(entry->IrCameraHandle); + int i; + for(i=0; iinitialized) continue; + irsStopImageProcessor(entry->IrCameraHandle); + } + + irsActivateIrsensor(0); + + serviceClose(&g_irsSrv); + shmemClose(&g_irsSharedmem); } - - irsActivateIrsensor(0); - - serviceClose(&g_irsSrv); - shmemClose(&g_irsSharedmem); } static Result _irsCameraEntryAlloc(u32 IrCameraHandle, irsCameraEntry **out_entry) { diff --git a/nx/source/services/nv.c b/nx/source/services/nv.c index 980ef684..7234ccfe 100644 --- a/nx/source/services/nv.c +++ b/nx/source/services/nv.c @@ -18,7 +18,7 @@ static Result _nvSetClientPID(u64 AppletResourceUserId); Result nvInitialize(nvServiceType servicetype, size_t transfermem_size) { - if(g_nvServiceType!=-1) + if (g_nvServiceType != -1) return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); Result rc = 0; @@ -70,7 +70,7 @@ Result nvInitialize(nvServiceType servicetype, size_t transfermem_size) void nvExit(void) { - if(g_nvServiceType == -1) + if (g_nvServiceType == -1) return; g_nvServiceType = -1; diff --git a/nx/source/services/pm.c b/nx/source/services/pm.c index b781e53b..073a6802 100644 --- a/nx/source/services/pm.c +++ b/nx/source/services/pm.c @@ -1,16 +1,31 @@ // Copyright 2017 plutoo #include "types.h" #include "result.h" +#include "arm/atomics.h" #include "kernel/ipc.h" #include "services/pm.h" #include "services/sm.h" static Service g_pmdmntSrv; +static u64 g_refCnt; + +Result pmdmntInitialize(void) +{ + atomicIncrement64(&g_refCnt); + + if (serviceIsActive(&g_pmdmntSrv)) + return 0; -Result pmdmntInitialize(void) { return smGetService(&g_pmdmntSrv, "pm:dmnt"); } +void pmdmntExit(void) +{ + if (atomicDecrement64(&g_refCnt) == 0) { + serviceClose(&g_pmdmntSrv); + } +} + Result pmdmntStartProcess(u64 pid) { IpcCommand c; ipcInitialize(&c); diff --git a/nx/source/services/set.c b/nx/source/services/set.c index e5130249..ae66fad0 100644 --- a/nx/source/services/set.c +++ b/nx/source/services/set.c @@ -7,6 +7,7 @@ */ #include "types.h" #include "result.h" +#include "arm/atomics.h" #include "kernel/ipc.h" #include "kernel/detect.h" #include "services/set.h" @@ -15,6 +16,8 @@ static Service g_setSrv; static Service g_setsysSrv; +static u64 g_refCnt; +static u64 g_refCntSys; static bool g_setLanguageCodesInitialized; static u64 g_setLanguageCodes[0x40]; @@ -24,8 +27,10 @@ static Result _setMakeLanguageCode(s32 Language, u64 *LanguageCode); Result setInitialize(void) { + atomicIncrement64(&g_refCnt); + if (serviceIsActive(&g_setSrv)) - return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); + return 0; g_setLanguageCodesInitialized = 0; @@ -34,11 +39,15 @@ Result setInitialize(void) void setExit(void) { - serviceClose(&g_setSrv); + if (atomicDecrement64(&g_refCnt) == 0) { + serviceClose(&g_setSrv); + } } Result setsysInitialize(void) { + atomicIncrement64(&g_refCntSys); + if (serviceIsActive(&g_setsysSrv)) return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); @@ -47,7 +56,9 @@ Result setsysInitialize(void) void setsysExit(void) { - serviceClose(&g_setsysSrv); + if (atomicDecrement64(&g_refCntSys) == 0) { + serviceClose(&g_setsysSrv); + } } static Result setInitializeLanguageCodesCache(void) { diff --git a/nx/source/services/sm.c b/nx/source/services/sm.c index 00472e1a..43c71ca1 100644 --- a/nx/source/services/sm.c +++ b/nx/source/services/sm.c @@ -1,11 +1,13 @@ // Copyright 2017 plutoo #include "types.h" #include "result.h" +#include "arm/atomics.h" #include "kernel/ipc.h" #include "services/fatal.h" #include "services/sm.h" static Handle g_smHandle = INVALID_HANDLE; +static u64 g_refCnt; #define MAX_OVERRIDES 32 @@ -48,6 +50,8 @@ bool smHasInitialized(void) { Result smInitialize(void) { + atomicIncrement64(&g_refCnt); + if (smHasInitialized()) return 0; @@ -93,9 +97,12 @@ Result smInitialize(void) return rc; } -void smExit(void) { - svcCloseHandle(g_smHandle); - g_smHandle = INVALID_HANDLE; +void smExit(void) +{ + if (atomicDecrement64(&g_refCnt) == 0) { + svcCloseHandle(g_smHandle); + g_smHandle = INVALID_HANDLE; + } } u64 smEncodeName(const char* name) diff --git a/nx/source/services/time.c b/nx/source/services/time.c index 4f65cd9c..e710e993 100644 --- a/nx/source/services/time.c +++ b/nx/source/services/time.c @@ -1,6 +1,7 @@ #include #include "types.h" #include "result.h" +#include "arm/atomics.h" #include "kernel/ipc.h" #include "services/time.h" #include "services/sm.h" @@ -10,13 +11,16 @@ static Service g_timeUserSystemClock; static Service g_timeNetworkSystemClock; static Service g_timeTimeZoneService; static Service g_timeLocalSystemClock; +static u64 g_refCnt; static Result _timeGetSession(Service* srv_out, u64 cmd_id); Result timeInitialize(void) { + atomicIncrement64(&g_refCnt); + if (serviceIsActive(&g_timeSrv)) - return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); + return 0; Result rc; @@ -46,14 +50,14 @@ Result timeInitialize(void) void timeExit(void) { - if (!serviceIsActive(&g_timeSrv)) - return; - - serviceClose(&g_timeLocalSystemClock); - serviceClose(&g_timeTimeZoneService); - serviceClose(&g_timeNetworkSystemClock); - serviceClose(&g_timeUserSystemClock); - serviceClose(&g_timeSrv); + if (atomicDecrement64(&g_refCnt) == 0) + { + serviceClose(&g_timeLocalSystemClock); + serviceClose(&g_timeTimeZoneService); + serviceClose(&g_timeNetworkSystemClock); + serviceClose(&g_timeUserSystemClock); + serviceClose(&g_timeSrv); + } } Service* timeGetSessionService(void) { diff --git a/nx/source/services/usb.c b/nx/source/services/usb.c index 6cd913a9..41050780 100644 --- a/nx/source/services/usb.c +++ b/nx/source/services/usb.c @@ -25,7 +25,8 @@ static Result _usbDsSetVidPidBcd(const usbDsDeviceInfo* deviceinfo); static Result _usbDsGetSession(Service* srv, Service* srv_out, u64 cmd_id, const void* buf0, size_t buf0size, const void* buf1, size_t buf1size); -Result usbDsInitialize(UsbComplexId complexId, const usbDsDeviceInfo* deviceinfo) { +Result usbDsInitialize(UsbComplexId complexId, const usbDsDeviceInfo* deviceinfo) +{ if (serviceIsActive(&g_usbDsSrv)) return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized);