blob: 8a8226abf5d168dc3c4b929a740f8d35f1e0b0e6 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef JOB_SCHEDULER_H_
#define JOB_SCHEDULER_H_
#include <chrono>
#include <functional>
#include <list>
#include <vector>
#include "magma_util/macros.h"
#include "msd_arm_atom.h"
class JobScheduler {
public:
class Owner {
public:
virtual void RunAtom(MsdArmAtom* atom) = 0;
virtual void AtomCompleted(MsdArmAtom* atom, ArmMaliResultCode result_code) = 0;
virtual void HardStopAtom(MsdArmAtom* atom) {}
virtual void SoftStopAtom(MsdArmAtom* atom) {}
virtual void ReleaseMappingsForAtom(MsdArmAtom* atom) {}
virtual magma::PlatformPort* GetPlatformPort() { return nullptr; }
virtual void UpdateGpuActive(bool active) {}
virtual bool IsInProtectedMode() = 0;
virtual void EnterProtectedMode() = 0;
virtual bool ExitProtectedMode() = 0;
virtual void OutputHangMessage() = 0;
};
using Clock = std::chrono::steady_clock;
JobScheduler(Owner* owner, uint32_t job_slots);
void EnqueueAtom(std::shared_ptr<MsdArmAtom> atom);
void TryToSchedule();
void PlatformPortSignaled(uint64_t key);
void CancelAtomsForConnection(std::shared_ptr<MsdArmConnection> connection);
void JobCompleted(uint64_t slot, ArmMaliResultCode result_code, uint64_t tail);
uint32_t job_slots() const { return job_slots_; }
size_t GetAtomListSize();
// Gets the duration until the earliest currently executing or waiting atom should time out, or
// max if there's no timeout pending.
Clock::duration GetCurrentTimeoutDuration();
void HandleTimedOutAtoms();
void ReleaseMappingsForConnection(std::shared_ptr<MsdArmConnection> connection);
private:
MsdArmAtom* executing_atom() const { return executing_atoms_[0].get(); }
void ProcessSoftAtom(std::shared_ptr<MsdArmSoftAtom> atom);
void SoftJobCompleted(std::shared_ptr<MsdArmSoftAtom> atom);
void UpdatePowerManager();
void MoveAtomsToRunnable();
void ScheduleRunnableAtoms();
uint32_t num_executing_atoms()
{
uint32_t count = 0;
for (auto& atom : executing_atoms_) {
if (atom) {
count++;
}
}
return count;
}
void ValidateCanSwitchProtected();
void set_timeout_duration(uint64_t timeout_duration_ms)
{
timeout_duration_ms_ = timeout_duration_ms;
}
void set_semaphore_timeout_duration(uint64_t semaphore_timeout_duration_ms)
{
semaphore_timeout_duration_ms_ = semaphore_timeout_duration_ms;
}
Owner* owner_;
uint32_t job_slots_;
// This duration determines how often to check whether this atom should be preempted by another
// of the same priority.
uint64_t job_tick_duration_ms_ = 100;
uint64_t timeout_duration_ms_ = 2000;
// Semaphore timeout is longer because one semaphore may need to wait for a
// lot of atoms to complete.
uint64_t semaphore_timeout_duration_ms_ = 5000;
// If we want to switch to a mode, then hold off submitting atoms in the
// other mode until that switch is complete.
bool want_to_switch_to_protected_ = false;
bool want_to_switch_to_nonprotected_ = false;
std::vector<std::shared_ptr<MsdArmSoftAtom>> waiting_atoms_;
std::vector<std::shared_ptr<MsdArmAtom>> executing_atoms_;
std::list<std::shared_ptr<MsdArmAtom>> atoms_;
std::vector<std::list<std::shared_ptr<MsdArmAtom>>> runnable_atoms_;
friend class TestJobScheduler;
DISALLOW_COPY_AND_ASSIGN(JobScheduler);
};
#endif // JOB_SCHEDULER_H_