libnx/nx/source/sf/sessionmgr.c

62 lines
1.8 KiB
C

#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);
}