summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/kernel.cpp
diff options
context:
space:
mode:
authorGravatar darkf2014-12-29 19:47:41 -0800
committerGravatar darkf2014-12-29 19:47:41 -0800
commit8ba9ac0f74abb0408a26207a76a0c1808bad8de0 (patch)
treef1c7c3393fa726435b5b90bf335567c93e528ef1 /src/core/hle/kernel/kernel.cpp
parentAdd comment regarding __WIN32__ in SkyEye code (diff)
parentMerge pull request #367 from bunnei/usat_ssat (diff)
downloadyuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.gz
yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.tar.xz
yuzu-8ba9ac0f74abb0408a26207a76a0c1808bad8de0.zip
Fix merge conflicts
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
-rw-r--r--src/core/hle/kernel/kernel.cpp139
1 files changed, 74 insertions, 65 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 018000abd..e59ed1b57 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -1,106 +1,117 @@
1// Copyright 2014 Citra Emulator Project / PPSSPP Project 1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm>
6
5#include "common/common.h" 7#include "common/common.h"
6 8
7#include "core/core.h" 9#include "core/core.h"
8#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
9#include "core/hle/kernel/thread.h" 11#include "core/hle/kernel/thread.h"
10#include "core/hle/kernel/archive.h"
11 12
12namespace Kernel { 13namespace Kernel {
13 14
14Handle g_main_thread = 0; 15Handle g_main_thread = 0;
15ObjectPool g_object_pool; 16HandleTable g_handle_table;
17u64 g_program_id = 0;
16 18
17ObjectPool::ObjectPool() { 19HandleTable::HandleTable() {
18 next_id = INITIAL_NEXT_ID; 20 next_generation = 1;
21 Clear();
19} 22}
20 23
21Handle ObjectPool::Create(Object* obj, int range_bottom, int range_top) { 24ResultVal<Handle> HandleTable::Create(Object* obj) {
22 if (range_top > MAX_COUNT) { 25 _dbg_assert_(Kernel, obj != nullptr);
23 range_top = MAX_COUNT; 26
24 } 27 u16 slot = next_free_slot;
25 if (next_id >= range_bottom && next_id < range_top) { 28 if (slot >= generations.size()) {
26 range_bottom = next_id++; 29 LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
27 } 30 return ERR_OUT_OF_HANDLES;
28 for (int i = range_bottom; i < range_top; i++) {
29 if (!occupied[i]) {
30 occupied[i] = true;
31 pool[i] = obj;
32 pool[i]->handle = i + HANDLE_OFFSET;
33 return i + HANDLE_OFFSET;
34 }
35 } 31 }
36 ERROR_LOG(HLE, "Unable to allocate kernel object, too many objects slots in use."); 32 next_free_slot = generations[slot];
37 return 0; 33
38} 34 u16 generation = next_generation++;
39 35
40bool ObjectPool::IsValid(Handle handle) { 36 // Overflow count so it fits in the 15 bits dedicated to the generation in the handle.
41 int index = handle - HANDLE_OFFSET; 37 // CTR-OS doesn't use generation 0, so skip straight to 1.
42 if (index < 0) 38 if (next_generation >= (1 << 15)) next_generation = 1;
43 return false;
44 if (index >= MAX_COUNT)
45 return false;
46 39
47 return occupied[index]; 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);
48} 47}
49 48
50void ObjectPool::Clear() { 49ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
51 for (int i = 0; i < MAX_COUNT; i++) { 50 Object* object = GetGeneric(handle);
52 //brutally clear everything, no validation 51 if (object == nullptr) {
53 if (occupied[i]) 52 LOG_ERROR(Kernel, "Tried to duplicate invalid handle: %08X", handle);
54 delete pool[i]; 53 return ERR_INVALID_HANDLE;
55 occupied[i] = false;
56 } 54 }
57 pool.fill(nullptr); 55 return Create(object);
58 next_id = INITIAL_NEXT_ID; 56}
57
58ResultCode HandleTable::Close(Handle handle) {
59 if (!IsValid(handle))
60 return ERR_INVALID_HANDLE;
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;
59} 71}
60 72
61Object* &ObjectPool::operator [](Handle handle) 73bool HandleTable::IsValid(Handle handle) const {
62{ 74 size_t slot = GetSlot(handle);
63 _dbg_assert_msg_(KERNEL, IsValid(handle), "GRABBING UNALLOCED KERNEL OBJ"); 75 u16 generation = GetGeneration(handle);
64 return pool[handle - HANDLE_OFFSET]; 76
77 return slot < MAX_COUNT && objects[slot] != nullptr && generations[slot] == generation;
65} 78}
66 79
67void ObjectPool::List() { 80Object* HandleTable::GetGeneric(Handle handle) const {
68 for (int i = 0; i < MAX_COUNT; i++) { 81 if (handle == CurrentThread) {
69 if (occupied[i]) { 82 // TODO(yuriks) Directly return the pointer once this is possible.
70 if (pool[i]) { 83 handle = GetCurrentThreadHandle();
71 INFO_LOG(KERNEL, "KO %i: %s \"%s\"", i + HANDLE_OFFSET, pool[i]->GetTypeName().c_str(), 84 } else if (handle == CurrentProcess) {
72 pool[i]->GetName().c_str()); 85 LOG_ERROR(Kernel, "Current process (%08X) pseudo-handle not supported", CurrentProcess);
73 } 86 return nullptr;
74 }
75 } 87 }
76}
77 88
78int ObjectPool::GetCount() { 89 if (!IsValid(handle)) {
79 int count = 0; 90 return nullptr;
80 for (int i = 0; i < MAX_COUNT; i++) {
81 if (occupied[i])
82 count++;
83 } 91 }
84 return count; 92 return objects[GetSlot(handle)];
85} 93}
86 94
87Object* ObjectPool::CreateByIDType(int type) { 95void HandleTable::Clear() {
88 ERROR_LOG(COMMON, "Unimplemented: %d.", type); 96 for (size_t i = 0; i < MAX_COUNT; ++i) {
89 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;
90} 103}
91 104
92/// Initialize the kernel 105/// Initialize the kernel
93void Init() { 106void Init() {
94 Kernel::ThreadingInit(); 107 Kernel::ThreadingInit();
95 Kernel::ArchiveInit();
96} 108}
97 109
98/// Shutdown the kernel 110/// Shutdown the kernel
99void Shutdown() { 111void Shutdown() {
100 Kernel::ThreadingShutdown(); 112 Kernel::ThreadingShutdown();
101 Kernel::ArchiveShutdown();
102 113
103 g_object_pool.Clear(); // Free all kernel objects 114 g_handle_table.Clear(); // Free all kernel objects
104} 115}
105 116
106/** 117/**
@@ -109,8 +120,6 @@ void Shutdown() {
109 * @return True on success, otherwise false 120 * @return True on success, otherwise false
110 */ 121 */
111bool LoadExec(u32 entry_point) { 122bool LoadExec(u32 entry_point) {
112 Init();
113
114 Core::g_app_core->SetPC(entry_point); 123 Core::g_app_core->SetPC(entry_point);
115 124
116 // 0x30 is the typical main thread priority I've seen used so far 125 // 0x30 is the typical main thread priority I've seen used so far