summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2014-12-21 10:04:08 -0200
committerGravatar Yuri Kunde Schlesner2014-12-28 11:52:55 -0200
commit7e2903cb74050d846f2da951dff7e84aee13761b (patch)
tree621c9245d2dd393a9569b1b4192f50a27d831972 /src
parentKernel: Replace GetStaticHandleType by HANDLE_TYPE constants (diff)
downloadyuzu-7e2903cb74050d846f2da951dff7e84aee13761b.tar.gz
yuzu-7e2903cb74050d846f2da951dff7e84aee13761b.tar.xz
yuzu-7e2903cb74050d846f2da951dff7e84aee13761b.zip
Kernel: New handle manager
This handle manager more closely mirrors the behaviour of the CTR-OS one. In addition object ref-counts and support for DuplicateHandle have been added. Note that support for DuplicateHandle is still experimental, since parts of the kernel still use Handles internally, which will likely cause troubles if two different handles to the same object are used to e.g. wait on a synchronization primitive.
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp3
-rw-r--r--src/core/hle/kernel/event.cpp3
-rw-r--r--src/core/hle/kernel/kernel.cpp118
-rw-r--r--src/core/hle/kernel/kernel.h190
-rw-r--r--src/core/hle/kernel/mutex.cpp5
-rw-r--r--src/core/hle/kernel/semaphore.cpp3
-rw-r--r--src/core/hle/kernel/shared_memory.cpp3
-rw-r--r--src/core/hle/kernel/thread.cpp3
-rw-r--r--src/core/hle/kernel/thread.h3
-rw-r--r--src/core/hle/service/fs/archive.cpp10
-rw-r--r--src/core/hle/service/service.cpp3
-rw-r--r--src/core/hle/service/service.h5
-rw-r--r--src/core/hle/svc.cpp28
13 files changed, 209 insertions, 168 deletions
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index acdbc92b3..38705e3cd 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -62,7 +62,8 @@ ResultCode ArbitrateAddress(Handle handle, ArbitrationType type, u32 address, s3
62/// Create an address arbiter 62/// Create an address arbiter
63AddressArbiter* CreateAddressArbiter(Handle& handle, const std::string& name) { 63AddressArbiter* CreateAddressArbiter(Handle& handle, const std::string& name) {
64 AddressArbiter* address_arbiter = new AddressArbiter; 64 AddressArbiter* address_arbiter = new AddressArbiter;
65 handle = Kernel::g_handle_table.Create(address_arbiter); 65 // TOOD(yuriks): Fix error reporting
66 handle = Kernel::g_handle_table.Create(address_arbiter).ValueOr(INVALID_HANDLE);
66 address_arbiter->name = name; 67 address_arbiter->name = name;
67 return address_arbiter; 68 return address_arbiter;
68} 69}
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 6a0e294cb..e43c3ee4e 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -129,7 +129,8 @@ ResultCode ClearEvent(Handle handle) {
129Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) { 129Event* CreateEvent(Handle& handle, const ResetType reset_type, const std::string& name) {
130 Event* evt = new Event; 130 Event* evt = new Event;
131 131
132 handle = Kernel::g_handle_table.Create(evt); 132 // TOOD(yuriks): Fix error reporting
133 handle = Kernel::g_handle_table.Create(evt).ValueOr(INVALID_HANDLE);
133 134
134 evt->locked = true; 135 evt->locked = true;
135 evt->permanent_locked = false; 136 evt->permanent_locked = false;
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
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 27c406ad4..7f86fd07d 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -12,13 +12,17 @@
12typedef u32 Handle; 12typedef u32 Handle;
13typedef s32 Result; 13typedef s32 Result;
14 14
15const Handle INVALID_HANDLE = 0;
16
15namespace Kernel { 17namespace Kernel {
16 18
17// From kernel.h. Declarations duplicated here to avoid a circular header dependency. 19// TODO: Verify code
18class Thread; 20const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
19Thread* GetCurrentThread(); 21 ErrorSummary::OutOfResource, ErrorLevel::Temporary);
22// TOOD: Verify code
23const ResultCode ERR_INVALID_HANDLE = InvalidHandle(ErrorModule::Kernel);
20 24
21enum KernelHandle { 25enum KernelHandle : Handle {
22 CurrentThread = 0xFFFF8000, 26 CurrentThread = 0xFFFF8000,
23 CurrentProcess = 0xFFFF8001, 27 CurrentProcess = 0xFFFF8001,
24}; 28};
@@ -61,103 +65,127 @@ public:
61 LOG_ERROR(Kernel, "(UNIMPLEMENTED)"); 65 LOG_ERROR(Kernel, "(UNIMPLEMENTED)");
62 return UnimplementedFunction(ErrorModule::Kernel); 66 return UnimplementedFunction(ErrorModule::Kernel);
63 } 67 }
64};
65 68
66class HandleTable : NonCopyable { 69private:
67public: 70 friend void intrusive_ptr_add_ref(Object*);
68 HandleTable(); 71 friend void intrusive_ptr_release(Object*);
69 ~HandleTable() {}
70 72
71 // Allocates a handle within the range and inserts the object into the map. 73 unsigned int ref_count = 0;
72 Handle Create(Object* obj, int range_bottom=INITIAL_NEXT_ID, int range_top=0x7FFFFFFF); 74};
73 75
74 static Object* CreateByIDType(int type); 76// Special functions that will later be used by boost::instrusive_ptr to do automatic ref-counting
77inline void intrusive_ptr_add_ref(Object* object) {
78 ++object->ref_count;
79}
75 80
76 template <class T> 81inline void intrusive_ptr_release(Object* object) {
77 void Destroy(Handle handle) { 82 if (--object->ref_count == 0) {
78 if (Get<T>(handle)) { 83 delete object;
79 occupied[handle - HANDLE_OFFSET] = false;
80 delete pool[handle - HANDLE_OFFSET];
81 }
82 } 84 }
85}
83 86
84 bool IsValid(Handle handle) const; 87/**
88 * This class allows the creation of Handles, which are references to objects that can be tested
89 * for validity and looked up. Here they are used to pass references to kernel objects to/from the
90 * emulated process. it has been designed so that it follows the same handle format and has
91 * approximately the same restrictions as the handle manager in the CTR-OS.
92 *
93 * Handles contain two sub-fields: a slot index (bits 31:15) and a generation value (bits 14:0).
94 * The slot index is used to index into the arrays in this class to access the data corresponding
95 * to the Handle.
96 *
97 * To prevent accidental use of a freed Handle whose slot has already been reused, a global counter
98 * is kept and incremented every time a Handle is created. This is the Handle's "generation". The
99 * value of the counter is stored into the Handle as well as in the handle table (in the
100 * "generations" array). When looking up a handle, the Handle's generation must match with the
101 * value stored on the class, otherwise the Handle is considered invalid.
102 *
103 * To find free slots when allocating a Handle without needing to scan the entire object array, the
104 * generations field of unallocated slots is re-purposed as a linked list of indices to free slots.
105 * When a Handle is created, an index is popped off the list and used for the new Handle. When it
106 * is destroyed, it is again pushed onto the list to be re-used by the next allocation. It is
107 * likely that this allocation strategy differs from the one used in CTR-OS, but this hasn't been
108 * verified and isn't likely to cause any problems.
109 */
110class HandleTable final : NonCopyable {
111public:
112 HandleTable();
85 113
86 template <class T> 114 /**
87 T* Get(Handle handle) { 115 * Allocates a handle for the given object.
88 if (handle == CurrentThread) { 116 * @return The created Handle or one of the following errors:
89 return reinterpret_cast<T*>(GetCurrentThread()); 117 * - `ERR_OUT_OF_HANDLES`: the maximum number of handles has been exceeded.
90 } 118 */
119 ResultVal<Handle> Create(Object* obj);
91 120
92 if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) { 121 /**
93 if (handle != 0) { 122 * Returns a new handle that points to the same object as the passed in handle.
94 LOG_ERROR(Kernel, "Bad object handle %08x", handle); 123 * @return The duplicated Handle or one of the following errors:
95 } 124 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
96 return nullptr; 125 * - Any errors returned by `Create()`.
97 } else { 126 */
98 Object* t = pool[handle - HANDLE_OFFSET]; 127 ResultVal<Handle> Duplicate(Handle handle);
99 if (t->GetHandleType() != T::HANDLE_TYPE) {
100 LOG_ERROR(Kernel, "Wrong object type for %08x", handle);
101 return nullptr;
102 }
103 return static_cast<T*>(t);
104 }
105 }
106 128
107 // ONLY use this when you know the handle is valid. 129 /**
108 template <class T> 130 * Closes a handle, removing it from the table and decreasing the object's ref-count.
109 T *GetFast(Handle handle) { 131 * @return `RESULT_SUCCESS` or one of the following errors:
110 if (handle == CurrentThread) { 132 * - `ERR_INVALID_HANDLE`: an invalid handle was passed in.
111 return reinterpret_cast<T*>(GetCurrentThread()); 133 */
112 } 134 ResultCode Close(Handle handle);
113 135
114 const Handle realHandle = handle - HANDLE_OFFSET; 136 /// Checks if a handle is valid and points to an existing object.
115 _dbg_assert_(Kernel, realHandle >= 0 && realHandle < MAX_COUNT && occupied[realHandle]); 137 bool IsValid(Handle handle) const;
116 return static_cast<T*>(pool[realHandle]);
117 }
118 138
119 template <class T, typename ArgT> 139 /**
120 void Iterate(bool func(T*, ArgT), ArgT arg) { 140 * Looks up a handle.
121 int type = T::GetStaticIDType(); 141 * @returns Pointer to the looked-up object, or `nullptr` if the handle is not valid.
122 for (int i = 0; i < MAX_COUNT; i++) 142 */
123 { 143 Object* GetGeneric(Handle handle) const;
124 if (!occupied[i])
125 continue;
126 T* t = static_cast<T*>(pool[i]);
127 if (t->GetIDType() == type) {
128 if (!func(t, arg))
129 break;
130 }
131 }
132 }
133 144
134 bool GetIDType(Handle handle, HandleType* type) const { 145 /**
135 if ((handle < HANDLE_OFFSET) || (handle >= HANDLE_OFFSET + MAX_COUNT) || 146 * Looks up a handle while verifying its type.
136 !occupied[handle - HANDLE_OFFSET]) { 147 * @returns Pointer to the looked-up object, or `nullptr` if the handle is not valid or its
137 LOG_ERROR(Kernel, "Bad object handle %08X", handle); 148 * type differs from the handle type `T::HANDLE_TYPE`.
138 return false; 149 */
150 template <class T>
151 T* Get(Handle handle) const {
152 Object* object = GetGeneric(handle);
153 if (object != nullptr && object->GetHandleType() == T::HANDLE_TYPE) {
154 return static_cast<T*>(object);
139 } 155 }
140 Object* t = pool[handle - HANDLE_OFFSET]; 156 return nullptr;
141 *type = t->GetHandleType();
142 return true;
143 } 157 }
144 158
145 Object* &operator [](Handle handle); 159 /// Closes all handles held in this table.
146 void List();
147 void Clear(); 160 void Clear();
148 int GetCount() const;
149 161
150private: 162private:
163 /**
164 * This is the maximum limit of handles allowed per process in CTR-OS. It can be further
165 * reduced by ExHeader values, but this is not emulated here.
166 */
167 static const size_t MAX_COUNT = 4096;
168
169 static size_t GetSlot(Handle handle) { return handle >> 15; }
170 static u16 GetGeneration(Handle handle) { return handle & 0x7FFF; }
171
172 /// Stores the Object referenced by the handle or null if the slot is empty.
173 std::array<Object*, MAX_COUNT> objects;
151 174
152 enum { 175 /**
153 MAX_COUNT = 0x1000, 176 * The value of `next_generation` when the handle was created, used to check for validity. For
154 HANDLE_OFFSET = 0x100, 177 * empty slots, contains the index of the next free slot in the list.
155 INITIAL_NEXT_ID = 0x10, 178 */
156 }; 179 std::array<u16, MAX_COUNT> generations;
180
181 /**
182 * Global counter of the number of created handles. Stored in `generations` when a handle is
183 * created, and wraps around to 1 when it hits 0x8000.
184 */
185 u16 next_generation;
157 186
158 std::array<Object*, MAX_COUNT> pool; 187 /// Head of the free slots linked list.
159 std::array<bool, MAX_COUNT> occupied; 188 u16 next_free_slot;
160 int next_id;
161}; 189};
162 190
163extern HandleTable g_handle_table; 191extern HandleTable g_handle_table;
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index 08462376d..558068c79 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -87,7 +87,7 @@ void ReleaseThreadMutexes(Handle thread) {
87 87
88 // Release every mutex that the thread holds, and resume execution on the waiting threads 88 // Release every mutex that the thread holds, and resume execution on the waiting threads
89 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) { 89 for (MutexMap::iterator iter = locked.first; iter != locked.second; ++iter) {
90 Mutex* mutex = g_handle_table.GetFast<Mutex>(iter->second); 90 Mutex* mutex = g_handle_table.Get<Mutex>(iter->second);
91 ResumeWaitingThread(mutex); 91 ResumeWaitingThread(mutex);
92 } 92 }
93 93
@@ -136,7 +136,8 @@ ResultCode ReleaseMutex(Handle handle) {
136 */ 136 */
137Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) { 137Mutex* CreateMutex(Handle& handle, bool initial_locked, const std::string& name) {
138 Mutex* mutex = new Mutex; 138 Mutex* mutex = new Mutex;
139 handle = Kernel::g_handle_table.Create(mutex); 139 // TODO(yuriks): Fix error reporting
140 handle = Kernel::g_handle_table.Create(mutex).ValueOr(INVALID_HANDLE);
140 141
141 mutex->locked = mutex->initial_locked = initial_locked; 142 mutex->locked = mutex->initial_locked = initial_locked;
142 mutex->name = name; 143 mutex->name = name;
diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp
index 1dee15f10..6bc8066a6 100644
--- a/src/core/hle/kernel/semaphore.cpp
+++ b/src/core/hle/kernel/semaphore.cpp
@@ -57,7 +57,8 @@ ResultCode CreateSemaphore(Handle* handle, s32 initial_count,
57 ErrorSummary::WrongArgument, ErrorLevel::Permanent); 57 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
58 58
59 Semaphore* semaphore = new Semaphore; 59 Semaphore* semaphore = new Semaphore;
60 *handle = g_handle_table.Create(semaphore); 60 // TOOD(yuriks): Fix error reporting
61 *handle = g_handle_table.Create(semaphore).ValueOr(INVALID_HANDLE);
61 62
62 // When the semaphore is created, some slots are reserved for other threads, 63 // When the semaphore is created, some slots are reserved for other threads,
63 // and the rest is reserved for the caller thread 64 // and the rest is reserved for the caller thread
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index bd9d947a3..cea1f6fa1 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -32,7 +32,8 @@ public:
32 */ 32 */
33SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) { 33SharedMemory* CreateSharedMemory(Handle& handle, const std::string& name) {
34 SharedMemory* shared_memory = new SharedMemory; 34 SharedMemory* shared_memory = new SharedMemory;
35 handle = Kernel::g_handle_table.Create(shared_memory); 35 // TOOD(yuriks): Fix error reporting
36 handle = Kernel::g_handle_table.Create(shared_memory).ValueOr(INVALID_HANDLE);
36 shared_memory->name = name; 37 shared_memory->name = name;
37 return shared_memory; 38 return shared_memory;
38} 39}
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 2739bdd52..872df2d14 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -341,7 +341,8 @@ Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 prio
341 341
342 Thread* thread = new Thread; 342 Thread* thread = new Thread;
343 343
344 handle = Kernel::g_handle_table.Create(thread); 344 // TOOD(yuriks): Fix error reporting
345 handle = Kernel::g_handle_table.Create(thread).ValueOr(INVALID_HANDLE);
345 346
346 thread_queue.push_back(handle); 347 thread_queue.push_back(handle);
347 thread_ready_queue.prepare(priority); 348 thread_ready_queue.prepare(priority);
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 9396b6b26..0e1397cd9 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -77,9 +77,6 @@ Handle ArbitrateHighestPriorityThread(u32 arbiter, u32 address);
77/// Arbitrate all threads currently waiting... 77/// Arbitrate all threads currently waiting...
78void ArbitrateAllThreads(u32 arbiter, u32 address); 78void ArbitrateAllThreads(u32 arbiter, u32 address);
79 79
80/// Gets the current thread
81Thread* GetCurrentThread();
82
83/// Gets the current thread handle 80/// Gets the current thread handle
84Handle GetCurrentThreadHandle(); 81Handle GetCurrentThreadHandle();
85 82
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 5746b58e5..487bf3aa7 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -133,7 +133,7 @@ public:
133 case FileCommand::Close: 133 case FileCommand::Close:
134 { 134 {
135 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); 135 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
136 Kernel::g_handle_table.Destroy<File>(GetHandle()); 136 backend->Close();
137 break; 137 break;
138 } 138 }
139 139
@@ -189,7 +189,7 @@ public:
189 case DirectoryCommand::Close: 189 case DirectoryCommand::Close:
190 { 190 {
191 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str()); 191 LOG_TRACE(Service_FS, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
192 Kernel::g_handle_table.Destroy<Directory>(GetHandle()); 192 backend->Close();
193 break; 193 break;
194 } 194 }
195 195
@@ -283,7 +283,8 @@ ResultVal<Handle> OpenFileFromArchive(ArchiveHandle archive_handle, const FileSy
283 } 283 }
284 284
285 auto file = Common::make_unique<File>(std::move(backend), path); 285 auto file = Common::make_unique<File>(std::move(backend), path);
286 Handle handle = Kernel::g_handle_table.Create(file.release()); 286 // TOOD(yuriks): Fix error reporting
287 Handle handle = Kernel::g_handle_table.Create(file.release()).ValueOr(INVALID_HANDLE);
287 return MakeResult<Handle>(handle); 288 return MakeResult<Handle>(handle);
288} 289}
289 290
@@ -388,7 +389,8 @@ ResultVal<Handle> OpenDirectoryFromArchive(ArchiveHandle archive_handle, const F
388 } 389 }
389 390
390 auto directory = Common::make_unique<Directory>(std::move(backend), path); 391 auto directory = Common::make_unique<Directory>(std::move(backend), path);
391 Handle handle = Kernel::g_handle_table.Create(directory.release()); 392 // TOOD(yuriks): Fix error reporting
393 Handle handle = Kernel::g_handle_table.Create(directory.release()).ValueOr(INVALID_HANDLE);
392 return MakeResult<Handle>(handle); 394 return MakeResult<Handle>(handle);
393} 395}
394 396
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index e9a7973b3..0f3cc2aa8 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -56,7 +56,8 @@ Manager::~Manager() {
56 56
57/// Add a service to the manager (does not create it though) 57/// Add a service to the manager (does not create it though)
58void Manager::AddService(Interface* service) { 58void Manager::AddService(Interface* service) {
59 m_port_map[service->GetPortName()] = Kernel::g_handle_table.Create(service); 59 // TOOD(yuriks): Fix error reporting
60 m_port_map[service->GetPortName()] = Kernel::g_handle_table.Create(service).ValueOr(INVALID_HANDLE);
60 m_services.push_back(service); 61 m_services.push_back(service);
61} 62}
62 63
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 9d5828fd0..28b4ccd17 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -54,7 +54,8 @@ public:
54 54
55 /// Allocates a new handle for the service 55 /// Allocates a new handle for the service
56 Handle CreateHandle(Kernel::Object *obj) { 56 Handle CreateHandle(Kernel::Object *obj) {
57 Handle handle = Kernel::g_handle_table.Create(obj); 57 // TODO(yuriks): Fix error reporting
58 Handle handle = Kernel::g_handle_table.Create(obj).ValueOr(INVALID_HANDLE);
58 m_handles.push_back(handle); 59 m_handles.push_back(handle);
59 return handle; 60 return handle;
60 } 61 }
@@ -62,7 +63,7 @@ public:
62 /// Frees a handle from the service 63 /// Frees a handle from the service
63 template <class T> 64 template <class T>
64 void DeleteHandle(const Handle handle) { 65 void DeleteHandle(const Handle handle) {
65 Kernel::g_handle_table.Destroy<T>(handle); 66 Kernel::g_handle_table.Close(handle);
66 m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end()); 67 m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end());
67 } 68 }
68 69
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index a48ac09a3..25944fc68 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -119,11 +119,9 @@ static Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
119 // TODO(bunnei): Do something with nano_seconds, currently ignoring this 119 // TODO(bunnei): Do something with nano_seconds, currently ignoring this
120 bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated 120 bool wait_infinite = (nano_seconds == -1); // Used to wait until a thread has terminated
121 121
122 if (!Kernel::g_handle_table.IsValid(handle)) { 122 Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handle);
123 if (object == nullptr)
123 return InvalidHandle(ErrorModule::Kernel).raw; 124 return InvalidHandle(ErrorModule::Kernel).raw;
124 }
125 Kernel::Object* object = Kernel::g_handle_table.GetFast<Kernel::Object>(handle);
126 _dbg_assert_(Kernel, object != nullptr);
127 125
128 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(), 126 LOG_TRACE(Kernel_SVC, "called handle=0x%08X(%s:%s), nanoseconds=%lld", handle, object->GetTypeName().c_str(),
129 object->GetName().c_str(), nano_seconds); 127 object->GetName().c_str(), nano_seconds);
@@ -150,10 +148,9 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
150 148
151 // Iterate through each handle, synchronize kernel object 149 // Iterate through each handle, synchronize kernel object
152 for (s32 i = 0; i < handle_count; i++) { 150 for (s32 i = 0; i < handle_count; i++) {
153 if (!Kernel::g_handle_table.IsValid(handles[i])) { 151 Kernel::Object* object = Kernel::g_handle_table.GetGeneric(handles[i]);
152 if (object == nullptr)
154 return InvalidHandle(ErrorModule::Kernel).raw; 153 return InvalidHandle(ErrorModule::Kernel).raw;
155 }
156 Kernel::Object* object = Kernel::g_handle_table.GetFast<Kernel::Object>(handles[i]);
157 154
158 LOG_TRACE(Kernel_SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(), 155 LOG_TRACE(Kernel_SVC, "\thandle[%d] = 0x%08X(%s:%s)", i, handles[i], object->GetTypeName().c_str(),
159 object->GetName().c_str()); 156 object->GetName().c_str());
@@ -321,19 +318,12 @@ static Result CreateEvent(Handle* evt, u32 reset_type) {
321 318
322/// Duplicates a kernel handle 319/// Duplicates a kernel handle
323static Result DuplicateHandle(Handle* out, Handle handle) { 320static Result DuplicateHandle(Handle* out, Handle handle) {
324 LOG_WARNING(Kernel_SVC, "(STUBBED) called handle=0x%08X", handle); 321 ResultVal<Handle> out_h = Kernel::g_handle_table.Duplicate(handle);
325 322 if (out_h.Succeeded()) {
326 // Translate kernel handles -> real handles 323 *out = *out_h;
327 if (handle == Kernel::CurrentThread) { 324 LOG_TRACE(Kernel_SVC, "duplicated 0x%08X to 0x%08X", handle, *out);
328 handle = Kernel::GetCurrentThreadHandle();
329 } 325 }
330 _assert_msg_(KERNEL, (handle != Kernel::CurrentProcess), 326 return out_h.Code().raw;
331 "(UNIMPLEMENTED) process handle duplication!");
332
333 // TODO(bunnei): FixMe - This is a hack to return the handle that we were asked to duplicate.
334 *out = handle;
335
336 return 0;
337} 327}
338 328
339/// Signals an event 329/// Signals an event