sceNetInet, sceNetApctl: Quicker access point connection, and no busy waits

pspautotests net/inet/timing measures, on a PSP that has connected to
an open network before: JOINING 11 ms after sceNetApctlConnect,
GETTING_IP after about 2.6 s, GOT_IP after about 3.6 s (6.6 s the first
time), and DISCONNECTED 1.1 s after a disconnect. We took 2 s to get to
each of the three, 6 s in all, and 10 ms to disconnect. Games have to
wait for the connection anyway, so it's now quicker than hardware:
JOINING after 10 ms, GETTING_IP 1.25 s later and GOT_IP 0.5 s after
that, with the delays in named constants. Disconnecting takes 0.5 s,
the state staying as it was until then.

The handlers also got 0 as the old state of every step but the first.
Each step now starts from the state the one before ended in.

recv, recvfrom, select and poll still added a 500 us or 1 ms delay to
every call, a workaround from before blocking calls waited for real.
They now take what they take on the PSP when they return at once,
4-15 us (net/inet/timing).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Henrik RydgårdandClaude Opus 5.5 committed 2026-10-28 20:30:07 +01:00
1 parent 7aecf86c4d
commit 8583d3beaa
3 files changed
+53 -31

No files matched your search

+19 -10
View File
@@ -922,6 +922,11 @@ static void __NetInetWaitPoll(u64 userdata, int cyclesLate) {
}
// FIXME: nfds is number of fd(s) as in posix poll, or was it maximum fd value as in posix select? Star Wars Battlefront Renegade seems to set the nfds to 64, while Coded Arms Contagion is using 256
// What these cost on a PSP when they return without waiting (pspautotests net/inet/timing).
static const int INET_SELECT_US = 15;
static const int INET_POLL_US = 11;
static const int INET_RECV_US = 4;
int sceNetInetSelect(int nfds, u32 readfdsPtr, u32 writefdsPtr, u32 exceptfdsPtr, u32 timeoutPtr) {
INET_CHECK_STACK_SOCKET();
InetThreadSeen();
@@ -957,7 +962,8 @@ int sceNetInetSelect(int nfds, u32 readfdsPtr, u32 writefdsPtr, u32 exceptfdsPtr
}
attempt.result = InetWouldBlockResult(InetWaitOp::Select, __KernelGetCurThread(), args, attempt.hostErrno, __FUNCTION__);
}
return hleDelayResult(hleLogDebug(Log::sceNet, attempt.result), "workaround until blocking-socket", 500); // Using hleDelayResult as a workaround for games that need blocking-socket to be implemented (ie. Coded Arms Contagion)
hleEatMicro(INET_SELECT_US);
return hleLogDebug(Log::sceNet, attempt.result);
}
int sceNetInetPoll(MIPSState *mips, u32 fdsPtr, u32 nfds, int timeout) {
@@ -982,7 +988,8 @@ int sceNetInetPoll(MIPSState *mips, u32 fdsPtr, u32 nfds, int timeout) {
}
attempt.result = 0;
}
return hleDelayResult(hleLogDebug(Log::sceNet, attempt.result), "workaround until blocking-socket", 1000); // Using hleDelayResult as a workaround for games that need blocking-socket to be implemented
hleEatMicro(INET_POLL_US);
return hleLogDebug(Log::sceNet, attempt.result);
}
static int sceNetInetRecv(int socket, u32 bufPtr, u32 bufLen, u32 flags) {
@@ -1003,12 +1010,14 @@ static int sceNetInetRecv(int socket, u32 bufPtr, u32 bufLen, u32 flags) {
return hleLogDebug(Log::sceNet, 0, "waiting");
}
attempt.result = InetWouldBlockResult(InetWaitOp::Recv, __KernelGetCurThread(), args, attempt.hostErrno, __FUNCTION__);
return hleDelayResult(hleLogDebug(Log::sceNet, attempt.result, "EAGAIN"), "workaround until blocking-socket", 500);
hleEatMicro(INET_RECV_US);
return hleLogDebug(Log::sceNet, attempt.result, "EAGAIN");
}
hleEatMicro(INET_RECV_US);
if (attempt.result < 0) {
return hleDelayResult(hleLogError(Log::sceNet, attempt.result), "workaround until blocking-socket", 500);
return hleLogError(Log::sceNet, attempt.result);
}
return hleDelayResult(hleLogInfo(Log::sceNet, attempt.result), "workaround until blocking-socket", 500); // Using hleDelayResult as a workaround for games that need blocking-socket to be implemented
return hleLogInfo(Log::sceNet, attempt.result);
}
static int sceNetInetSend(int socket, u32 bufPtr, u32 bufLen, u32 flags) {
@@ -1748,14 +1757,14 @@ static int sceNetInetRecvfrom(int socket, u32 bufferPtr, int len, int flags, u32
return hleLogDebug(Log::sceNet, 0, "waiting");
}
attempt.result = InetWouldBlockResult(InetWaitOp::RecvFrom, __KernelGetCurThread(), args, attempt.hostErrno, __FUNCTION__);
// Using hleDelayResult as a workaround for games that need blocking-socket to be implemented (ie. Coded Arms Contagion)
return hleDelayResult(hleLogDebug(Log::sceNet, attempt.result, "EAGAIN"), "workaround until blocking-socket", 500);
hleEatMicro(INET_RECV_US);
return hleLogDebug(Log::sceNet, attempt.result, "EAGAIN");
}
hleEatMicro(INET_RECV_US);
if (attempt.result < 0) {
return hleDelayResult(hleLogError(Log::sceNet, attempt.result), "workaround until blocking-socket", 500);
return hleLogError(Log::sceNet, attempt.result);
}
// Using hleDelayResult as a workaround for games that need blocking-socket to be implemented (ie. Coded Arms Contagion)
return hleDelayResult(hleLogDebug(Log::sceNet, attempt.result), "workaround until blocking-socket", 500);
return hleLogDebug(Log::sceNet, attempt.result);
}
// args: socket, buf, len, flags, to, tolen.