mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	Kernel: Added WaitObject and changed "waitable" objects inherit from it.
This commit is contained in:
		
							parent
							
								
									0c7498545f
								
							
						
					
					
						commit
						c22bac6398
					
				@ -14,7 +14,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Kernel {
 | 
					namespace Kernel {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Event : public Object {
 | 
					class Event : public WaitObject {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    std::string GetTypeName() const override { return "Event"; }
 | 
					    std::string GetTypeName() const override { return "Event"; }
 | 
				
			||||||
    std::string GetName() const override { return name; }
 | 
					    std::string GetName() const override { return name; }
 | 
				
			||||||
@ -27,16 +27,12 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    bool locked;                            ///< Event signal wait
 | 
					    bool locked;                            ///< Event signal wait
 | 
				
			||||||
    bool permanent_locked;                  ///< Hack - to set event permanent state (for easy passthrough)
 | 
					    bool permanent_locked;                  ///< Hack - to set event permanent state (for easy passthrough)
 | 
				
			||||||
    std::vector<Handle> waiting_threads;    ///< Threads that are waiting for the event
 | 
					 | 
				
			||||||
    std::string name;                       ///< Name of event (optional)
 | 
					    std::string name;                       ///< Name of event (optional)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ResultVal<bool> WaitSynchronization() override {
 | 
					    ResultVal<bool> WaitSynchronization() override {
 | 
				
			||||||
        bool wait = locked;
 | 
					        bool wait = locked;
 | 
				
			||||||
        if (locked) {
 | 
					        if (locked) {
 | 
				
			||||||
            Handle thread = GetCurrentThread()->GetHandle();
 | 
					            AddWaitingThread(GetCurrentThread());
 | 
				
			||||||
            if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {
 | 
					 | 
				
			||||||
                waiting_threads.push_back(thread);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            Kernel::WaitCurrentThread(WAITTYPE_EVENT, this);
 | 
					            Kernel::WaitCurrentThread(WAITTYPE_EVENT, this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (reset_type != RESETTYPE_STICKY && !permanent_locked) {
 | 
					        if (reset_type != RESETTYPE_STICKY && !permanent_locked) {
 | 
				
			||||||
@ -86,20 +82,12 @@ ResultCode SignalEvent(const Handle handle) {
 | 
				
			|||||||
    if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
 | 
					    if (evt == nullptr) return InvalidHandle(ErrorModule::Kernel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Resume threads waiting for event to signal
 | 
					    // Resume threads waiting for event to signal
 | 
				
			||||||
    bool event_caught = false;
 | 
					    bool event_caught = evt->ResumeAllWaitingThreads();
 | 
				
			||||||
    for (size_t i = 0; i < evt->waiting_threads.size(); ++i) {
 | 
					 | 
				
			||||||
        Thread* thread = Kernel::g_handle_table.Get<Thread>(evt->waiting_threads[i]).get();
 | 
					 | 
				
			||||||
        if (thread != nullptr)
 | 
					 | 
				
			||||||
            thread->ResumeFromWait();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // If any thread is signalled awake by this event, assume the event was "caught" and reset
 | 
					 | 
				
			||||||
        // the event. This will result in the next thread waiting on the event to block. Otherwise,
 | 
					 | 
				
			||||||
        // the event will not be reset, and the next thread to call WaitSynchronization on it will
 | 
					 | 
				
			||||||
        // not block. Not sure if this is correct behavior, but it seems to work.
 | 
					 | 
				
			||||||
        event_caught = true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    evt->waiting_threads.clear();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // If any thread is signalled awake by this event, assume the event was "caught" and reset
 | 
				
			||||||
 | 
					    // the event. This will result in the next thread waiting on the event to block. Otherwise,
 | 
				
			||||||
 | 
					    // the event will not be reset, and the next thread to call WaitSynchronization on it will
 | 
				
			||||||
 | 
					    // not block. Not sure if this is correct behavior, but it seems to work.
 | 
				
			||||||
    if (!evt->permanent_locked) {
 | 
					    if (!evt->permanent_locked) {
 | 
				
			||||||
        evt->locked = event_caught;
 | 
					        evt->locked = event_caught;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -18,6 +18,32 @@ SharedPtr<Thread> g_main_thread = nullptr;
 | 
				
			|||||||
HandleTable g_handle_table;
 | 
					HandleTable g_handle_table;
 | 
				
			||||||
u64 g_program_id = 0;
 | 
					u64 g_program_id = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void WaitObject::AddWaitingThread(Thread* thread) {
 | 
				
			||||||
 | 
					    if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {
 | 
				
			||||||
 | 
					        waiting_threads.push_back(thread);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Thread* WaitObject::ResumeNextThread() {
 | 
				
			||||||
 | 
					    if (waiting_threads.empty()) return nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    auto next_thread = waiting_threads.front();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    next_thread->ResumeFromWait();
 | 
				
			||||||
 | 
					    waiting_threads.erase(waiting_threads.begin());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return next_thread.get();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void WaitObject::ReleaseAllWaitingThreads() {
 | 
				
			||||||
 | 
					    auto waiting_threads_copy = waiting_threads;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (auto thread : waiting_threads_copy)
 | 
				
			||||||
 | 
					        thread->ReleaseWaitObject(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    waiting_threads.clear();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
HandleTable::HandleTable() {
 | 
					HandleTable::HandleTable() {
 | 
				
			||||||
    next_generation = 1;
 | 
					    next_generation = 1;
 | 
				
			||||||
    Clear();
 | 
					    Clear();
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <array>
 | 
					#include <array>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "common/common.h"
 | 
					#include "common/common.h"
 | 
				
			||||||
#include "core/hle/result.h"
 | 
					#include "core/hle/result.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -92,6 +94,29 @@ inline void intrusive_ptr_release(Object* object) {
 | 
				
			|||||||
template <typename T>
 | 
					template <typename T>
 | 
				
			||||||
using SharedPtr = boost::intrusive_ptr<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:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Add a thread to wait on this object
 | 
				
			||||||
 | 
					     * @param thread Pointer to thread to add
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    void AddWaitingThread(Thread* thread);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Resumes the next thread waiting on this object
 | 
				
			||||||
 | 
					     * @return Pointer to the thread that was resumed, nullptr if no threads are waiting
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    Thread* ResumeNextThread();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /// Releases all threads waiting on this object
 | 
				
			||||||
 | 
					    void ReleaseAllWaitingThreads();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
					    std::vector<Thread*> waiting_threads; ///< Threads waiting for this object to become available
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This class allows the creation of Handles, which are references to objects that can be tested
 | 
					 * 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
 | 
					 * for validity and looked up. Here they are used to pass references to kernel objects to/from the
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Kernel {
 | 
					namespace Kernel {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Mutex : public Object {
 | 
					class Mutex : public WaitObject {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    std::string GetTypeName() const override { return "Mutex"; }
 | 
					    std::string GetTypeName() const override { return "Mutex"; }
 | 
				
			||||||
    std::string GetName() const override { return name; }
 | 
					    std::string GetName() const override { return name; }
 | 
				
			||||||
@ -24,7 +24,6 @@ public:
 | 
				
			|||||||
    bool initial_locked;                        ///< Initial lock state when mutex was created
 | 
					    bool initial_locked;                        ///< Initial lock state when mutex was created
 | 
				
			||||||
    bool locked;                                ///< Current locked state
 | 
					    bool locked;                                ///< Current locked state
 | 
				
			||||||
    Handle lock_thread;                         ///< Handle to thread that currently has mutex
 | 
					    Handle lock_thread;                         ///< Handle to thread that currently has mutex
 | 
				
			||||||
    std::vector<Handle> waiting_threads;        ///< Threads that are waiting for the mutex
 | 
					 | 
				
			||||||
    std::string name;                           ///< Name of mutex (optional)
 | 
					    std::string name;                           ///< Name of mutex (optional)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ResultVal<bool> WaitSynchronization() override;
 | 
					    ResultVal<bool> WaitSynchronization() override;
 | 
				
			||||||
@ -45,36 +44,20 @@ void MutexAcquireLock(Mutex* mutex, Handle thread = GetCurrentThread()->GetHandl
 | 
				
			|||||||
    mutex->lock_thread = thread;
 | 
					    mutex->lock_thread = thread;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool ReleaseMutexForThread(Mutex* mutex, Handle thread_handle) {
 | 
					 | 
				
			||||||
    MutexAcquireLock(mutex, thread_handle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Thread* thread = Kernel::g_handle_table.Get<Thread>(thread_handle).get();
 | 
					 | 
				
			||||||
    if (thread == nullptr) {
 | 
					 | 
				
			||||||
        LOG_ERROR(Kernel, "Called with invalid handle: %08X", thread_handle);
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    thread->ResumeFromWait();
 | 
					 | 
				
			||||||
    return true;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Resumes a thread waiting for the specified mutex
 | 
					 * Resumes a thread waiting for the specified mutex
 | 
				
			||||||
 * @param mutex The mutex that some thread is waiting on
 | 
					 * @param mutex The mutex that some thread is waiting on
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void ResumeWaitingThread(Mutex* mutex) {
 | 
					void ResumeWaitingThread(Mutex* mutex) {
 | 
				
			||||||
    // Find the next waiting thread for the mutex...
 | 
					    // Find the next waiting thread for the mutex...
 | 
				
			||||||
    if (mutex->waiting_threads.empty()) {
 | 
					    auto next_thread = mutex->ResumeNextThread();
 | 
				
			||||||
 | 
					    if (next_thread != nullptr) {
 | 
				
			||||||
 | 
					        MutexAcquireLock(mutex, next_thread->GetHandle());
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
        // Reset mutex lock thread handle, nothing is waiting
 | 
					        // Reset mutex lock thread handle, nothing is waiting
 | 
				
			||||||
        mutex->locked = false;
 | 
					        mutex->locked = false;
 | 
				
			||||||
        mutex->lock_thread = -1;
 | 
					        mutex->lock_thread = -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
        // Resume the next waiting thread and re-lock the mutex
 | 
					 | 
				
			||||||
        std::vector<Handle>::iterator iter = mutex->waiting_threads.begin();
 | 
					 | 
				
			||||||
        ReleaseMutexForThread(mutex, *iter);
 | 
					 | 
				
			||||||
        mutex->waiting_threads.erase(iter);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void MutexEraseLock(Mutex* mutex) {
 | 
					void MutexEraseLock(Mutex* mutex) {
 | 
				
			||||||
@ -175,7 +158,7 @@ Handle CreateMutex(bool initial_locked, const std::string& name) {
 | 
				
			|||||||
ResultVal<bool> Mutex::WaitSynchronization() {
 | 
					ResultVal<bool> Mutex::WaitSynchronization() {
 | 
				
			||||||
    bool wait = locked;
 | 
					    bool wait = locked;
 | 
				
			||||||
    if (locked) {
 | 
					    if (locked) {
 | 
				
			||||||
        waiting_threads.push_back(GetCurrentThread()->GetHandle());
 | 
					        AddWaitingThread(GetCurrentThread());
 | 
				
			||||||
        Kernel::WaitCurrentThread(WAITTYPE_MUTEX, this);
 | 
					        Kernel::WaitCurrentThread(WAITTYPE_MUTEX, this);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        // Lock the mutex when the first thread accesses it
 | 
					        // Lock the mutex when the first thread accesses it
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Kernel {
 | 
					namespace Kernel {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Semaphore : public Object {
 | 
					class Semaphore : public WaitObject {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    std::string GetTypeName() const override { return "Semaphore"; }
 | 
					    std::string GetTypeName() const override { return "Semaphore"; }
 | 
				
			||||||
    std::string GetName() const override { return name; }
 | 
					    std::string GetName() const override { return name; }
 | 
				
			||||||
@ -22,7 +22,6 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    s32 max_count;                              ///< Maximum number of simultaneous holders the semaphore can have
 | 
					    s32 max_count;                              ///< Maximum number of simultaneous holders the semaphore can have
 | 
				
			||||||
    s32 available_count;                        ///< Number of free slots left in the semaphore
 | 
					    s32 available_count;                        ///< Number of free slots left in the semaphore
 | 
				
			||||||
    std::queue<Handle> waiting_threads;         ///< Threads that are waiting for the semaphore
 | 
					 | 
				
			||||||
    std::string name;                           ///< Name of semaphore (optional)
 | 
					    std::string name;                           ///< Name of semaphore (optional)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -38,7 +37,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (wait) {
 | 
					        if (wait) {
 | 
				
			||||||
            Kernel::WaitCurrentThread(WAITTYPE_SEMA, this);
 | 
					            Kernel::WaitCurrentThread(WAITTYPE_SEMA, this);
 | 
				
			||||||
            waiting_threads.push(GetCurrentThread()->GetHandle());
 | 
					            AddWaitingThread(GetCurrentThread());
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            --available_count;
 | 
					            --available_count;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -83,11 +82,7 @@ ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Notify some of the threads that the semaphore has been released
 | 
					    // Notify some of the threads that the semaphore has been released
 | 
				
			||||||
    // stop once the semaphore is full again or there are no more waiting threads
 | 
					    // stop once the semaphore is full again or there are no more waiting threads
 | 
				
			||||||
    while (!semaphore->waiting_threads.empty() && semaphore->IsAvailable()) {
 | 
					    while (semaphore->IsAvailable() && semaphore->ResumeNextThread() != nullptr) {
 | 
				
			||||||
        Thread* thread = Kernel::g_handle_table.Get<Thread>(semaphore->waiting_threads.front()).get();
 | 
					 | 
				
			||||||
        if (thread != nullptr)
 | 
					 | 
				
			||||||
            thread->ResumeFromWait();
 | 
					 | 
				
			||||||
        semaphore->waiting_threads.pop();
 | 
					 | 
				
			||||||
        --semaphore->available_count;
 | 
					        --semaphore->available_count;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -25,10 +25,7 @@ namespace Kernel {
 | 
				
			|||||||
ResultVal<bool> Thread::WaitSynchronization() {
 | 
					ResultVal<bool> Thread::WaitSynchronization() {
 | 
				
			||||||
    const bool wait = status != THREADSTATUS_DORMANT;
 | 
					    const bool wait = status != THREADSTATUS_DORMANT;
 | 
				
			||||||
    if (wait) {
 | 
					    if (wait) {
 | 
				
			||||||
        Thread* thread = GetCurrentThread();
 | 
					        AddWaitingThread(GetCurrentThread());
 | 
				
			||||||
        if (std::find(waiting_threads.begin(), waiting_threads.end(), thread) == waiting_threads.end()) {
 | 
					 | 
				
			||||||
            waiting_threads.push_back(thread);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        WaitCurrentThread(WAITTYPE_THREADEND, this);
 | 
					        WaitCurrentThread(WAITTYPE_THREADEND, this);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -110,11 +107,7 @@ void Thread::Stop(const char* reason) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ChangeReadyState(this, false);
 | 
					    ChangeReadyState(this, false);
 | 
				
			||||||
    status = THREADSTATUS_DORMANT;
 | 
					    status = THREADSTATUS_DORMANT;
 | 
				
			||||||
    for (auto& waiting_thread : waiting_threads) {
 | 
					    ResumeAllWaitingThreads();
 | 
				
			||||||
        if (CheckWaitType(waiting_thread.get(), WAITTYPE_THREADEND, this))
 | 
					 | 
				
			||||||
            waiting_thread->ResumeFromWait();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    waiting_threads.clear();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Stopped threads are never waiting.
 | 
					    // Stopped threads are never waiting.
 | 
				
			||||||
    wait_type = WAITTYPE_NONE;
 | 
					    wait_type = WAITTYPE_NONE;
 | 
				
			||||||
 | 
				
			|||||||
@ -52,7 +52,7 @@ enum WaitType {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Kernel {
 | 
					namespace Kernel {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Thread : public Kernel::Object {
 | 
					class Thread : public WaitObject {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority,
 | 
					    static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, s32 priority,
 | 
				
			||||||
        u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size);
 | 
					        u32 arg, s32 processor_id, VAddr stack_top, u32 stack_size);
 | 
				
			||||||
@ -99,8 +99,6 @@ public:
 | 
				
			|||||||
    Object* wait_object;
 | 
					    Object* wait_object;
 | 
				
			||||||
    VAddr wait_address;
 | 
					    VAddr wait_address;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::vector<SharedPtr<Thread>> waiting_threads;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    std::string name;
 | 
					    std::string name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /// Whether this thread is intended to never actually be executed, i.e. always idle
 | 
					    /// Whether this thread is intended to never actually be executed, i.e. always idle
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
namespace Kernel {
 | 
					namespace Kernel {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Timer : public Object {
 | 
					class Timer : public WaitObject {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    std::string GetTypeName() const override { return "Timer"; }
 | 
					    std::string GetTypeName() const override { return "Timer"; }
 | 
				
			||||||
    std::string GetName() const override { return name; }
 | 
					    std::string GetName() const override { return name; }
 | 
				
			||||||
@ -24,7 +24,6 @@ public:
 | 
				
			|||||||
    ResetType reset_type;                   ///< The ResetType of this timer
 | 
					    ResetType reset_type;                   ///< The ResetType of this timer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool signaled;                          ///< Whether the timer has been signaled or not
 | 
					    bool signaled;                          ///< Whether the timer has been signaled or not
 | 
				
			||||||
    std::set<Handle> waiting_threads;       ///< Threads that are waiting for the timer
 | 
					 | 
				
			||||||
    std::string name;                       ///< Name of timer (optional)
 | 
					    std::string name;                       ///< Name of timer (optional)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    u64 initial_delay;                      ///< The delay until the timer fires for the first time
 | 
					    u64 initial_delay;                      ///< The delay until the timer fires for the first time
 | 
				
			||||||
@ -33,7 +32,7 @@ public:
 | 
				
			|||||||
    ResultVal<bool> WaitSynchronization() override {
 | 
					    ResultVal<bool> WaitSynchronization() override {
 | 
				
			||||||
        bool wait = !signaled;
 | 
					        bool wait = !signaled;
 | 
				
			||||||
        if (wait) {
 | 
					        if (wait) {
 | 
				
			||||||
            waiting_threads.insert(GetCurrentThread()->GetHandle());
 | 
					            AddWaitingThread(GetCurrentThread());
 | 
				
			||||||
            Kernel::WaitCurrentThread(WAITTYPE_TIMER, this);
 | 
					            Kernel::WaitCurrentThread(WAITTYPE_TIMER, this);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return MakeResult<bool>(wait);
 | 
					        return MakeResult<bool>(wait);
 | 
				
			||||||
@ -92,12 +91,7 @@ static void TimerCallback(u64 timer_handle, int cycles_late) {
 | 
				
			|||||||
    timer->signaled = true;
 | 
					    timer->signaled = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Resume all waiting threads
 | 
					    // Resume all waiting threads
 | 
				
			||||||
    for (Handle thread_handle : timer->waiting_threads) {
 | 
					    timer->ResumeAllWaitingThreads();
 | 
				
			||||||
        if (SharedPtr<Thread> thread = Kernel::g_handle_table.Get<Thread>(thread_handle))
 | 
					 | 
				
			||||||
            thread->ResumeFromWait();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    timer->waiting_threads.clear();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (timer->reset_type == RESETTYPE_ONESHOT)
 | 
					    if (timer->reset_type == RESETTYPE_ONESHOT)
 | 
				
			||||||
        timer->signaled = false;
 | 
					        timer->signaled = false;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user