summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/kernel.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/kernel.h')
-rw-r--r--src/core/hle/kernel/kernel.h108
1 files changed, 93 insertions, 15 deletions
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 5e5217b78..4d8e388b6 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -8,12 +8,19 @@
#include <array>
#include <string>
+#include <vector>
+
#include "common/common.h"
#include "core/hle/result.h"
typedef u32 Handle;
typedef s32 Result;
+// TODO: It would be nice to eventually replace these with strong types that prevent accidental
+// conversion between each other.
+typedef u32 VAddr; ///< Represents a pointer in the userspace virtual address space.
+typedef u32 PAddr; ///< Represents a pointer in the ARM11 physical address space.
+
const Handle INVALID_HANDLE = 0;
namespace Kernel {
@@ -24,7 +31,8 @@ class Thread;
const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel,
ErrorSummary::OutOfResource, ErrorLevel::Temporary);
// TOOD: Verify code
-const ResultCode ERR_INVALID_HANDLE = InvalidHandle(ErrorModule::Kernel);
+const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel,
+ ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
enum KernelHandle : Handle {
CurrentThread = 0xFFFF8000,
@@ -50,32 +58,51 @@ enum {
DEFAULT_STACK_SIZE = 0x4000,
};
-class HandleTable;
-
class Object : NonCopyable {
- friend class HandleTable;
- u32 handle = INVALID_HANDLE;
public:
virtual ~Object() {}
- Handle GetHandle() const { return handle; }
+
+ /// Returns a unique identifier for the object. For debugging purposes only.
+ unsigned int GetObjectId() const { return object_id; }
+
virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; }
virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; }
virtual Kernel::HandleType GetHandleType() const = 0;
/**
- * Wait for kernel object to synchronize.
- * @return True if the current thread should wait as a result of the wait
+ * Check if a thread can wait on the object
+ * @return True if a thread can wait on the object, otherwise false
*/
- virtual ResultVal<bool> WaitSynchronization() {
- LOG_ERROR(Kernel, "(UNIMPLEMENTED)");
- return UnimplementedFunction(ErrorModule::Kernel);
+ bool IsWaitable() const {
+ switch (GetHandleType()) {
+ case HandleType::Session:
+ case HandleType::Event:
+ case HandleType::Mutex:
+ case HandleType::Thread:
+ case HandleType::Semaphore:
+ case HandleType::Timer:
+ return true;
+
+ case HandleType::Unknown:
+ case HandleType::Port:
+ case HandleType::SharedMemory:
+ case HandleType::Redirection:
+ case HandleType::Process:
+ case HandleType::AddressArbiter:
+ return false;
+ }
+
+ return false;
}
private:
friend void intrusive_ptr_add_ref(Object*);
friend void intrusive_ptr_release(Object*);
+ static unsigned int next_object_id;
+
unsigned int ref_count = 0;
+ unsigned int object_id = next_object_id++;
};
// Special functions used by boost::instrusive_ptr to do automatic ref-counting
@@ -92,6 +119,45 @@ inline void intrusive_ptr_release(Object* object) {
template <typename T>
using SharedPtr = boost::intrusive_ptr<T>;
+/// Class that represents a Kernel object that a thread can be waiting on
+class WaitObject : public Object {
+public:
+
+ /**
+ * Check if the current thread should wait until the object is available
+ * @return True if the current thread should wait due to this object being unavailable
+ */
+ virtual bool ShouldWait() = 0;
+
+ /// Acquire/lock the object if it is available
+ virtual void Acquire() = 0;
+
+ /**
+ * Add a thread to wait on this object
+ * @param thread Pointer to thread to add
+ */
+ void AddWaitingThread(SharedPtr<Thread> thread);
+
+ /**
+ * Removes a thread from waiting on this object (e.g. if it was resumed already)
+ * @param thread Pointer to thread to remove
+ */
+ void RemoveWaitingThread(Thread* thread);
+
+ /**
+ * Wake up the next thread waiting on this object
+ * @return Pointer to the thread that was resumed, nullptr if no threads are waiting
+ */
+ SharedPtr<Thread> WakeupNextThread();
+
+ /// Wake up all threads waiting on this object
+ void WakeupAllWaitingThreads();
+
+private:
+ /// Threads waiting for this object to become available
+ std::vector<SharedPtr<Thread>> waiting_threads;
+};
+
/**
* This class allows the creation of Handles, which are references to objects that can be tested
* for validity and looked up. Here they are used to pass references to kernel objects to/from the
@@ -146,14 +212,14 @@ public:
/**
* Looks up a handle.
- * @returns Pointer to the looked-up object, or `nullptr` if the handle is not valid.
+ * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid.
*/
SharedPtr<Object> GetGeneric(Handle handle) const;
/**
* Looks up a handle while verifying its type.
- * @returns Pointer to the looked-up object, or `nullptr` if the handle is not valid or its
- * type differs from the handle type `T::HANDLE_TYPE`.
+ * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or its
+ * type differs from the handle type `T::HANDLE_TYPE`.
*/
template <class T>
SharedPtr<T> Get(Handle handle) const {
@@ -164,6 +230,19 @@ public:
return nullptr;
}
+ /**
+ * Looks up a handle while verifying that it is an object that a thread can wait on
+ * @return Pointer to the looked-up object, or `nullptr` if the handle is not valid or it is
+ * not a waitable object.
+ */
+ SharedPtr<WaitObject> GetWaitObject(Handle handle) const {
+ SharedPtr<Object> object = GetGeneric(handle);
+ if (object != nullptr && object->IsWaitable()) {
+ return boost::static_pointer_cast<WaitObject>(std::move(object));
+ }
+ return nullptr;
+ }
+
/// Closes all handles held in this table.
void Clear();
@@ -197,7 +276,6 @@ private:
};
extern HandleTable g_handle_table;
-extern SharedPtr<Thread> g_main_thread;
/// The ID code of the currently running game
/// TODO(Subv): This variable should not be here,