Kernel: Moved Wait and Acquire to WaitObject, added way to retrieve a WaitObject safely.
This commit is contained in:
parent
c06d64528a
commit
9412996c8f
|
@ -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
|
* Check if a thread can wait on the object
|
||||||
* @return True if the current thread should wait due to this object being unavailable
|
* @return True if a thread can wait on the object, otherwise false
|
||||||
*/
|
*/
|
||||||
virtual ResultVal<bool> Wait() {
|
bool IsWaitable() const {
|
||||||
LOG_ERROR(Kernel, "(UNIMPLEMENTED)");
|
switch (GetHandleType()) {
|
||||||
return UnimplementedFunction(ErrorModule::Kernel);
|
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;
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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,13 +212,13 @@ 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
|
* @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`.
|
* type differs from the handle type `T::HANDLE_TYPE`.
|
||||||
*/
|
*/
|
||||||
template <class T>
|
template <class T>
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Reference in New Issue