mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
Introduce SessionMgr for managing multiplexed services; change fs to use it
This commit is contained in:
parent
051ad2dc60
commit
bc13692938
@ -24,7 +24,7 @@ VERSION := $(LIBNX_MAJOR).$(LIBNX_MINOR).$(LIBNX_PATCH)
|
|||||||
#---------------------------------------------------------------------------------
|
#---------------------------------------------------------------------------------
|
||||||
TARGET := nx
|
TARGET := nx
|
||||||
#BUILD := build
|
#BUILD := build
|
||||||
SOURCES := source/arm source/kernel source/services source/crypto source/nvidia source/nvidia/ioctl source/display source/audio source/applets source/runtime source/runtime/devices source/runtime/util/utf
|
SOURCES := source/arm source/kernel source/sf source/services source/crypto source/nvidia source/nvidia/ioctl source/display source/audio source/applets source/runtime source/runtime/devices source/runtime/util/utf
|
||||||
DATA := data
|
DATA := data
|
||||||
INCLUDES := include external/bsd/include
|
INCLUDES := include external/bsd/include
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ extern "C" {
|
|||||||
#include "switch/sf/hipc.h"
|
#include "switch/sf/hipc.h"
|
||||||
#include "switch/sf/cmif.h"
|
#include "switch/sf/cmif.h"
|
||||||
#include "switch/sf/service.h"
|
#include "switch/sf/service.h"
|
||||||
|
#include "switch/sf/sessionmgr.h"
|
||||||
|
|
||||||
#include "switch/services/sm.h"
|
#include "switch/services/sm.h"
|
||||||
#include "switch/services/smm.h"
|
#include "switch/services/smm.h"
|
||||||
|
26
nx/include/switch/sf/sessionmgr.h
Normal file
26
nx/include/switch/sf/sessionmgr.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "../types.h"
|
||||||
|
#include "../kernel/mutex.h"
|
||||||
|
#include "../kernel/condvar.h"
|
||||||
|
|
||||||
|
#define NX_SESSION_MGR_MAX_SESSIONS 16
|
||||||
|
|
||||||
|
typedef struct SessionMgr
|
||||||
|
{
|
||||||
|
Handle sessions[NX_SESSION_MGR_MAX_SESSIONS];
|
||||||
|
u32 num_sessions;
|
||||||
|
u32 free_mask;
|
||||||
|
Mutex mutex;
|
||||||
|
CondVar condvar;
|
||||||
|
bool is_waiting;
|
||||||
|
} SessionMgr;
|
||||||
|
|
||||||
|
Result sessionmgrCreate(SessionMgr* mgr, Handle root_session, u32 num_sessions);
|
||||||
|
void sessionmgrClose(SessionMgr* mgr);
|
||||||
|
int sessionmgrAttachClient(SessionMgr* mgr);
|
||||||
|
void sessionmgrDetachClient(SessionMgr* mgr, int slot);
|
||||||
|
|
||||||
|
NX_CONSTEXPR Handle sessionmgrGetClientSession(SessionMgr* mgr, int slot)
|
||||||
|
{
|
||||||
|
return mgr->sessions[slot];
|
||||||
|
}
|
@ -1,52 +1,18 @@
|
|||||||
// Copyright 2017 plutoo
|
// Copyright 2017 plutoo
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "service_guard.h"
|
#include "service_guard.h"
|
||||||
#include "kernel/mutex.h"
|
#include "sf/sessionmgr.h"
|
||||||
#include "kernel/condvar.h"
|
|
||||||
#include "runtime/hosversion.h"
|
#include "runtime/hosversion.h"
|
||||||
#include "services/fs.h"
|
#include "services/fs.h"
|
||||||
#include "services/acc.h"
|
#include "services/acc.h"
|
||||||
|
|
||||||
#define FS_MAX_SESSIONS 8
|
|
||||||
|
|
||||||
__attribute__((weak)) u32 __nx_fs_num_sessions = 3;
|
__attribute__((weak)) u32 __nx_fs_num_sessions = 3;
|
||||||
|
|
||||||
static Service g_fsSrv;
|
static Service g_fsSrv;
|
||||||
|
static SessionMgr g_fsSessionMgr;
|
||||||
static Handle g_fsSessions[FS_MAX_SESSIONS];
|
|
||||||
static u32 g_fsSessionFreeMask;
|
|
||||||
static Mutex g_fsSessionMutex;
|
|
||||||
static CondVar g_fsSessionCondVar;
|
|
||||||
static bool g_fsSessionWaiting;
|
|
||||||
|
|
||||||
static __thread u32 g_fsPriority = FsPriority_Normal;
|
static __thread u32 g_fsPriority = FsPriority_Normal;
|
||||||
|
|
||||||
static int _fsGetSessionSlot(void)
|
|
||||||
{
|
|
||||||
mutexLock(&g_fsSessionMutex);
|
|
||||||
int slot;
|
|
||||||
for (;;) {
|
|
||||||
slot = __builtin_ffs(g_fsSessionFreeMask)-1;
|
|
||||||
if (slot >= 0) break;
|
|
||||||
g_fsSessionWaiting = true;
|
|
||||||
condvarWait(&g_fsSessionCondVar, &g_fsSessionMutex);
|
|
||||||
}
|
|
||||||
g_fsSessionFreeMask &= ~(1U << slot);
|
|
||||||
mutexUnlock(&g_fsSessionMutex);
|
|
||||||
return slot;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void _fsPutSessionSlot(int slot)
|
|
||||||
{
|
|
||||||
mutexLock(&g_fsSessionMutex);
|
|
||||||
g_fsSessionFreeMask |= 1U << slot;
|
|
||||||
if (g_fsSessionWaiting) {
|
|
||||||
g_fsSessionWaiting = false;
|
|
||||||
condvarWakeOne(&g_fsSessionCondVar);
|
|
||||||
}
|
|
||||||
mutexUnlock(&g_fsSessionMutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
NX_INLINE bool _fsObjectIsChild(Service* s)
|
NX_INLINE bool _fsObjectIsChild(Service* s)
|
||||||
{
|
{
|
||||||
return s->session == g_fsSrv.session;
|
return s->session == g_fsSrv.session;
|
||||||
@ -58,12 +24,12 @@ static void _fsObjectClose(Service* s)
|
|||||||
serviceClose(s);
|
serviceClose(s);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int slot = _fsGetSessionSlot();
|
int slot = sessionmgrAttachClient(&g_fsSessionMgr);
|
||||||
uint32_t object_id = serviceGetObjectId(s);
|
uint32_t object_id = serviceGetObjectId(s);
|
||||||
serviceAssumeDomain(s);
|
serviceAssumeDomain(s);
|
||||||
cmifMakeCloseRequest(armGetTls(), object_id);
|
cmifMakeCloseRequest(armGetTls(), object_id);
|
||||||
svcSendSyncRequest(g_fsSessions[slot]);
|
svcSendSyncRequest(sessionmgrGetClientSession(&g_fsSessionMgr, slot));
|
||||||
_fsPutSessionSlot(slot);
|
sessionmgrDetachClient(&g_fsSessionMgr, slot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,9 +41,9 @@ NX_INLINE Result _fsObjectDispatchImpl(
|
|||||||
) {
|
) {
|
||||||
int slot = -1;
|
int slot = -1;
|
||||||
if (_fsObjectIsChild(s)) {
|
if (_fsObjectIsChild(s)) {
|
||||||
slot = _fsGetSessionSlot();
|
slot = sessionmgrAttachClient(&g_fsSessionMgr);
|
||||||
if (slot < 0) __builtin_unreachable();
|
if (slot < 0) __builtin_unreachable();
|
||||||
disp.target_session = g_fsSessions[slot];
|
disp.target_session = sessionmgrGetClientSession(&g_fsSessionMgr, slot);
|
||||||
serviceAssumeDomain(s);
|
serviceAssumeDomain(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +51,7 @@ NX_INLINE Result _fsObjectDispatchImpl(
|
|||||||
Result rc = serviceDispatchImpl(s, request_id, in_data, in_data_size, out_data, out_data_size, disp);
|
Result rc = serviceDispatchImpl(s, request_id, in_data, in_data_size, out_data, out_data_size, disp);
|
||||||
|
|
||||||
if (slot >= 0) {
|
if (slot >= 0) {
|
||||||
_fsPutSessionSlot(slot);
|
sessionmgrDetachClient(&g_fsSessionMgr, slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@ -106,9 +72,6 @@ NX_INLINE Result _fsObjectDispatchImpl(
|
|||||||
NX_GENERATE_SERVICE_GUARD(fs);
|
NX_GENERATE_SERVICE_GUARD(fs);
|
||||||
|
|
||||||
Result _fsInitialize(void) {
|
Result _fsInitialize(void) {
|
||||||
if (__nx_fs_num_sessions < 1 || __nx_fs_num_sessions > FS_MAX_SESSIONS)
|
|
||||||
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
|
||||||
|
|
||||||
Result rc = smGetService(&g_fsSrv, "fsp-srv");
|
Result rc = smGetService(&g_fsSrv, "fsp-srv");
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
if (R_SUCCEEDED(rc)) {
|
||||||
@ -121,28 +84,15 @@ Result _fsInitialize(void) {
|
|||||||
rc = serviceDispatchIn(&g_fsSrv, 1, pid_placeholder, .in_send_pid = true);
|
rc = serviceDispatchIn(&g_fsSrv, 1, pid_placeholder, .in_send_pid = true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (R_SUCCEEDED(rc)) {
|
if (R_SUCCEEDED(rc))
|
||||||
g_fsSessionFreeMask = (1U << __nx_fs_num_sessions) - 1U;
|
rc = sessionmgrCreate(&g_fsSessionMgr, g_fsSrv.session, __nx_fs_num_sessions);
|
||||||
g_fsSessions[0] = g_fsSrv.session;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 1; R_SUCCEEDED(rc) && i < __nx_fs_num_sessions; i ++) {
|
|
||||||
rc = cmifCloneCurrentObject(g_fsSessions[0], &g_fsSessions[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _fsCleanup(void) {
|
void _fsCleanup(void) {
|
||||||
// Close extra sessions
|
// Close extra sessions
|
||||||
g_fsSessions[0] = INVALID_HANDLE;
|
sessionmgrClose(&g_fsSessionMgr);
|
||||||
for (u32 i = 1; i < __nx_fs_num_sessions; i ++) {
|
|
||||||
if (g_fsSessions[i] != INVALID_HANDLE) {
|
|
||||||
cmifMakeCloseRequest(armGetTls(), 0);
|
|
||||||
svcSendSyncRequest(g_fsSessions[i]);
|
|
||||||
g_fsSessions[i] = INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We can't assume g_fsSrv is a domain here because serviceConvertToDomain might have failed
|
// We can't assume g_fsSrv is a domain here because serviceConvertToDomain might have failed
|
||||||
serviceClose(&g_fsSrv);
|
serviceClose(&g_fsSrv);
|
||||||
|
61
nx/source/sf/sessionmgr.c
Normal file
61
nx/source/sf/sessionmgr.c
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "kernel/svc.h"
|
||||||
|
#include "sf/cmif.h"
|
||||||
|
#include "sf/sessionmgr.h"
|
||||||
|
|
||||||
|
Result sessionmgrCreate(SessionMgr* mgr, Handle root_session, u32 num_sessions) {
|
||||||
|
if (root_session == INVALID_HANDLE)
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||||
|
if (num_sessions < 1 || num_sessions > NX_SESSION_MGR_MAX_SESSIONS)
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_BadInput);
|
||||||
|
if (mgr->sessions[0] != INVALID_HANDLE)
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized);
|
||||||
|
|
||||||
|
__builtin_memset(mgr, 0, sizeof(*mgr));
|
||||||
|
mgr->sessions[0] = root_session;
|
||||||
|
mgr->num_sessions = num_sessions;
|
||||||
|
mgr->free_mask = (1U << num_sessions) - 1U;
|
||||||
|
|
||||||
|
Result rc = 0;
|
||||||
|
for (u32 i = 1; R_SUCCEEDED(rc) && i < num_sessions; i ++)
|
||||||
|
rc = cmifCloneCurrentObject(root_session, &mgr->sessions[i]);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sessionmgrClose(SessionMgr* mgr) {
|
||||||
|
if (mgr->sessions[0] == INVALID_HANDLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mgr->sessions[0] = INVALID_HANDLE;
|
||||||
|
for (u32 i = 1; i < mgr->num_sessions; i ++) {
|
||||||
|
if (mgr->sessions[i] != INVALID_HANDLE) {
|
||||||
|
cmifMakeCloseRequest(armGetTls(), 0);
|
||||||
|
svcSendSyncRequest(mgr->sessions[i]);
|
||||||
|
mgr->sessions[i] = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int sessionmgrAttachClient(SessionMgr* mgr) {
|
||||||
|
mutexLock(&mgr->mutex);
|
||||||
|
int slot;
|
||||||
|
for (;;) {
|
||||||
|
slot = __builtin_ffs(mgr->free_mask)-1;
|
||||||
|
if (slot >= 0) break;
|
||||||
|
mgr->is_waiting = true;
|
||||||
|
condvarWait(&mgr->condvar, &mgr->mutex);
|
||||||
|
}
|
||||||
|
mgr->free_mask &= ~(1U << slot);
|
||||||
|
mutexUnlock(&mgr->mutex);
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sessionmgrDetachClient(SessionMgr* mgr, int slot) {
|
||||||
|
mutexLock(&mgr->mutex);
|
||||||
|
mgr->free_mask |= 1U << slot;
|
||||||
|
if (mgr->is_waiting) {
|
||||||
|
mgr->is_waiting = false;
|
||||||
|
condvarWakeOne(&mgr->condvar);
|
||||||
|
}
|
||||||
|
mutexUnlock(&mgr->mutex);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user