address_arbiter.cpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include "common/common_types.h"
  5. #include "core/mem_map.h"
  6. #include "core/hle/hle.h"
  7. #include "core/hle/kernel/address_arbiter.h"
  8. #include "core/hle/kernel/thread.h"
  9. ////////////////////////////////////////////////////////////////////////////////////////////////////
  10. // Kernel namespace
  11. namespace Kernel {
  12. class AddressArbiter : public Object {
  13. public:
  14. std::string GetTypeName() const override { return "Arbiter"; }
  15. std::string GetName() const override { return name; }
  16. static const HandleType HANDLE_TYPE = HandleType::AddressArbiter;
  17. HandleType GetHandleType() const override { return HANDLE_TYPE; }
  18. std::string name; ///< Name of address arbiter object (optional)
  19. };
  20. ////////////////////////////////////////////////////////////////////////////////////////////////////
  21. /// Arbitrate an address
  22. ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s32 value) {
  23. Object* object = Kernel::g_handle_table.GetGeneric(handle).get();
  24. if (object == nullptr)
  25. return InvalidHandle(ErrorModule::Kernel);
  26. switch (type) {
  27. // Signal thread(s) waiting for arbitrate address...
  28. case ArbitrationType::Signal:
  29. // Negative value means resume all threads
  30. if (value < 0) {
  31. ArbitrateAllThreads(object, address);
  32. } else {
  33. // Resume first N threads
  34. for(int i = 0; i < value; i++)
  35. ArbitrateHighestPriorityThread(object, address);
  36. }
  37. break;
  38. // Wait current thread (acquire the arbiter)...
  39. case ArbitrationType::WaitIfLessThan:
  40. if ((s32)Memory::Read32(address) <= value) {
  41. Kernel::WaitCurrentThread(WAITTYPE_ARB, object, address);
  42. HLE::Reschedule(__func__);
  43. }
  44. break;
  45. case ArbitrationType::DecrementAndWaitIfLessThan:
  46. {
  47. s32 memory_value = Memory::Read32(address) - 1;
  48. Memory::Write32(address, memory_value);
  49. if (memory_value <= value) {
  50. Kernel::WaitCurrentThread(WAITTYPE_ARB, object, address);
  51. HLE::Reschedule(__func__);
  52. }
  53. break;
  54. }
  55. default:
  56. LOG_ERROR(Kernel, "unknown type=%d", type);
  57. return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, ErrorSummary::WrongArgument, ErrorLevel::Usage);
  58. }
  59. return RESULT_SUCCESS;
  60. }
  61. /// Create an address arbiter
  62. AddressArbiter* CreateAddressArbiter(Handle& handle, const std::string& name) {
  63. AddressArbiter* address_arbiter = new AddressArbiter;
  64. // TOOD(yuriks): Fix error reporting
  65. handle = Kernel::g_handle_table.Create(address_arbiter).ValueOr(INVALID_HANDLE);
  66. address_arbiter->name = name;
  67. return address_arbiter;
  68. }
  69. /// Create an address arbiter
  70. Handle CreateAddressArbiter(const std::string& name) {
  71. Handle handle;
  72. CreateAddressArbiter(handle, name);
  73. return handle;
  74. }
  75. } // namespace Kernel