Skip to content

Instantly share code, notes, and snippets.

@archshift
Created December 6, 2014 06:38
Show Gist options
  • Save archshift/b7381db5b39ed2c3a234 to your computer and use it in GitHub Desktop.
Save archshift/b7381db5b39ed2c3a234 to your computer and use it in GitHub Desktop.
diff --git a/src/core/hle/kernel/archive.cpp b/src/core/hle/kernel/archive.cpp
index 647f0de..2e6c73b 100644
--- a/src/core/hle/kernel/archive.cpp
+++ b/src/core/hle/kernel/archive.cpp
@@ -178,7 +178,7 @@ public:
case FileCommand::Close:
{
DEBUG_LOG(KERNEL, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
- Kernel::g_object_pool.Destroy<File>(GetHandle());
+ Kernel::g_object_pool.Destroy(GetHandle());
break;
}
@@ -233,7 +233,7 @@ public:
case DirectoryCommand::Close:
{
DEBUG_LOG(KERNEL, "Close %s %s", GetTypeName().c_str(), GetName().c_str());
- Kernel::g_object_pool.Destroy<Directory>(GetHandle());
+ Kernel::g_object_pool.Destroy(GetHandle());
break;
}
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 80a34c2..e327d44 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -31,6 +31,7 @@ Handle ObjectPool::Create(Object* obj, int range_bottom, int range_top) {
if (!occupied[i]) {
occupied[i] = true;
pool[i] = obj;
+ pool[i]->ref_count++;
pool[i]->handle = i + HANDLE_OFFSET;
return i + HANDLE_OFFSET;
}
@@ -52,8 +53,12 @@ bool ObjectPool::IsValid(Handle handle) const {
void ObjectPool::Clear() {
for (int i = 0; i < MAX_COUNT; i++) {
//brutally clear everything, no validation
- if (occupied[i])
- delete pool[i];
+ if (occupied[i]) {
+ if (pool[i]->ref_count == 1)
+ delete pool[i];
+ else
+ pool[i]->ref_count--;
+ }
occupied[i] = false;
}
pool.fill(nullptr);
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 00a2228..46e1c9b 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -66,6 +66,8 @@ public:
* @return True if the current thread should wait as a result of the wait
*/
virtual ResultVal<bool> WaitSynchronization() = 0;
+
+ int ref_count;
};
class ObjectPool : NonCopyable {
@@ -78,15 +80,29 @@ public:
static Object* CreateByIDType(int type);
- template <class T>
+ bool IsValid(Handle handle) const;
+
void Destroy(Handle handle) {
- if (Get<T>(handle)) {
- occupied[handle - HANDLE_OFFSET] = false;
- delete pool[handle - HANDLE_OFFSET];
+ if (IsValid(handle)) {
+ Handle real_handle = handle - HANDLE_OFFSET;
+ occupied[real_handle] = false;
+ if (pool[real_handle]->ref_count == 1) {
+ delete pool[real_handle];
+ pool[real_handle] = nullptr;
+ } else {
+ pool[real_handle]->ref_count--;
+ }
}
}
- bool IsValid(Handle handle) const;
+ Object* Get(Handle handle) {
+ if (handle < HANDLE_OFFSET || handle >= HANDLE_OFFSET + MAX_COUNT || !occupied[handle - HANDLE_OFFSET]) {
+ if (handle != 0)
+ WARN_LOG(KERNEL, "Kernel: Bad object handle %i (%08x)", handle, handle);
+ return nullptr;
+ }
+ return pool[handle - HANDLE_OFFSET];
+ }
template <class T>
T* Get(Handle handle) {
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 20e7fb4..a91c0dd 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -69,9 +69,8 @@ public:
}
/// Frees a handle from the service
- template <class T>
void DeleteHandle(const Handle handle) {
- Kernel::g_object_pool.Destroy<T>(handle);
+ Kernel::g_object_pool.Destroy(handle);
m_handles.erase(std::remove(m_handles.begin(), m_handles.end(), handle), m_handles.end());
}
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index a5805ed..403a63c 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -107,8 +107,9 @@ static Result SendSyncRequest(Handle handle) {
/// Close a handle
static Result CloseHandle(Handle handle) {
- // ImplementMe
- ERROR_LOG(SVC, "(UNIMPLEMENTED) called handle=0x%08X", handle);
+ Kernel::g_object_pool.Destroy(handle);
+
+ ERROR_LOG(SVC, "called handle=0x%08X", handle);
return 0;
}
@@ -310,11 +311,10 @@ static Result DuplicateHandle(Handle* out, Handle handle) {
if (handle == Kernel::CurrentThread) {
handle = Kernel::GetCurrentThreadHandle();
}
- _assert_msg_(KERNEL, (handle != Kernel::CurrentProcess),
- "(UNIMPLEMENTED) process handle duplication!");
- // TODO(bunnei): FixMe - This is a hack to return the handle that we were asked to duplicate.
- *out = handle;
+ *out = Kernel::g_object_pool.Create(Kernel::g_object_pool.Get(handle));
+
+ DEBUG_LOG(SVC, "called handle=0x%08X", handle);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment