mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Scheduler: Release old thread fiber before trying to switch to the next thread fiber.
This commit is contained in:
		
							parent
							
								
									c43e559734
								
							
						
					
					
						commit
						1c672128c4
					
				@ -53,7 +53,8 @@ u32 GlobalScheduler::SelectThreads() {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            sched.selected_thread_set = SharedFrom(thread);
 | 
					            sched.selected_thread_set = SharedFrom(thread);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        const bool reschedule_pending = sched.selected_thread_set != sched.current_thread;
 | 
					        const bool reschedule_pending =
 | 
				
			||||||
 | 
					            sched.is_context_switch_pending || (sched.selected_thread_set != sched.current_thread);
 | 
				
			||||||
        sched.is_context_switch_pending = reschedule_pending;
 | 
					        sched.is_context_switch_pending = reschedule_pending;
 | 
				
			||||||
        std::atomic_thread_fence(std::memory_order_seq_cst);
 | 
					        std::atomic_thread_fence(std::memory_order_seq_cst);
 | 
				
			||||||
        sched.guard.unlock();
 | 
					        sched.guard.unlock();
 | 
				
			||||||
@ -552,7 +553,9 @@ void GlobalScheduler::Unlock() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Scheduler::Scheduler(Core::System& system, std::size_t core_id)
 | 
					Scheduler::Scheduler(Core::System& system, std::size_t core_id)
 | 
				
			||||||
    : system{system}, core_id{core_id} {}
 | 
					    : system(system), core_id(core_id) {
 | 
				
			||||||
 | 
					    switch_fiber = std::make_shared<Common::Fiber>(std::function<void(void*)>(OnSwitch), this);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Scheduler::~Scheduler() = default;
 | 
					Scheduler::~Scheduler() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -636,8 +639,9 @@ void Scheduler::SwitchContext() {
 | 
				
			|||||||
    current_thread = selected_thread;
 | 
					    current_thread = selected_thread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    is_context_switch_pending = false;
 | 
					    is_context_switch_pending = false;
 | 
				
			||||||
    guard.unlock();
 | 
					
 | 
				
			||||||
    if (new_thread == previous_thread) {
 | 
					    if (new_thread == previous_thread) {
 | 
				
			||||||
 | 
					        guard.unlock();
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -669,20 +673,31 @@ void Scheduler::SwitchContext() {
 | 
				
			|||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        old_context = idle_thread->GetHostContext();
 | 
					        old_context = idle_thread->GetHostContext();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    guard.unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::shared_ptr<Common::Fiber> next_context;
 | 
					    Common::Fiber::YieldTo(old_context, switch_fiber);
 | 
				
			||||||
    if (new_thread != nullptr) {
 | 
					 | 
				
			||||||
        next_context = new_thread->GetHostContext();
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        next_context = idle_thread->GetHostContext();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Common::Fiber::YieldTo(old_context, next_context);
 | 
					 | 
				
			||||||
    /// When a thread wakes up, the scheduler may have changed to other in another core.
 | 
					    /// When a thread wakes up, the scheduler may have changed to other in another core.
 | 
				
			||||||
    auto& next_scheduler = system.Kernel().CurrentScheduler();
 | 
					    auto& next_scheduler = system.Kernel().CurrentScheduler();
 | 
				
			||||||
    next_scheduler.SwitchContextStep2();
 | 
					    next_scheduler.SwitchContextStep2();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Scheduler::OnSwitch(void* this_scheduler) {
 | 
				
			||||||
 | 
					    Scheduler* sched = static_cast<Scheduler*>(this_scheduler);
 | 
				
			||||||
 | 
					    sched->SwitchToCurrent();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Scheduler::SwitchToCurrent() {
 | 
				
			||||||
 | 
					    while (true) {
 | 
				
			||||||
 | 
					        std::shared_ptr<Common::Fiber> next_context;
 | 
				
			||||||
 | 
					        if (current_thread != nullptr) {
 | 
				
			||||||
 | 
					            next_context = current_thread->GetHostContext();
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            next_context = idle_thread->GetHostContext();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Common::Fiber::YieldTo(switch_fiber, next_context);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Scheduler::UpdateLastContextSwitchTime(Thread* thread, Process* process) {
 | 
					void Scheduler::UpdateLastContextSwitchTime(Thread* thread, Process* process) {
 | 
				
			||||||
    const u64 prev_switch_ticks = last_context_switch_time;
 | 
					    const u64 prev_switch_ticks = last_context_switch_time;
 | 
				
			||||||
    const u64 most_recent_switch_ticks = system.CoreTiming().GetCPUTicks();
 | 
					    const u64 most_recent_switch_ticks = system.CoreTiming().GetCPUTicks();
 | 
				
			||||||
 | 
				
			|||||||
@ -15,6 +15,10 @@
 | 
				
			|||||||
#include "core/hardware_properties.h"
 | 
					#include "core/hardware_properties.h"
 | 
				
			||||||
#include "core/hle/kernel/thread.h"
 | 
					#include "core/hle/kernel/thread.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace Common {
 | 
				
			||||||
 | 
					    class Fiber;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Core {
 | 
					namespace Core {
 | 
				
			||||||
class ARM_Interface;
 | 
					class ARM_Interface;
 | 
				
			||||||
class System;
 | 
					class System;
 | 
				
			||||||
@ -247,12 +251,17 @@ private:
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    void UpdateLastContextSwitchTime(Thread* thread, Process* process);
 | 
					    void UpdateLastContextSwitchTime(Thread* thread, Process* process);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static void OnSwitch(void* this_scheduler);
 | 
				
			||||||
 | 
					    void SwitchToCurrent();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::shared_ptr<Thread> current_thread = nullptr;
 | 
					    std::shared_ptr<Thread> current_thread = nullptr;
 | 
				
			||||||
    std::shared_ptr<Thread> selected_thread = nullptr;
 | 
					    std::shared_ptr<Thread> selected_thread = nullptr;
 | 
				
			||||||
    std::shared_ptr<Thread> current_thread_prev = nullptr;
 | 
					    std::shared_ptr<Thread> current_thread_prev = nullptr;
 | 
				
			||||||
    std::shared_ptr<Thread> selected_thread_set = nullptr;
 | 
					    std::shared_ptr<Thread> selected_thread_set = nullptr;
 | 
				
			||||||
    std::shared_ptr<Thread> idle_thread = nullptr;
 | 
					    std::shared_ptr<Thread> idle_thread = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    std::shared_ptr<Common::Fiber> switch_fiber = nullptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Core::System& system;
 | 
					    Core::System& system;
 | 
				
			||||||
    u64 last_context_switch_time = 0;
 | 
					    u64 last_context_switch_time = 0;
 | 
				
			||||||
    u64 idle_selection_count = 0;
 | 
					    u64 idle_selection_count = 0;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user