Просмотр исходного кода

Kernel: Moved Wait and Acquire to WaitObject, added way to retrieve a WaitObject safely.

bunnei 11 лет назад
Родитель
Сommit
9412996c8f
4 измененных файлов с 59 добавлено и 20 удалено
  1. 55 16
      src/core/hle/kernel/kernel.h
  2. 1 1
      src/core/hle/kernel/thread.cpp
  3. 1 1
      src/core/hle/kernel/thread.h
  4. 2 2
      src/core/hle/svc.cpp

+ 55 - 16
src/core/hle/kernel/kernel.h

@@ -60,26 +60,34 @@ class Object : NonCopyable {
 public:
 public:
     virtual ~Object() {}
     virtual ~Object() {}
     Handle GetHandle() const { return handle; }
     Handle GetHandle() const { return handle; }
+
     virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; }
     virtual std::string GetTypeName() const { return "[BAD KERNEL OBJECT TYPE]"; }
     virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; }
     virtual std::string GetName() const { return "[UNKNOWN KERNEL OBJECT]"; }
     virtual Kernel::HandleType GetHandleType() const = 0;
     virtual Kernel::HandleType GetHandleType() const = 0;
 
 
     /**
     /**
-     * Check if this object is available
-     * @return True if the current thread should wait due to this object being unavailable
+     * Check if a thread can wait on the object
+     * @return True if a thread can wait on the object, otherwise false
      */
      */
-    virtual ResultVal<bool> Wait() {
-        LOG_ERROR(Kernel, "(UNIMPLEMENTED)");
-        return UnimplementedFunction(ErrorModule::Kernel);
-    }
+    bool IsWaitable() const {
+        switch (GetHandleType()) {
+        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;
+        }
 
 
-    /**
-     * Acquire/lock the this object if it is available
-     * @return True if we were able to acquire this object, otherwise false
-     */
-    virtual ResultVal<bool> Acquire() {
-        LOG_ERROR(Kernel, "(UNIMPLEMENTED)");
-        return UnimplementedFunction(ErrorModule::Kernel);
+        return false;
     }
     }
 
 
 private:
 private:
@@ -107,6 +115,24 @@ using SharedPtr = boost::intrusive_ptr<T>;
 class WaitObject : public Object {
 class WaitObject : public Object {
 public:
 public:
 
 
+    /**
+     * Check if this object is available
+     * @return True if the current thread should wait due to this object being unavailable
+     */
+    virtual ResultVal<bool> Wait() {
+        LOG_ERROR(Kernel, "(UNIMPLEMENTED)");
+        return UnimplementedFunction(ErrorModule::Kernel);
+    }
+
+    /**
+     * Acquire/lock the this object if it is available
+     * @return True if we were able to acquire this object, otherwise false
+     */
+    virtual ResultVal<bool> Acquire() {
+        LOG_ERROR(Kernel, "(UNIMPLEMENTED)");
+        return UnimplementedFunction(ErrorModule::Kernel);
+    }
+
     /**
     /**
      * Add a thread to wait on this object
      * Add a thread to wait on this object
      * @param thread Pointer to thread to add
      * @param thread Pointer to thread to add
@@ -186,14 +212,14 @@ public:
 
 
     /**
     /**
      * Looks up a handle.
      * 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;
     SharedPtr<Object> GetGeneric(Handle handle) const;
 
 
     /**
     /**
      * Looks up a handle while verifying its type.
      * 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>
     template <class T>
     SharedPtr<T> Get(Handle handle) const {
     SharedPtr<T> Get(Handle handle) const {
@@ -204,6 +230,19 @@ public:
         return nullptr;
         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.
     /// Closes all handles held in this table.
     void Clear();
     void Clear();
 
 

+ 1 - 1
src/core/hle/kernel/thread.cpp

@@ -210,7 +210,7 @@ void WaitCurrentThread_Sleep() {
     ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND)));
     ChangeThreadState(thread, ThreadStatus(THREADSTATUS_WAIT | (thread->status & THREADSTATUS_SUSPEND)));
 }
 }
 
 
-void WaitCurrentThread_WaitSynchronization(WaitObject* wait_object, bool wait_all) {
+void WaitCurrentThread_WaitSynchronization(SharedPtr<WaitObject> wait_object, bool wait_all) {
     Thread* thread = GetCurrentThread();
     Thread* thread = GetCurrentThread();
     thread->wait_all = wait_all;
     thread->wait_all = wait_all;
     thread->wait_address = 0;
     thread->wait_address = 0;

+ 1 - 1
src/core/hle/kernel/thread.h

@@ -136,7 +136,7 @@ void WaitCurrentThread_Sleep();
  * @param wait_object Kernel object that we are waiting on
  * @param wait_object Kernel object that we are waiting on
  * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only)
  * @param wait_all If true, wait on all objects before resuming (for WaitSynchronizationN only)
  */
  */
-void WaitCurrentThread_WaitSynchronization(WaitObject* wait_object, bool wait_all=false);
+void WaitCurrentThread_WaitSynchronization(SharedPtr<WaitObject> wait_object, bool wait_all = false);
 
 
 /**
 /**
  * Waits the current thread from an ArbitrateAddress call
  * Waits the current thread from an ArbitrateAddress call

+ 2 - 2
src/core/hle/svc.cpp

@@ -115,7 +115,7 @@ static Result CloseHandle(Handle handle) {
 
 
 /// Wait for a handle to synchronize, timeout after the specified nanoseconds
 /// Wait for a handle to synchronize, timeout after the specified nanoseconds
 static Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
 static Result WaitSynchronization1(Handle handle, s64 nano_seconds) {
-    Kernel::WaitObject* object = static_cast<Kernel::WaitObject*>(Kernel::g_handle_table.GetGeneric(handle).get());
+    auto object = Kernel::g_handle_table.GetWaitObject(handle);
     if (object == nullptr)
     if (object == nullptr)
         return InvalidHandle(ErrorModule::Kernel).raw;
         return InvalidHandle(ErrorModule::Kernel).raw;
 
 
@@ -163,7 +163,7 @@ static Result WaitSynchronizationN(s32* out, Handle* handles, s32 handle_count,
     if (handle_count != 0) {
     if (handle_count != 0) {
         bool selected = false; // True once an object has been selected
         bool selected = false; // True once an object has been selected
         for (int i = 0; i < handle_count; ++i) {
         for (int i = 0; i < handle_count; ++i) {
-            Kernel::WaitObject* object = static_cast<Kernel::WaitObject*>(Kernel::g_handle_table.GetGeneric(handles[i]).get());
+            auto object = Kernel::g_handle_table.GetWaitObject(handles[i]);
             if (object == nullptr)
             if (object == nullptr)
                 return InvalidHandle(ErrorModule::Kernel).raw;
                 return InvalidHandle(ErrorModule::Kernel).raw;