address_arbiter.cpp 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/assert.h"
  5. #include "common/common_funcs.h"
  6. #include "common/common_types.h"
  7. #include "core/core.h"
  8. #include "core/hle/kernel/errors.h"
  9. #include "core/hle/kernel/kernel.h"
  10. #include "core/hle/kernel/process.h"
  11. #include "core/hle/kernel/thread.h"
  12. #include "core/hle/lock.h"
  13. #include "core/memory.h"
  14. namespace Kernel {
  15. namespace AddressArbiter {
  16. // Performs actual address waiting logic.
  17. ResultCode WaitForAddress(VAddr address, s64 timeout) {
  18. SharedPtr<Thread> current_thread = GetCurrentThread();
  19. current_thread->arb_wait_address = address;
  20. current_thread->arb_wait_result = RESULT_TIMEOUT;
  21. current_thread->status = THREADSTATUS_WAIT_ARB;
  22. current_thread->wakeup_callback = nullptr;
  23. current_thread->WakeAfterDelay(timeout);
  24. Core::System::GetInstance().CpuCore(current_thread->processor_id).PrepareReschedule();
  25. return RESULT_SUCCESS;
  26. }
  27. // Signals an address being waited on.
  28. ResultCode SignalToAddress(VAddr address, s32 value, s32 num_to_wake) {
  29. // TODO
  30. return RESULT_SUCCESS;
  31. }
  32. // Signals an address being waited on and increments its value if equal to the value argument.
  33. ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake) {
  34. // TODO
  35. return RESULT_SUCCESS;
  36. }
  37. // Signals an address being waited on and modifies its value based on waiting thread count if equal to the value argument.
  38. ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake) {
  39. // TODO
  40. return RESULT_SUCCESS;
  41. }
  42. // Waits on an address if the value passed is less than the argument value, optionally decrementing.
  43. ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool should_decrement) {
  44. // Ensure that we can read the address.
  45. if (!Memory::IsValidVirtualAddress(address)) {
  46. return ERR_INVALID_ADDRESS_STATE;
  47. }
  48. s32 cur_value;
  49. // Get value, decrementing if less than
  50. {
  51. // Decrement if less than must be an atomic operation.
  52. std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
  53. cur_value = (s32)Memory::Read32(address);
  54. if (cur_value < value) {
  55. Memory::Write32(address, (u32)(cur_value - 1));
  56. }
  57. }
  58. if (cur_value >= value) {
  59. return ERR_INVALID_STATE;
  60. }
  61. // Short-circuit without rescheduling, if timeout is zero.
  62. if (timeout == 0) {
  63. return RESULT_TIMEOUT;
  64. }
  65. return WaitForAddress(address, timeout);
  66. }
  67. // Waits on an address if the value passed is equal to the argument value.
  68. ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) {
  69. // Ensure that we can read the address.
  70. if (!Memory::IsValidVirtualAddress(address)) {
  71. return ERR_INVALID_ADDRESS_STATE;
  72. }
  73. // Only wait for the address if equal.
  74. if ((s32)Memory::Read32(address) != value) {
  75. return ERR_INVALID_STATE;
  76. }
  77. // Short-circuit without rescheduling, if timeout is zero.
  78. if (timeout == 0) {
  79. return RESULT_TIMEOUT;
  80. }
  81. return WaitForAddress(address, timeout);
  82. }
  83. } // namespace AddressArbiter
  84. } // namespace Kernel