mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 20:42:44 +02:00
62 lines
1.9 KiB
C
62 lines
1.9 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]);
|
|
svcCloseHandle(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->num_waiters ++;
|
|
condvarWait(&mgr->condvar, &mgr->mutex);
|
|
mgr->num_waiters --;
|
|
}
|
|
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->num_waiters)
|
|
condvarWakeOne(&mgr->condvar);
|
|
mutexUnlock(&mgr->mutex);
|
|
}
|