handle_table.cpp 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <utility>
  5. #include "common/assert.h"
  6. #include "common/logging/log.h"
  7. #include "core/core.h"
  8. #include "core/hle/kernel/errors.h"
  9. #include "core/hle/kernel/handle_table.h"
  10. #include "core/hle/kernel/kernel.h"
  11. #include "core/hle/kernel/process.h"
  12. #include "core/hle/kernel/thread.h"
  13. namespace Kernel {
  14. HandleTable g_handle_table;
  15. HandleTable::HandleTable() {
  16. next_generation = 1;
  17. Clear();
  18. }
  19. ResultVal<Handle> HandleTable::Create(SharedPtr<Object> obj) {
  20. DEBUG_ASSERT(obj != nullptr);
  21. u16 slot = next_free_slot;
  22. if (slot >= generations.size()) {
  23. NGLOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
  24. return ERR_OUT_OF_HANDLES;
  25. }
  26. next_free_slot = generations[slot];
  27. u16 generation = next_generation++;
  28. // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
  29. // CTR-OS doesn't use generation 0, so skip straight to 1.
  30. if (next_generation >= (1 << 15))
  31. next_generation = 1;
  32. generations[slot] = generation;
  33. objects[slot] = std::move(obj);
  34. Handle handle = generation | (slot << 15);
  35. return MakeResult<Handle>(handle);
  36. }
  37. ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
  38. SharedPtr<Object> object = GetGeneric(handle);
  39. if (object == nullptr) {
  40. NGLOG_ERROR(Kernel, "Tried to duplicate invalid handle: {:08X}", handle);
  41. return ERR_INVALID_HANDLE;
  42. }
  43. return Create(std::move(object));
  44. }
  45. ResultCode HandleTable::Close(Handle handle) {
  46. if (!IsValid(handle))
  47. return ERR_INVALID_HANDLE;
  48. u16 slot = GetSlot(handle);
  49. objects[slot] = nullptr;
  50. generations[slot] = next_free_slot;
  51. next_free_slot = slot;
  52. return RESULT_SUCCESS;
  53. }
  54. bool HandleTable::IsValid(Handle handle) const {
  55. size_t slot = GetSlot(handle);
  56. u16 generation = GetGeneration(handle);
  57. return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
  58. }
  59. SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
  60. if (handle == CurrentThread) {
  61. return GetCurrentThread();
  62. } else if (handle == CurrentProcess) {
  63. return Core::CurrentProcess();
  64. }
  65. if (!IsValid(handle)) {
  66. return nullptr;
  67. }
  68. return objects[GetSlot(handle)];
  69. }
  70. void HandleTable::Clear() {
  71. for (u16 i = 0; i < MAX_COUNT; ++i) {
  72. generations[i] = i + 1;
  73. objects[i] = nullptr;
  74. }
  75. next_free_slot = 0;
  76. }
  77. } // namespace Kernel