summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/kernel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
-rw-r--r--src/core/hle/kernel/kernel.cpp118
1 files changed, 67 insertions, 51 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index e8bf83a44..e59ed1b57 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -17,73 +17,89 @@ HandleTable g_handle_table;
17u64 g_program_id = 0; 17u64 g_program_id = 0;
18 18
19HandleTable::HandleTable() { 19HandleTable::HandleTable() {
20 next_id = INITIAL_NEXT_ID; 20 next_generation = 1;
21 Clear();
21} 22}
22 23
23Handle HandleTable::Create(Object* obj, int range_bottom, int range_top) { 24ResultVal<Handle> HandleTable::Create(Object* obj) {
24 if (range_top > MAX_COUNT) { 25 _dbg_assert_(Kernel, obj != nullptr);
25 range_top = MAX_COUNT; 26
26 } 27 u16 slot = next_free_slot;
27 if (next_id >= range_bottom && next_id < range_top) { 28 if (slot >= generations.size()) {
28 range_bottom = next_id++; 29 LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
29 } 30 return ERR_OUT_OF_HANDLES;
30 for (int i = range_bottom; i < range_top; i++) {
31 if (!occupied[i]) {
32 occupied[i] = true;
33 pool[i] = obj;
34 pool[i]->handle = i + HANDLE_OFFSET;
35 return i + HANDLE_OFFSET;
36 }
37 } 31 }
38 LOG_ERROR(Kernel, "Unable to allocate kernel object, too many objects slots in use."); 32 next_free_slot = generations[slot];
39 return 0;
40}
41 33
42bool HandleTable::IsValid(Handle handle) const { 34 u16 generation = next_generation++;
43 int index = handle - HANDLE_OFFSET;
44 if (index < 0)
45 return false;
46 if (index >= MAX_COUNT)
47 return false;
48 35
49 return occupied[index]; 36 // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
37 // CTR-OS doesn't use generation 0, so skip straight to 1.
38 if (next_generation >= (1 << 15)) next_generation = 1;
39
40 generations[slot] = generation;
41 intrusive_ptr_add_ref(obj);
42 objects[slot] = obj;
43
44 Handle handle = generation | (slot << 15);
45 obj->handle = handle;
46 return MakeResult<Handle>(handle);
50} 47}
51 48
52void HandleTable::Clear() { 49ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
53 for (int i = 0; i < MAX_COUNT; i++) { 50 Object* object = GetGeneric(handle);
54 //brutally clear everything, no validation 51 if (object == nullptr) {
55 if (occupied[i]) 52 LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle);
56 delete pool[i]; 53 return ERR_INVALID_HANDLE;
57 occupied[i] = false;
58 } 54 }
59 pool.fill(nullptr); 55 return Create(object);
60 next_id = INITIAL_NEXT_ID;
61} 56}
62 57
63Object* &HandleTable::operator [](Handle handle) 58ResultCode HandleTable::Close(Handle handle) {
64{ 59 if (!IsValid(handle))
65 _dbg_assert_msg_(Kernel, IsValid(handle), "GRABBING UNALLOCED KERNEL OBJ"); 60 return ERR_INVALID_HANDLE;
66 return pool[handle - HANDLE_OFFSET]; 61
62 size_t slot = GetSlot(handle);
63 u16 generation = GetGeneration(handle);
64
65 intrusive_ptr_release(objects[slot]);
66 objects[slot] = nullptr;
67
68 generations[generation] = next_free_slot;
69 next_free_slot = slot;
70 return RESULT_SUCCESS;
67} 71}
68 72
69void HandleTable::List() { 73bool HandleTable::IsValid(Handle handle) const {
70 for (int i = 0; i < MAX_COUNT; i++) { 74 size_t slot = GetSlot(handle);
71 if (occupied[i]) { 75 u16 generation = GetGeneration(handle);
72 if (pool[i]) { 76
73 LOG_DEBUG(Kernel, "KO %i: %s \"%s\"", i + HANDLE_OFFSET, pool[i]->GetTypeName().c_str(), 77 return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
74 pool[i]->GetName().c_str());
75 }
76 }
77 }
78} 78}
79 79
80int HandleTable::GetCount() const { 80Object* HandleTable::GetGeneric(Handle handle) const {
81 return std::count(occupied.begin(), occupied.end(), true); 81 if (handle == CurrentThread) {
82 // TODO(yuriks) Directly return the pointer once this is possible.
83 handle = GetCurrentThreadHandle();
84 } else if (handle == CurrentProcess) {
85 LOG_ERROR(Kernel, "Current process (%08X) pseudo-handle not supported", CurrentProcess);
86 return nullptr;
87 }
88
89 if (!IsValid(handle)) {
90 return nullptr;
91 }
92 return objects[GetSlot(handle)];
82} 93}
83 94
84Object* HandleTable::CreateByIDType(int type) { 95void HandleTable::Clear() {
85 LOG_ERROR(Kernel, "Unimplemented: %d.", type); 96 for (size_t i = 0; i < MAX_COUNT; ++i) {
86 return nullptr; 97 generations[i] = i + 1;
98 if (objects[i] != nullptr)
99 intrusive_ptr_release(objects[i]);
100 objects[i] = nullptr;
101 }
102 next_free_slot = 0;
87} 103}
88 104
89/// Initialize the kernel 105/// Initialize the kernel