From 79c30ee716261c4199b1cb91bd5f5001b8029caf Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Fri, 5 Feb 2021 21:39:08 +0700 Subject: [PATCH 1/6] We don't really need to allocate a buffer when using MSG_TRUNC on recvfrom --- Core/HLE/proAdhoc.cpp | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index 10f89df145b8..b9d4618ca7d1 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -1908,20 +1908,10 @@ u_long getAvailToRecv(int sock, int udpBufferSize) { return 0; if (udpBufferSize > 0 && n > 0) { - // Cap number of bytes of full DGRAM message(s?) up to buffer size - static int lastUdpBufSize = 0; - static char* buf = NULL; - if (udpBufferSize > lastUdpBufSize) { - // Reusing temp buffer to prevent causing too many fragmentation due to repeated alloc -> free (was getting out of memory issue) - char *tmp = (char*)realloc(buf, udpBufferSize); - if (tmp) { - buf = tmp; - lastUdpBufSize = udpBufferSize; - } - } - // Does each recv can only received one message? - err = recvfrom(sock, buf, udpBufferSize, MSG_PEEK | MSG_NOSIGNAL | MSG_TRUNC, NULL, NULL); - //free(buf); // Repeated alloc -> free seems to cause too many fragmentation and ended getting out of memory due to too many alloc -> free + // TODO: Cap number of bytes of full DGRAM message(s) up to buffer size + char buf[8]; + // Each recv can only received one message, not sure how to read the next pending msg without actually receiving the first one + err = recvfrom(sock, buf, sizeof(buf), MSG_PEEK | MSG_NOSIGNAL | MSG_TRUNC, NULL, NULL); if (err >= 0) return (u_long)err; } From a7eccc0c6fe01bb248dad470371550fa95bd59a3 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Fri, 5 Feb 2021 21:43:29 +0700 Subject: [PATCH 2/6] Minor renaming --- Core/HLE/sceNetAdhoc.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 06dd821f3372..8270a9140ac9 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -109,7 +109,7 @@ int PollAdhocSocket(SceNetAdhocPollSd* sds, int count, int timeout, int nonblock int FlushPtpSocket(int socketId); int NetAdhocGameMode_DeleteMaster(); int NetAdhocctl_ExitGameMode(); -int NetAdhoc_PtpConnect(int id, int timeout, int flag, bool allowForcedConnect = true); +int NetAdhocPtp_Connect(int id, int timeout, int flag, bool allowForcedConnect = true); static int sceNetAdhocPdpSend(int id, const char* mac, u32 port, void* data, int len, int timeout, int flag); static int sceNetAdhocPdpRecv(int id, void* addr, void* port, void* buf, void* dataLength, u32 timeout, int flag); @@ -3210,7 +3210,7 @@ static int sceNetAdhocPtpOpen(const char *srcmac, int sport, const char *dstmac, changeBlockingMode(tcpsocket, 1); // Initiate PtpConnect (ie. The Warrior seems to try to PtpSend right after PtpOpen without trying to PtpConnect first) - NetAdhoc_PtpConnect(i + 1, rexmt_int, 1, false); + NetAdhocPtp_Connect(i + 1, rexmt_int, 1, false); // Return PTP Socket Pointer return hleLogDebug(SCENET, i + 1, "success"); @@ -3459,7 +3459,7 @@ static int sceNetAdhocPtpAccept(int id, u32 peerMacAddrPtr, u32 peerPortPtr, int return hleLogSuccessVerboseI(SCENET, ERROR_NET_ADHOC_NOT_INITIALIZED, "not initialized"); } -int NetAdhoc_PtpConnect(int id, int timeout, int flag, bool allowForcedConnect) { +int NetAdhocPtp_Connect(int id, int timeout, int flag, bool allowForcedConnect) { // Library is initialized if (netAdhocInited) { @@ -3578,7 +3578,7 @@ static int sceNetAdhocPtpConnect(int id, int timeout, int flag) { return -1; } - return NetAdhoc_PtpConnect(id, timeout, flag); + return NetAdhocPtp_Connect(id, timeout, flag); } int NetAdhocPtp_Close(int id, int unknown) { From ddc122bcbecc874e22c941bf73c9db5dc67dfcea Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Fri, 5 Feb 2021 21:46:16 +0700 Subject: [PATCH 3/6] Moving hleDelayResult from internal function of SetSocketAlert to prevent waking up HLE-blocked thread --- Core/HLE/sceNetAdhoc.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 8270a9140ac9..001cefe5c65c 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -1808,14 +1808,16 @@ int NetAdhoc_SetSocketAlert(int id, s32_le flag) { adhocSockets[id - 1]->flags = flg; adhocSockets[id - 1]->alerted_flags = 0; - return hleDelayResult(0, "set socket alert delay", 1000); + return 0; } // Flags seems to be bitmasks of ADHOC_F_ALERT... (need more games to test this) int sceNetAdhocSetSocketAlert(int id, int flag) { WARN_LOG_REPORT_ONCE(sceNetAdhocSetSocketAlert, SCENET, "UNTESTED sceNetAdhocSetSocketAlert(%d, %08x) at %08x", id, flag, currentMIPS->pc); - return hleLogDebug(SCENET, NetAdhoc_SetSocketAlert(id, flag), ""); + int retval = NetAdhoc_SetSocketAlert(id, flag); + hleDelayResult(retval, "set socket alert delay", 1000); + return hleLogDebug(SCENET, retval, ""); } int PollAdhocSocket(SceNetAdhocPollSd* sds, int count, int timeout, int nonblock) { From 04434ea68ee09d074731e42c99f324bc2069e316 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Fri, 5 Feb 2021 21:49:02 +0700 Subject: [PATCH 4/6] Fix possible race condition issue. --- Core/HLE/proAdhoc.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/HLE/proAdhoc.cpp b/Core/HLE/proAdhoc.cpp index b9d4618ca7d1..0e2b957f5867 100644 --- a/Core/HLE/proAdhoc.cpp +++ b/Core/HLE/proAdhoc.cpp @@ -1139,18 +1139,18 @@ void AfterMatchingMipsCall::SetData(int ContextID, int eventId, u32_le BufAddr) bool SetMatchingInCallback(SceNetAdhocMatchingContext* context, bool IsInCB) { if (context == NULL) return false; - context->eventlock->lock(); //peerlock.lock(); + peerlock.lock(); context->IsMatchingInCB = IsInCB; - context->eventlock->unlock(); //peerlock.unlock(); + peerlock.unlock(); return IsInCB; } bool IsMatchingInCallback(SceNetAdhocMatchingContext* context) { bool inCB = false; if (context == NULL) return inCB; - context->eventlock->lock(); //peerlock.lock(); + peerlock.lock(); inCB = (context->IsMatchingInCB); - context->eventlock->unlock(); //peerlock.unlock(); + peerlock.unlock(); return inCB; } From f17d387a65c6e10f461284f34b4ccea33144e5f1 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Sun, 7 Feb 2021 12:08:02 +0700 Subject: [PATCH 5/6] Updated some Logs to help finding the location of the call to debug. --- Core/HLE/sceNet.cpp | 2 +- Core/HLE/sceNetAdhoc.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/HLE/sceNet.cpp b/Core/HLE/sceNet.cpp index 448b0ba66e19..b13aad410cfe 100644 --- a/Core/HLE/sceNet.cpp +++ b/Core/HLE/sceNet.cpp @@ -591,7 +591,7 @@ u32 Net_Term() { } static u32 sceNetTerm() { - WARN_LOG(SCENET, "sceNetTerm()"); + WARN_LOG(SCENET, "sceNetTerm() at %08x", currentMIPS->pc); int retval = Net_Term(); // Give time to make sure everything are cleaned up diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index 001cefe5c65c..af3343158357 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -2386,7 +2386,7 @@ static u32 sceNetAdhocctlDelHandler(u32 handlerID) { if (adhocctlHandlers.find(handlerID) != adhocctlHandlers.end()) { adhocctlHandlers.erase(handlerID); - INFO_LOG(SCENET, "sceNetAdhocctlDelHandler(%d)", handlerID); + INFO_LOG(SCENET, "sceNetAdhocctlDelHandler(%d) at %08x", handlerID, currentMIPS->pc); } else { WARN_LOG(SCENET, "sceNetAdhocctlDelHandler(%d): Invalid Handler ID", handlerID); } @@ -2443,7 +2443,7 @@ int NetAdhocctl_Term() { int sceNetAdhocctlTerm() { // WLAN might be disabled in the middle of successfull multiplayer, but we still need to cleanup right? - INFO_LOG(SCENET, "sceNetAdhocctlTerm()"); + INFO_LOG(SCENET, "sceNetAdhocctlTerm() at %08x", currentMIPS->pc); //if (netAdhocMatchingInited) NetAdhocMatching_Term(); int retval = NetAdhocctl_Term(); From 8432d6c5d7ba46efc4e269bb2796d285bea8cd16 Mon Sep 17 00:00:00 2001 From: ANR2ME Date: Sun, 7 Feb 2021 12:09:29 +0700 Subject: [PATCH 6/6] Removing hleDelayResult from internal adhoc functions to prevent waking up thread that supposed to be blocked by the outer HLE. --- Core/HLE/sceNetAdhoc.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Core/HLE/sceNetAdhoc.cpp b/Core/HLE/sceNetAdhoc.cpp index af3343158357..ad2ab98096de 100644 --- a/Core/HLE/sceNetAdhoc.cpp +++ b/Core/HLE/sceNetAdhoc.cpp @@ -2363,7 +2363,7 @@ u32 NetAdhocctl_Disconnect() { } // Return Success, some games might ignore returned value and always treat it as success, otherwise repeatedly calling this function - return hleDelayResult(0, "disconnect delay", us); + return 0; } // Library uninitialized @@ -2397,6 +2397,7 @@ static u32 sceNetAdhocctlDelHandler(u32 handlerID) { int NetAdhocctl_Term() { if (netAdhocctlInited) { if (adhocctlState != ADHOCCTL_STATE_DISCONNECTED) { + // Note: This might block current thread if the first attempt to send OPCODE_DISCONNECT to AdhocServer failed with EAGAIN error if (netAdhocGameModeEntered) NetAdhocctl_ExitGameMode(); else @@ -2409,6 +2410,8 @@ int NetAdhocctl_Term() { friendFinderThread.join(); } + // TODO: May need to block current thread to make sure all Adhocctl callbacks have been fully executed before terminating Adhoc PSPThread (ie. threadAdhocID). + // Clear GameMode resources NetAdhocGameMode_DeleteMaster(); deleteAllGMB(); @@ -2661,7 +2664,7 @@ int NetAdhocctl_Create(const char* groupName) { hleEatMicro(us); // Return Success // FIXME: When tested using JPCSP + official prx files it seems sceNetAdhocctlCreate switching to a different thread for at least 100ms after returning success and before executing the next line. - return hleDelayResult(0, "create/connect/join delay", adhocEventPollDelay); + return 0; } // Connected State @@ -4695,8 +4698,7 @@ int NetAdhocMatching_Start(int matchingId, int evthPri, int evthPartitionId, int // Multithreading Unlock peerlock.unlock(); - // Give a little time to make sure matching Threads are ready before the game use the next sceNet functions, should've checked for status instead of guessing the time? - return hleDelayResult(0, "give some time", adhocMatchingEventDelay); + return 0; } #define KERNEL_PARTITION_ID 1 @@ -4708,7 +4710,9 @@ static int sceNetAdhocMatchingStart(int matchingId, int evthPri, int evthStack, if (!g_Config.bEnableWlan) return -1; - return NetAdhocMatching_Start(matchingId, evthPri, USER_PARTITION_ID, evthStack, inthPri, USER_PARTITION_ID, inthStack, optLen, optDataAddr); + int retval = NetAdhocMatching_Start(matchingId, evthPri, USER_PARTITION_ID, evthStack, inthPri, USER_PARTITION_ID, inthStack, optLen, optDataAddr); + // Give a little time to make sure matching Threads are ready before the game use the next sceNet functions, should've checked for status instead of guessing the time? + return hleDelayResult(retval, "give some time", adhocMatchingEventDelay); } // With params for Partition ID for the event & input handler stack @@ -4717,7 +4721,9 @@ static int sceNetAdhocMatchingStart2(int matchingId, int evthPri, int evthPartit if (!g_Config.bEnableWlan) return -1; - return NetAdhocMatching_Start(matchingId, evthPri, evthPartitionId, evthStack, inthPri, inthPartitionId, inthStack, optLen, optDataAddr); + int retval = NetAdhocMatching_Start(matchingId, evthPri, evthPartitionId, evthStack, inthPri, inthPartitionId, inthStack, optLen, optDataAddr); + // Give a little time to make sure matching Threads are ready before the game use the next sceNet functions, should've checked for status instead of guessing the time? + return hleDelayResult(retval, "give some time", adhocMatchingEventDelay); }