kernel.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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/assert.h"
  6. #include "common/logging/log.h"
  7. #include "core/hle/config_mem.h"
  8. #include "core/hle/kernel/kernel.h"
  9. #include "core/hle/kernel/memory.h"
  10. #include "core/hle/kernel/process.h"
  11. #include "core/hle/kernel/resource_limit.h"
  12. #include "core/hle/kernel/thread.h"
  13. #include "core/hle/kernel/timer.h"
  14. #include "core/hle/shared_page.h"
  15. namespace Kernel {
  16. unsigned int Object::next_object_id;
  17. HandleTable g_handle_table;
  18. void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {
  19. auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
  20. if (itr == waiting_threads.end())
  21. waiting_threads.push_back(std::move(thread));
  22. }
  23. void WaitObject::RemoveWaitingThread(Thread* thread) {
  24. auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
  25. if (itr != waiting_threads.end())
  26. waiting_threads.erase(itr);
  27. }
  28. void WaitObject::WakeupAllWaitingThreads() {
  29. for (auto thread : waiting_threads)
  30. thread->ResumeFromWait();
  31. waiting_threads.clear();
  32. HLE::Reschedule(__func__);
  33. }
  34. HandleTable::HandleTable() {
  35. next_generation = 1;
  36. Clear();
  37. }
  38. ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
  39. DEBUG_ASSERT(obj != nullptr);
  40. u16 slot = next_free_slot;
  41. if (slot >= generations.size()) {
  42. LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
  43. return ERR_OUT_OF_HANDLES;
  44. }
  45. next_free_slot = generations[slot];
  46. u16 generation = next_generation++;
  47. // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
  48. // CTR-OS doesn't use generation 0, so skip straight to 1.
  49. if (next_generation >= (1 << 15)) next_generation = 1;
  50. generations[slot] = generation;
  51. objects[slot] = std::move(obj);
  52. Handle handle = generation | (slot << 15);
  53. return MakeResult<Handle>(handle);
  54. }
  55. ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
  56. SharedPtr<Object> object = GetGeneric(handle);
  57. if (object == nullptr) {
  58. LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle);
  59. return ERR_INVALID_HANDLE;
  60. }
  61. return Create(std::move(object));
  62. }
  63. ResultCode HandleTable::Close(Handle handle) {
  64. if (!IsValid(handle))
  65. return ERR_INVALID_HANDLE;
  66. u16 slot = GetSlot(handle);
  67. objects[slot] = nullptr;
  68. generations[slot] = next_free_slot;
  69. next_free_slot = slot;
  70. return RESULT_SUCCESS;
  71. }
  72. bool HandleTable::IsValid(Handle handle) const {
  73. size_t slot = GetSlot(handle);
  74. u16 generation = GetGeneration(handle);
  75. return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
  76. }
  77. SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
  78. if (handle == CurrentThread) {
  79. return GetCurrentThread();
  80. } else if (handle == CurrentProcess) {
  81. return g_current_process;
  82. }
  83. if (!IsValid(handle)) {
  84. return nullptr;
  85. }
  86. return objects[GetSlot(handle)];
  87. }
  88. void HandleTable::Clear() {
  89. for (u16 i = 0; i < MAX_COUNT; ++i) {
  90. generations[i] = i + 1;
  91. objects[i] = nullptr;
  92. }
  93. next_free_slot = 0;
  94. }
  95. /// Initialize the kernel
  96. void Init() {
  97. ConfigMem::Init();
  98. SharedPage::Init();
  99. // TODO(yuriks): The memory type parameter needs to be determined by the ExHeader field instead
  100. // For now it defaults to the one with a largest allocation to the app
  101. Kernel::MemoryInit(2); // Allocates 96MB to the application
  102. Kernel::ResourceLimitsInit();
  103. Kernel::ThreadingInit();
  104. Kernel::TimersInit();
  105. Object::next_object_id = 0;
  106. // TODO(Subv): Start the process ids from 10 for now, as lower PIDs are
  107. // reserved for low-level services
  108. Process::next_process_id = 10;
  109. }
  110. /// Shutdown the kernel
  111. void Shutdown() {
  112. g_handle_table.Clear(); // Free all kernel objects
  113. Kernel::ThreadingShutdown();
  114. g_current_process = nullptr;
  115. Kernel::TimersShutdown();
  116. Kernel::ResourceLimitsShutdown();
  117. Kernel::MemoryShutdown();
  118. }
  119. } // namespace