svc_event.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "common/scope_exit.h"
  4. #include "core/core.h"
  5. #include "core/hle/kernel/k_event.h"
  6. #include "core/hle/kernel/k_process.h"
  7. #include "core/hle/kernel/k_scoped_resource_reservation.h"
  8. #include "core/hle/kernel/kernel.h"
  9. #include "core/hle/kernel/svc.h"
  10. namespace Kernel::Svc {
  11. Result SignalEvent(Core::System& system, Handle event_handle) {
  12. LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
  13. // Get the current handle table.
  14. const KHandleTable& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
  15. // Get the event.
  16. KScopedAutoObject event = handle_table.GetObject<KEvent>(event_handle);
  17. R_UNLESS(event.IsNotNull(), ResultInvalidHandle);
  18. R_RETURN(event->Signal());
  19. }
  20. Result ClearEvent(Core::System& system, Handle event_handle) {
  21. LOG_TRACE(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
  22. // Get the current handle table.
  23. const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
  24. // Try to clear the writable event.
  25. {
  26. KScopedAutoObject event = handle_table.GetObject<KEvent>(event_handle);
  27. if (event.IsNotNull()) {
  28. R_RETURN(event->Clear());
  29. }
  30. }
  31. // Try to clear the readable event.
  32. {
  33. KScopedAutoObject readable_event = handle_table.GetObject<KReadableEvent>(event_handle);
  34. if (readable_event.IsNotNull()) {
  35. R_RETURN(readable_event->Clear());
  36. }
  37. }
  38. R_THROW(ResultInvalidHandle);
  39. }
  40. Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
  41. LOG_DEBUG(Kernel_SVC, "called");
  42. // Get the kernel reference and handle table.
  43. auto& kernel = system.Kernel();
  44. auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
  45. // Reserve a new event from the process resource limit
  46. KScopedResourceReservation event_reservation(GetCurrentProcessPointer(kernel),
  47. LimitableResource::EventCountMax);
  48. R_UNLESS(event_reservation.Succeeded(), ResultLimitReached);
  49. // Create a new event.
  50. KEvent* event = KEvent::Create(kernel);
  51. R_UNLESS(event != nullptr, ResultOutOfResource);
  52. // Initialize the event.
  53. event->Initialize(GetCurrentProcessPointer(kernel));
  54. // Commit the thread reservation.
  55. event_reservation.Commit();
  56. // Ensure that we clean up the event (and its only references are handle table) on function end.
  57. SCOPE_EXIT({
  58. event->GetReadableEvent().Close();
  59. event->Close();
  60. });
  61. // Register the event.
  62. KEvent::Register(kernel, event);
  63. // Add the event to the handle table.
  64. R_TRY(handle_table.Add(out_write, event));
  65. // Ensure that we maintain a clean handle state on exit.
  66. ON_RESULT_FAILURE {
  67. handle_table.Remove(*out_write);
  68. };
  69. // Add the readable event to the handle table.
  70. R_RETURN(handle_table.Add(out_read, std::addressof(event->GetReadableEvent())));
  71. }
  72. Result SignalEvent64(Core::System& system, Handle event_handle) {
  73. R_RETURN(SignalEvent(system, event_handle));
  74. }
  75. Result ClearEvent64(Core::System& system, Handle event_handle) {
  76. R_RETURN(ClearEvent(system, event_handle));
  77. }
  78. Result CreateEvent64(Core::System& system, Handle* out_write_handle, Handle* out_read_handle) {
  79. R_RETURN(CreateEvent(system, out_write_handle, out_read_handle));
  80. }
  81. Result SignalEvent64From32(Core::System& system, Handle event_handle) {
  82. R_RETURN(SignalEvent(system, event_handle));
  83. }
  84. Result ClearEvent64From32(Core::System& system, Handle event_handle) {
  85. R_RETURN(ClearEvent(system, event_handle));
  86. }
  87. Result CreateEvent64From32(Core::System& system, Handle* out_write_handle,
  88. Handle* out_read_handle) {
  89. R_RETURN(CreateEvent(system, out_write_handle, out_read_handle));
  90. }
  91. } // namespace Kernel::Svc