blob: 8a65af5fc04fd4bc6acc3a68d200603b33826bdb [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 MSD_ARM_ATOM_H_
#define MSD_ARM_ATOM_H_
#include <chrono>
#include <cstdint>
#include <memory>
#include <vector>
#include "address_space.h"
#include "magma_arm_mali_types.h"
#include "platform_semaphore.h"
class MsdArmAtom {
public:
struct Dependency {
ArmMaliDependencyType type;
std::shared_ptr<MsdArmAtom> atom;
ArmMaliResultCode saved_result = kArmMaliResultRunning;
};
using DependencyList = std::vector<Dependency>;
static constexpr uint64_t kInvalidGpuAddress = ~0ul;
virtual ~MsdArmAtom() {}
MsdArmAtom(std::weak_ptr<MsdArmConnection> connection, uint64_t gpu_address, uint32_t slot,
uint8_t atom_number, magma_arm_mali_user_data user_data, int8_t priority,
AtomFlags flags = static_cast<AtomFlags>(0));
uint64_t trace_nonce() const { return trace_nonce_; }
std::weak_ptr<MsdArmConnection> connection() const { return connection_; }
uint64_t gpu_address() const { return gpu_address_; }
void set_gpu_address(uint64_t gpu_address) { gpu_address_ = gpu_address; }
uint32_t slot() const { return slot_; }
uint8_t atom_number() const { return atom_number_; }
const magma_arm_mali_user_data& user_data() const { return user_data_; }
void set_require_cycle_counter() { require_cycle_counter_ = true; }
void set_using_cycle_counter(bool using_cycle_counter)
{
using_cycle_counter_ = using_cycle_counter;
}
bool require_cycle_counter() const { return require_cycle_counter_; }
bool using_cycle_counter() const { return using_cycle_counter_; }
int8_t priority() const { return priority_; }
AtomFlags flags() const { return flags_; }
bool is_protected() const { return flags_ & kAtomFlagProtected; }
bool IsDependencyOnly() const { return !gpu_address_; }
void set_dependencies(const DependencyList& dependencies);
void UpdateDependencies(bool* all_finished_out);
// Returns a failure result code if a data dependency of this atom failed.
ArmMaliResultCode GetFinalDependencyResult() const;
ArmMaliResultCode result_code() const { return result_code_; }
// These methods should only be called on the device thread.
void set_result_code(ArmMaliResultCode code)
{
DASSERT(result_code_ == kArmMaliResultRunning);
result_code_ = code;
}
bool hard_stopped() const { return hard_stopped_; }
void set_hard_stopped() { hard_stopped_ = true; }
bool soft_stopped() const { return soft_stopped_; }
void set_soft_stopped(bool stopped) { soft_stopped_ = stopped; }
void SetExecutionStarted();
void SetTickStarted();
// Preempted by a timer interrupt (not by a higher priority atom)
bool preempted() const { return preempted_; }
void set_preempted(bool preempted) { preempted_ = preempted; }
std::chrono::time_point<std::chrono::steady_clock> execution_start_time() const
{
return execution_start_time_;
}
std::chrono::time_point<std::chrono::steady_clock> tick_start_time() const
{
return tick_start_time_;
}
// These methods should only be called on the device thread.
void set_address_slot_mapping(std::shared_ptr<AddressSlotMapping> address_slot_mapping);
std::shared_ptr<AddressSlotMapping> address_slot_mapping() const
{
return address_slot_mapping_;
}
virtual bool is_soft_atom() const { return false; }
private:
// The following data is immmutable after construction.
const uint64_t trace_nonce_;
const std::weak_ptr<MsdArmConnection> connection_;
uint64_t gpu_address_;
const uint32_t slot_;
const int8_t priority_;
const AtomFlags flags_{};
bool require_cycle_counter_ = false;
DependencyList dependencies_;
// Assigned by client.
const uint8_t atom_number_;
const magma_arm_mali_user_data user_data_;
// This data is mutable after construction from the device thread.
ArmMaliResultCode result_code_ = kArmMaliResultRunning;
std::shared_ptr<AddressSlotMapping> address_slot_mapping_;
std::chrono::time_point<std::chrono::steady_clock> execution_start_time_;
std::chrono::time_point<std::chrono::steady_clock> tick_start_time_;
bool hard_stopped_ = false;
bool soft_stopped_ = false;
bool using_cycle_counter_ = false;
bool preempted_ = false;
};
// Soft atoms don't actually execute in hardware.
class MsdArmSoftAtom : public MsdArmAtom {
public:
static std::shared_ptr<MsdArmSoftAtom> cast(std::shared_ptr<MsdArmAtom> atom)
{
if (atom->is_soft_atom())
return std::static_pointer_cast<MsdArmSoftAtom>(atom);
return nullptr;
}
MsdArmSoftAtom(std::weak_ptr<MsdArmConnection> connection, AtomFlags soft_flags,
std::shared_ptr<magma::PlatformSemaphore> platform_semaphore,
uint8_t atom_number, magma_arm_mali_user_data user_data)
: MsdArmAtom(connection, kInvalidGpuAddress, 0, atom_number, user_data, 0, soft_flags),
platform_semaphore_(platform_semaphore)
{
}
AtomFlags soft_flags() const { return flags(); }
std::shared_ptr<magma::PlatformSemaphore> platform_semaphore() const
{
return platform_semaphore_;
}
bool is_soft_atom() const override { return true; }
private:
// Immutable after construction.
const std::shared_ptr<magma::PlatformSemaphore> platform_semaphore_;
};
#endif // MSD_ARM_ATOM_H_