diff options
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 82 |
1 files changed, 68 insertions, 14 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 3a89511aa..510a9b3e3 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -323,7 +323,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien | |||
| 323 | // Add the server session to the handle table. | 323 | // Add the server session to the handle table. |
| 324 | R_TRY(handle_table.Add(out_server, &session->GetServerSession())); | 324 | R_TRY(handle_table.Add(out_server, &session->GetServerSession())); |
| 325 | 325 | ||
| 326 | // Add the client session to the handle table. */ | 326 | // Add the client session to the handle table. |
| 327 | const auto result = handle_table.Add(out_client, &session->GetClientSession()); | 327 | const auto result = handle_table.Add(out_client, &session->GetClientSession()); |
| 328 | 328 | ||
| 329 | if (!R_SUCCEEDED(result)) { | 329 | if (!R_SUCCEEDED(result)) { |
| @@ -383,7 +383,8 @@ static Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_n | |||
| 383 | 383 | ||
| 384 | // Create a session. | 384 | // Create a session. |
| 385 | KClientSession* session{}; | 385 | KClientSession* session{}; |
| 386 | R_TRY(port->CreateSession(std::addressof(session))); | 386 | R_TRY(port->CreateSession(std::addressof(session), |
| 387 | std::make_shared<SessionRequestManager>(kernel))); | ||
| 387 | port->Close(); | 388 | port->Close(); |
| 388 | 389 | ||
| 389 | // Register the session in the table, close the extra reference. | 390 | // Register the session in the table, close the extra reference. |
| @@ -401,7 +402,7 @@ static Result ConnectToNamedPort32(Core::System& system, Handle* out_handle, | |||
| 401 | return ConnectToNamedPort(system, out_handle, port_name_address); | 402 | return ConnectToNamedPort(system, out_handle, port_name_address); |
| 402 | } | 403 | } |
| 403 | 404 | ||
| 404 | /// Makes a blocking IPC call to an OS service. | 405 | /// Makes a blocking IPC call to a service. |
| 405 | static Result SendSyncRequest(Core::System& system, Handle handle) { | 406 | static Result SendSyncRequest(Core::System& system, Handle handle) { |
| 406 | auto& kernel = system.Kernel(); | 407 | auto& kernel = system.Kernel(); |
| 407 | 408 | ||
| @@ -415,22 +416,75 @@ static Result SendSyncRequest(Core::System& system, Handle handle) { | |||
| 415 | 416 | ||
| 416 | LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); | 417 | LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName()); |
| 417 | 418 | ||
| 418 | { | 419 | return session->SendSyncRequest(); |
| 419 | KScopedSchedulerLock lock(kernel); | ||
| 420 | |||
| 421 | // This is a synchronous request, so we should wait for our request to complete. | ||
| 422 | GetCurrentThread(kernel).BeginWait(std::addressof(wait_queue)); | ||
| 423 | GetCurrentThread(kernel).SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); | ||
| 424 | session->SendSyncRequest(&GetCurrentThread(kernel), system.Memory(), system.CoreTiming()); | ||
| 425 | } | ||
| 426 | |||
| 427 | return GetCurrentThread(kernel).GetWaitResult(); | ||
| 428 | } | 420 | } |
| 429 | 421 | ||
| 430 | static Result SendSyncRequest32(Core::System& system, Handle handle) { | 422 | static Result SendSyncRequest32(Core::System& system, Handle handle) { |
| 431 | return SendSyncRequest(system, handle); | 423 | return SendSyncRequest(system, handle); |
| 432 | } | 424 | } |
| 433 | 425 | ||
| 426 | static Result ReplyAndReceive(Core::System& system, s32* out_index, Handle* handles, | ||
| 427 | s32 num_handles, Handle reply_target, s64 timeout_ns) { | ||
| 428 | auto& kernel = system.Kernel(); | ||
| 429 | auto& handle_table = GetCurrentThread(kernel).GetOwnerProcess()->GetHandleTable(); | ||
| 430 | |||
| 431 | // Convert handle list to object table. | ||
| 432 | std::vector<KSynchronizationObject*> objs(num_handles); | ||
| 433 | R_UNLESS( | ||
| 434 | handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, num_handles), | ||
| 435 | ResultInvalidHandle); | ||
| 436 | |||
| 437 | // Ensure handles are closed when we're done. | ||
| 438 | SCOPE_EXIT({ | ||
| 439 | for (auto i = 0; i < num_handles; ++i) { | ||
| 440 | objs[i]->Close(); | ||
| 441 | } | ||
| 442 | }); | ||
| 443 | |||
| 444 | // Reply to the target, if one is specified. | ||
| 445 | if (reply_target != InvalidHandle) { | ||
| 446 | KScopedAutoObject session = handle_table.GetObject<KServerSession>(reply_target); | ||
| 447 | R_UNLESS(session.IsNotNull(), ResultInvalidHandle); | ||
| 448 | |||
| 449 | // If we fail to reply, we want to set the output index to -1. | ||
| 450 | // ON_RESULT_FAILURE { *out_index = -1; }; | ||
| 451 | |||
| 452 | // Send the reply. | ||
| 453 | // R_TRY(session->SendReply()); | ||
| 454 | |||
| 455 | Result rc = session->SendReply(); | ||
| 456 | if (!R_SUCCEEDED(rc)) { | ||
| 457 | *out_index = -1; | ||
| 458 | return rc; | ||
| 459 | } | ||
| 460 | } | ||
| 461 | |||
| 462 | // Wait for a message. | ||
| 463 | while (true) { | ||
| 464 | // Wait for an object. | ||
| 465 | s32 index; | ||
| 466 | Result result = KSynchronizationObject::Wait(kernel, &index, objs.data(), | ||
| 467 | static_cast<s32>(objs.size()), timeout_ns); | ||
| 468 | if (result == ResultTimedOut) { | ||
| 469 | return result; | ||
| 470 | } | ||
| 471 | |||
| 472 | // Receive the request. | ||
| 473 | if (R_SUCCEEDED(result)) { | ||
| 474 | KServerSession* session = objs[index]->DynamicCast<KServerSession*>(); | ||
| 475 | if (session != nullptr) { | ||
| 476 | result = session->ReceiveRequest(); | ||
| 477 | if (result == ResultNotFound) { | ||
| 478 | continue; | ||
| 479 | } | ||
| 480 | } | ||
| 481 | } | ||
| 482 | |||
| 483 | *out_index = index; | ||
| 484 | return result; | ||
| 485 | } | ||
| 486 | } | ||
| 487 | |||
| 434 | /// Get the ID for the specified thread. | 488 | /// Get the ID for the specified thread. |
| 435 | static Result GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) { | 489 | static Result GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) { |
| 436 | // Get the thread from its handle. | 490 | // Get the thread from its handle. |
| @@ -2951,7 +3005,7 @@ static const FunctionDef SVC_Table_64[] = { | |||
| 2951 | {0x40, SvcWrap64<CreateSession>, "CreateSession"}, | 3005 | {0x40, SvcWrap64<CreateSession>, "CreateSession"}, |
| 2952 | {0x41, nullptr, "AcceptSession"}, | 3006 | {0x41, nullptr, "AcceptSession"}, |
| 2953 | {0x42, nullptr, "ReplyAndReceiveLight"}, | 3007 | {0x42, nullptr, "ReplyAndReceiveLight"}, |
| 2954 | {0x43, nullptr, "ReplyAndReceive"}, | 3008 | {0x43, SvcWrap64<ReplyAndReceive>, "ReplyAndReceive"}, |
| 2955 | {0x44, nullptr, "ReplyAndReceiveWithUserBuffer"}, | 3009 | {0x44, nullptr, "ReplyAndReceiveWithUserBuffer"}, |
| 2956 | {0x45, SvcWrap64<CreateEvent>, "CreateEvent"}, | 3010 | {0x45, SvcWrap64<CreateEvent>, "CreateEvent"}, |
| 2957 | {0x46, nullptr, "MapIoRegion"}, | 3011 | {0x46, nullptr, "MapIoRegion"}, |