address_arbiter.h 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <list>
  6. #include <memory>
  7. #include <unordered_map>
  8. #include <vector>
  9. #include "common/common_types.h"
  10. union ResultCode;
  11. namespace Core {
  12. class System;
  13. }
  14. namespace Kernel {
  15. class Thread;
  16. class AddressArbiter {
  17. public:
  18. enum class ArbitrationType {
  19. WaitIfLessThan = 0,
  20. DecrementAndWaitIfLessThan = 1,
  21. WaitIfEqual = 2,
  22. };
  23. enum class SignalType {
  24. Signal = 0,
  25. IncrementAndSignalIfEqual = 1,
  26. ModifyByWaitingCountAndSignalIfEqual = 2,
  27. };
  28. explicit AddressArbiter(Core::System& system);
  29. ~AddressArbiter();
  30. AddressArbiter(const AddressArbiter&) = delete;
  31. AddressArbiter& operator=(const AddressArbiter&) = delete;
  32. AddressArbiter(AddressArbiter&&) = default;
  33. AddressArbiter& operator=(AddressArbiter&&) = delete;
  34. /// Signals an address being waited on with a particular signaling type.
  35. ResultCode SignalToAddress(VAddr address, SignalType type, s32 value, s32 num_to_wake);
  36. /// Waits on an address with a particular arbitration type.
  37. ResultCode WaitForAddress(VAddr address, ArbitrationType type, s32 value, s64 timeout_ns);
  38. /// Removes a thread from the container and resets its address arbiter adress to 0
  39. void HandleWakeupThread(std::shared_ptr<Thread> thread);
  40. private:
  41. /// Signals an address being waited on.
  42. ResultCode SignalToAddressOnly(VAddr address, s32 num_to_wake);
  43. /// Signals an address being waited on and increments its value if equal to the value argument.
  44. ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake);
  45. /// Signals an address being waited on and modifies its value based on waiting thread count if
  46. /// equal to the value argument.
  47. ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value,
  48. s32 num_to_wake);
  49. /// Waits on an address if the value passed is less than the argument value,
  50. /// optionally decrementing.
  51. ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout,
  52. bool should_decrement);
  53. /// Waits on an address if the value passed is equal to the argument value.
  54. ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout);
  55. /// Wake up num_to_wake (or all) threads in a vector.
  56. void WakeThreads(const std::vector<std::shared_ptr<Thread>>& waiting_threads, s32 num_to_wake);
  57. /// Insert a thread into the address arbiter container
  58. void InsertThread(std::shared_ptr<Thread> thread);
  59. /// Removes a thread from the address arbiter container
  60. void RemoveThread(std::shared_ptr<Thread> thread);
  61. // Gets the threads waiting on an address.
  62. std::vector<std::shared_ptr<Thread>> GetThreadsWaitingOnAddress(VAddr address) const;
  63. /// List of threads waiting for a address arbiter
  64. std::unordered_map<VAddr, std::list<std::shared_ptr<Thread>>> arb_threads;
  65. Core::System& system;
  66. };
  67. } // namespace Kernel