diff --git a/sysmodules/sm/source/main.c b/sysmodules/sm/source/main.c index 7457f60..3318bf3 100644 --- a/sysmodules/sm/source/main.c +++ b/sysmodules/sm/source/main.c @@ -66,7 +66,8 @@ int main(void) { Result res; u32 *cmdbuf = getThreadCommandBuffer(); - u32 nbHandles = 3, nbSessions = 0, nbSrvPmSessions = 0; + u32 nbHandles = 3, nbSessions = 0; + bool srvPmSessionCreated = false; Handle clientPortDummy; Handle srvPort, srvPmPort; @@ -90,17 +91,31 @@ int main(void) for(;;) { - s32 id; + s32 id = -1; if(replyTarget == 0) cmdbuf[0] = 0xFFFF0000; // Kernel11 + // Rebuild the list + nbHandles = 3; + nbSessions = 0; + for(sessionData = sessionDataInUseList.first; sessionData != NULL; sessionData = sessionData->next) + { + handles[nbHandles++] = sessionData->handle; + nbSessions++; + } + + for(sessionData = sessionDataWaitingPortReadyList.first; sessionData != NULL; sessionData = sessionData->next) + { + handles[nbHandles++] = sessionData->busyClientPortHandle; + } + res = svcReplyAndReceive(&id, handles, nbHandles, replyTarget); if(res == (Result)0xC920181A) // unreachable remote { // Note: if a process has ended, pm will call UnregisterProcess on it if(id < 0) { - for(id = 3; (u32)id < nbHandles && handles[id] != replyTarget; id++); + for(id = 0; (u32)id < nbHandles && handles[id] != replyTarget; id++); if((u32)id >= nbHandles) panic(); } @@ -118,30 +133,7 @@ int main(void) if(sessionData != NULL) { - if(sessionData->busyClientPortHandle != 0) // remove unreferenced client port handles from array - { - u32 refCount = 0; - for(u32 i = 0; i < sizeof(sessionDataPool) / sizeof(SessionData); i++) - { - if(sessionDataPool[i].busyClientPortHandle == sessionData->busyClientPortHandle) - ++refCount; - } - if(refCount <= 1) - { - u32 i; - for(i = 3 + nbSessions; i < nbHandles && handles[i] == sessionData->busyClientPortHandle; i++); - if(i < nbHandles) - handles[i] = handles[--nbHandles]; - } - } - - --nbHandles; - for(u32 i = (u32)id; i < nbHandles; i++) - handles[i] = handles[i + 1]; - --nbSessions; svcCloseHandle(sessionData->handle); - if(sessionData->isSrvPm) - --nbSrvPmSessions; moveNode(sessionData, &freeSessionDataList, false); } else @@ -163,8 +155,7 @@ int main(void) } } - svcCloseHandle(handles[id]); - handles[id] = handles[--nbHandles]; + // Don't close the handle. } replyTarget = 0; @@ -181,26 +172,17 @@ int main(void) sessionData = (SessionData *)allocateNode(&sessionDataInUseList, &freeSessionDataList, sizeof(SessionData), false); sessionData->pid = (u32)-1; sessionData->handle = session; - for(u32 i = nbHandles; i > 3 + nbSessions; i--) - handles[i] = handles[i - 1]; - handles[3 + nbSessions++] = session; - ++nbHandles; } else if(id == 2) // New srv:pm session { Handle session; - if(!IS_PRE_7X && nbSrvPmSessions >= 1) + if(!IS_PRE_7X && srvPmSessionCreated) panic(); assertSuccess(svcAcceptSession(&session, srvPmPort)); sessionData = (SessionData *)allocateNode(&sessionDataInUseList, &freeSessionDataList, sizeof(SessionData), false); sessionData->pid = (u32)-1; sessionData->handle = session; sessionData->isSrvPm = true; - for(u32 i = nbHandles; i > 3 + nbSessions; i--) - handles[i] = handles[i - 1]; - handles[3 + nbSessions++] = session; - ++nbHandles; - ++nbSrvPmSessions; } else { @@ -210,31 +192,17 @@ int main(void) panic(); sessionData = sessionDataToWakeUpAfterServiceOrPortRegisterList.first; moveNode(sessionData, &sessionDataInUseList, false); - for(u32 i = nbHandles; i > 3 + nbSessions; i--) - handles[i] = handles[i - 1]; - handles[3 + nbSessions++] = sessionData->handle; - ++nbHandles; - if(sessionData->isSrvPm) - ++nbSrvPmSessions; memcpy(cmdbuf, sessionData->replayCmdbuf, 16); } else if((u32)id >= 3 + nbSessions) // Resume SRV:GetServiceHandle if service was full { - SessionData *sTmp; for(sessionData = sessionDataWaitingPortReadyList.first; sessionData != NULL && sessionData->busyClientPortHandle != handles[id]; sessionData = sessionData->next); - if(sessionData == NULL) - panic(); + if(sessionData == NULL) { + // Ignore (client process could have ended) and continue + continue; + } moveNode(sessionData, &sessionDataInUseList, false); - for(sTmp = sessionDataWaitingPortReadyList.first; sTmp != NULL && sTmp->busyClientPortHandle != handles[id]; sTmp = sTmp->next); - if(sTmp == NULL) - handles[id] = handles[--nbHandles]; - for(u32 i = nbHandles + 1; i > 3 + nbSessions; i--) - handles[i] = handles[i - 1]; - handles[3 + nbSessions++] = sessionData->handle; - ++nbHandles; - if(sessionData->isSrvPm) - ++nbSrvPmSessions; memcpy(cmdbuf, sessionData->replayCmdbuf, 16); sessionData->busyClientPortHandle = 0; } @@ -245,10 +213,6 @@ int main(void) panic(); } - for(id = 3; (u32)id < 3 + nbSessions && handles[id] != sessionData->handle; id++); - if((u32)id >= 3 + nbSessions) - panic(); - res = sessionData->isSrvPm ? srvPmHandleCommands(sessionData) : srvHandleCommands(sessionData); if(R_MODULE(res) == RM_SRV && R_SUMMARY(res) == RS_WOULDBLOCK) @@ -257,22 +221,10 @@ int main(void) if(res == (Result)0xD0406401) // service or named port not registered yet dstList = &sessionDataWaitingForServiceOrPortRegisterList; else if(res == (Result)0xD0406402) // service full - { - u32 i; dstList = &sessionDataWaitingPortReadyList; - for(i = 3 + nbSessions; i < nbHandles && handles[i] != sessionData->busyClientPortHandle; i++); - if(i >= nbHandles) - handles[nbHandles++] = sessionData->busyClientPortHandle; - } else panic(); - --nbHandles; - for(u32 i = (u32)id; i < nbHandles; i++) - handles[i] = handles[i + 1]; - --nbSessions; - if(sessionData->isSrvPm) - --nbSrvPmSessions; moveNode(sessionData, dstList, true); } else