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

This commit is contained in:
bunnei 2015-01-18 14:33:11 -05:00
parent c06d64528a
commit 9412996c8f
4 changed files with 59 additions and 20 deletions

View file

@ -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:
* Acquire/lock the this object if it is available case HandleType::Port:
* @return True if we were able to acquire this object, otherwise false case HandleType::SharedMemory:
*/ case HandleType::Redirection:
virtual ResultVal<bool> Acquire() { case HandleType::Process:
LOG_ERROR(Kernel, "(UNIMPLEMENTED)"); case HandleType::AddressArbiter:
return UnimplementedFunction(ErrorModule::Kernel); return false;
}
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 * @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>
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();

View file

@ -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;

View file

@ -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

View file

@ -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;