kernel.cpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include "common/common.h"
  6. #include "core/arm/arm_interface.h"
  7. #include "core/core.h"
  8. #include "core/hle/kernel/kernel.h"
  9. #include "core/hle/kernel/thread.h"
  10. #include "core/hle/kernel/timer.h"
  11. namespace Kernel {
  12. unsigned int Object::next_object_id = 0;
  13. SharedPtr<Thread> g_main_thread = nullptr;
  14. HandleTable g_handle_table;
  15. u64 g_program_id = 0;
  16. void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {
  17. auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
  18. if (itr == waiting_threads.end())
  19. waiting_threads.push_back(std::move(thread));
  20. }
  21. void WaitObject::RemoveWaitingThread(Thread* thread) {
  22. auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
  23. if (itr != waiting_threads.end())
  24. waiting_threads.erase(itr);
  25. }
  26. SharedPtr<Thread> WaitObject::WakeupNextThread() {
  27. if (waiting_threads.empty())
  28. return nullptr;
  29. auto next_thread = std::move(waiting_threads.front());
  30. waiting_threads.erase(waiting_threads.begin());
  31. next_thread->ReleaseWaitObject(this);
  32. return next_thread;
  33. }
  34. void WaitObject::WakeupAllWaitingThreads() {
  35. auto waiting_threads_copy = waiting_threads;
  36. // We use a copy because ReleaseWaitObject will remove the thread from this object's
  37. // waiting_threads list
  38. for (auto thread : waiting_threads_copy)
  39. thread->ReleaseWaitObject(this);
  40. ASSERT_MSG(waiting_threads.empty(), "failed to awaken all waiting threads!");
  41. }
  42. HandleTable::HandleTable() {
  43. next_generation = 1;
  44. Clear();
  45. }
  46. ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
  47. DEBUG_ASSERT(obj != nullptr);
  48. u16 slot = next_free_slot;
  49. if (slot >= generations.size()) {
  50. LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
  51. return ERR_OUT_OF_HANDLES;
  52. }
  53. next_free_slot = generations[slot];
  54. u16 generation = next_generation++;
  55. // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
  56. // CTR-OS doesn't use generation 0, so skip straight to 1.
  57. if (next_generation >= (1 << 15)) next_generation = 1;
  58. generations[slot] = generation;
  59. objects[slot] = std::move(obj);
  60. Handle handle = generation | (slot << 15);
  61. return MakeResult<Handle>(handle);
  62. }
  63. ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
  64. SharedPtr<Object> object = GetGeneric(handle);
  65. if (object == nullptr) {
  66. LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle);
  67. return ERR_INVALID_HANDLE;
  68. }
  69. return Create(std::move(object));
  70. }
  71. ResultCode HandleTable::Close(Handle handle) {
  72. if (!IsValid(handle))
  73. return ERR_INVALID_HANDLE;
  74. u16 slot = GetSlot(handle);
  75. objects[slot] = nullptr;
  76. generations[slot] = next_free_slot;
  77. next_free_slot = slot;
  78. return RESULT_SUCCESS;
  79. }
  80. bool HandleTable::IsValid(Handle handle) const {
  81. size_t slot = GetSlot(handle);
  82. u16 generation = GetGeneration(handle);
  83. return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
  84. }
  85. SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
  86. if (handle == CurrentThread) {
  87. return GetCurrentThread();
  88. } else if (handle == CurrentProcess) {
  89. LOG_ERROR(Kernel, "Current process (%08X) pseudo-handle not supported", CurrentProcess);
  90. return nullptr;
  91. }
  92. if (!IsValid(handle)) {
  93. return nullptr;
  94. }
  95. return objects[GetSlot(handle)];
  96. }
  97. void HandleTable::Clear() {
  98. for (u16 i = 0; i < MAX_COUNT; ++i) {
  99. generations[i] = i + 1;
  100. objects[i] = nullptr;
  101. }
  102. next_free_slot = 0;
  103. }
  104. /// Initialize the kernel
  105. void Init() {
  106. Kernel::ThreadingInit();
  107. Kernel::TimersInit();
  108. }
  109. /// Shutdown the kernel
  110. void Shutdown() {
  111. Kernel::ThreadingShutdown();
  112. Kernel::TimersShutdown();
  113. g_handle_table.Clear(); // Free all kernel objects
  114. }
  115. /**
  116. * Loads executable stored at specified address
  117. * @entry_point Entry point in memory of loaded executable
  118. * @return True on success, otherwise false
  119. */
  120. bool LoadExec(u32 entry_point) {
  121. // 0x30 is the typical main thread priority I've seen used so far
  122. g_main_thread = Kernel::SetupMainThread(Kernel::DEFAULT_STACK_SIZE, entry_point, 0x30);
  123. return true;
  124. }
  125. } // namespace