mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
Add internal service guard helper, needed for proper thread safe service init/exit
This commit is contained in:
parent
c3b920d210
commit
5ab1219f40
@ -1,34 +1,26 @@
|
||||
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
||||
#include <string.h>
|
||||
#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,
|
||||
|
58
nx/source/services/service_guard.h
Normal file
58
nx/source/services/service_guard.h
Normal file
@ -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), ())
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user