2018-02-18 14:58:40 -05:00
|
|
|
// Copyright 2018 yuzu emulator team
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2018-05-07 22:12:45 -04:00
|
|
|
#include <mutex>
|
2018-02-18 14:58:40 -05:00
|
|
|
#include <vector>
|
|
|
|
#include "common/common_types.h"
|
|
|
|
#include "common/thread_queue_list.h"
|
2018-08-01 22:40:00 -04:00
|
|
|
#include "core/hle/kernel/object.h"
|
2018-02-18 14:58:40 -05:00
|
|
|
#include "core/hle/kernel/thread.h"
|
|
|
|
|
2018-08-24 21:43:32 -04:00
|
|
|
namespace Core {
|
2018-07-31 08:06:09 -04:00
|
|
|
class ARM_Interface;
|
2018-08-24 21:43:32 -04:00
|
|
|
}
|
2018-07-31 08:06:09 -04:00
|
|
|
|
2018-02-18 14:58:40 -05:00
|
|
|
namespace Kernel {
|
|
|
|
|
2018-10-25 18:42:50 -04:00
|
|
|
class Process;
|
|
|
|
|
2018-02-18 14:58:40 -05:00
|
|
|
class Scheduler final {
|
|
|
|
public:
|
2018-09-25 16:00:14 -04:00
|
|
|
explicit Scheduler(Core::ARM_Interface& cpu_core);
|
2018-02-18 14:58:40 -05:00
|
|
|
~Scheduler();
|
|
|
|
|
|
|
|
/// Returns whether there are any threads that are ready to run.
|
2018-08-12 12:55:56 -04:00
|
|
|
bool HaveReadyThreads() const;
|
2018-02-18 14:58:40 -05:00
|
|
|
|
|
|
|
/// Reschedules to the next available thread (call after current thread is suspended)
|
|
|
|
void Reschedule();
|
|
|
|
|
|
|
|
/// Gets the current running thread
|
|
|
|
Thread* GetCurrentThread() const;
|
|
|
|
|
2018-10-25 18:42:50 -04:00
|
|
|
/// Gets the timestamp for the last context switch in ticks.
|
|
|
|
u64 GetLastContextSwitchTicks() const;
|
|
|
|
|
2018-02-18 14:58:40 -05:00
|
|
|
/// Adds a new thread to the scheduler
|
|
|
|
void AddThread(SharedPtr<Thread> thread, u32 priority);
|
|
|
|
|
|
|
|
/// Removes a thread from the scheduler
|
|
|
|
void RemoveThread(Thread* thread);
|
|
|
|
|
|
|
|
/// Schedules a thread that has become "ready"
|
|
|
|
void ScheduleThread(Thread* thread, u32 priority);
|
|
|
|
|
|
|
|
/// Unschedules a thread that was already scheduled
|
|
|
|
void UnscheduleThread(Thread* thread, u32 priority);
|
|
|
|
|
|
|
|
/// Sets the priority of a thread in the scheduler
|
|
|
|
void SetThreadPriority(Thread* thread, u32 priority);
|
|
|
|
|
|
|
|
/// Returns a list of all threads managed by the scheduler
|
|
|
|
const std::vector<SharedPtr<Thread>>& GetThreadList() const {
|
|
|
|
return thread_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
/**
|
|
|
|
* Pops and returns the next thread from the thread queue
|
|
|
|
* @return A pointer to the next ready thread
|
|
|
|
*/
|
|
|
|
Thread* PopNextReadyThread();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Switches the CPU's active thread context to that of the specified thread
|
|
|
|
* @param new_thread The thread to switch to
|
|
|
|
*/
|
|
|
|
void SwitchContext(Thread* new_thread);
|
|
|
|
|
2018-10-25 18:42:50 -04:00
|
|
|
/**
|
|
|
|
* Called on every context switch to update the internal timestamp
|
|
|
|
* This also updates the running time ticks for the given thread and
|
|
|
|
* process using the following difference:
|
|
|
|
*
|
|
|
|
* ticks += most_recent_ticks - last_context_switch_ticks
|
|
|
|
*
|
|
|
|
* The internal tick timestamp for the scheduler is simply the
|
|
|
|
* most recent tick count retrieved. No special arithmetic is
|
|
|
|
* applied to it.
|
|
|
|
*/
|
|
|
|
void UpdateLastContextSwitchTime(Thread* thread, Process* process);
|
|
|
|
|
2018-02-18 14:58:40 -05:00
|
|
|
/// Lists all thread ids that aren't deleted/etc.
|
|
|
|
std::vector<SharedPtr<Thread>> thread_list;
|
|
|
|
|
|
|
|
/// Lists only ready thread ids.
|
|
|
|
Common::ThreadQueueList<Thread*, THREADPRIO_LOWEST + 1> ready_queue;
|
|
|
|
|
|
|
|
SharedPtr<Thread> current_thread = nullptr;
|
|
|
|
|
2018-09-25 16:00:14 -04:00
|
|
|
Core::ARM_Interface& cpu_core;
|
2018-10-25 18:42:50 -04:00
|
|
|
u64 last_context_switch_time = 0;
|
2018-05-07 22:12:45 -04:00
|
|
|
|
|
|
|
static std::mutex scheduler_mutex;
|
2018-02-18 14:58:40 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace Kernel
|