1
0
Fork 0

HLE/SRV: Don't return the port handle if it isn't available when calling GetServiceHandle.

This was incorrect behavior that somehow found its way to 3dbrew. The correct behavior is to sleep until the port becomes available again and then return a session to it.

This is currently unimplemented due to the inability to put a guest thread to sleep during HLE requests.

The correct behavior was reverse engineered by TuxSH a while ago but we never corrected the code in citra.
This commit is contained in:
Subv 2017-11-06 14:09:56 -05:00
parent d55a13c35d
commit afb6dd7747
1 changed files with 5 additions and 7 deletions

View File

@ -87,7 +87,7 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) {
size_t name_len = rp.Pop<u32>();
u32 flags = rp.Pop<u32>();
bool return_port_on_failure = (flags & 1) == 0;
bool wait_until_available = (flags & 1) == 0;
if (name_len > Service::kMaxPortSize) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
@ -115,12 +115,10 @@ void SRV::GetServiceHandle(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(session.Code());
rb.PushObjects(std::move(session).Unwrap());
} else if (session.Code() == Kernel::ERR_MAX_CONNECTIONS_REACHED && return_port_on_failure) {
LOG_WARNING(Service_SRV, "called service=%s -> ERR_MAX_CONNECTIONS_REACHED, *port*=%u",
name.c_str(), (*client_port)->GetObjectId());
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
rb.Push(ERR_MAX_CONNECTIONS_REACHED);
rb.PushObjects(std::move(client_port).Unwrap());
} else if (session.Code() == Kernel::ERR_MAX_CONNECTIONS_REACHED && wait_until_available) {
LOG_WARNING(Service_SRV, "called service=%s -> ERR_MAX_CONNECTIONS_REACHED", name.c_str());
// TODO(Subv): Put the caller guest thread to sleep until this port becomes available again.
UNIMPLEMENTED_MSG("Unimplemented wait until port %s is available.", name.c_str());
} else {
LOG_ERROR(Service_SRV, "called service=%s -> error 0x%08X", name.c_str(),
session.Code().raw);