core_cpu.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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 <atomic>
  6. #include <condition_variable>
  7. #include <cstddef>
  8. #include <memory>
  9. #include <mutex>
  10. #include "common/common_types.h"
  11. namespace Kernel {
  12. class GlobalScheduler;
  13. class Scheduler;
  14. } // namespace Kernel
  15. namespace Core {
  16. class System;
  17. }
  18. namespace Core::Timing {
  19. class CoreTiming;
  20. }
  21. namespace Memory {
  22. class Memory;
  23. }
  24. namespace Core {
  25. class ARM_Interface;
  26. class ExclusiveMonitor;
  27. constexpr unsigned NUM_CPU_CORES{4};
  28. class CpuBarrier {
  29. public:
  30. bool IsAlive() const {
  31. return !end;
  32. }
  33. void NotifyEnd();
  34. bool Rendezvous();
  35. private:
  36. unsigned cores_waiting{NUM_CPU_CORES};
  37. std::mutex mutex;
  38. std::condition_variable condition;
  39. std::atomic<bool> end{};
  40. };
  41. class Cpu {
  42. public:
  43. Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier,
  44. std::size_t core_index);
  45. ~Cpu();
  46. void RunLoop(bool tight_loop = true);
  47. void SingleStep();
  48. void PrepareReschedule();
  49. ARM_Interface& ArmInterface() {
  50. return *arm_interface;
  51. }
  52. const ARM_Interface& ArmInterface() const {
  53. return *arm_interface;
  54. }
  55. Kernel::Scheduler& Scheduler() {
  56. return *scheduler;
  57. }
  58. const Kernel::Scheduler& Scheduler() const {
  59. return *scheduler;
  60. }
  61. bool IsMainCore() const {
  62. return core_index == 0;
  63. }
  64. std::size_t CoreIndex() const {
  65. return core_index;
  66. }
  67. void Shutdown();
  68. /**
  69. * Creates an exclusive monitor to handle exclusive reads/writes.
  70. *
  71. * @param memory The current memory subsystem that the monitor may wish
  72. * to keep track of.
  73. *
  74. * @param num_cores The number of cores to assume about the CPU.
  75. *
  76. * @returns The constructed exclusive monitor instance, or nullptr if the current
  77. * CPU backend is unable to use an exclusive monitor.
  78. */
  79. static std::unique_ptr<ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory,
  80. std::size_t num_cores);
  81. private:
  82. void Reschedule();
  83. std::unique_ptr<ARM_Interface> arm_interface;
  84. CpuBarrier& cpu_barrier;
  85. Kernel::GlobalScheduler& global_scheduler;
  86. std::unique_ptr<Kernel::Scheduler> scheduler;
  87. Timing::CoreTiming& core_timing;
  88. std::atomic<bool> reschedule_pending = false;
  89. std::size_t core_index;
  90. };
  91. } // namespace Core