android: add affinity support with config

add aarch64 get_cpu_name
teach cfg::try_to_enum_value and cfg::try_to_enum_list ignore gaps
This commit is contained in:
DH 2025-03-19 05:03:15 +03:00
parent 1585817013
commit 6ad58c8813
6 changed files with 94 additions and 8 deletions

View file

@ -226,6 +226,7 @@ bool try_to_string(std::string* out, const f64& value)
bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) func, std::string_view value)
{
u64 max = umax;
std::size_t gap = 0;
for (u64 i = 0;; i++)
{
@ -242,9 +243,15 @@ bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) f
fmt_class_string<u64>::format(hex, i);
if (var == hex)
{
break;
if (++gap > 100)
{
break;
}
continue;
}
gap = 0;
max = i;
}
@ -281,6 +288,7 @@ bool cfg::try_to_enum_value(u64* out, decltype(&fmt_class_string<int>::format) f
std::vector<std::string> cfg::try_to_enum_list(decltype(&fmt_class_string<int>::format) func)
{
std::vector<std::string> result;
std::size_t gap = 0;
for (u64 i = 0;; i++)
{
@ -291,9 +299,16 @@ std::vector<std::string> cfg::try_to_enum_list(decltype(&fmt_class_string<int>::
fmt_class_string<u64>::format(hex, i);
if (var == hex)
{
break;
if (++gap > 100)
{
break;
}
continue;
}
gap = 0;
result.emplace_back(std::move(var));
}

View file

@ -111,6 +111,22 @@ extern thread_local std::string(*g_tls_log_prefix)();
enum cpu_threads_emulation_info_dump_t : u32 {};
template<>
void fmt_class_string<thread_class>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](thread_class value)
{
switch (value)
{
case thread_class::general: return "General";
case thread_class::ppu: return "PPU";
case thread_class::spu: return "SPU";
case thread_class::rsx: return "RSX";
}
return unknown;
});
}
std::string dump_useful_thread_info()
{
std::string result;
@ -2926,6 +2942,28 @@ void thread_ctrl::detect_cpu_layout()
u64 thread_ctrl::get_affinity_mask(thread_class group)
{
#ifdef ANDROID
u64 mask = 0;
thread_class affinities[] = {
g_cfg.core.affinity.cpu0.get(),
g_cfg.core.affinity.cpu1.get(),
g_cfg.core.affinity.cpu2.get(),
g_cfg.core.affinity.cpu3.get(),
g_cfg.core.affinity.cpu4.get(),
g_cfg.core.affinity.cpu5.get(),
g_cfg.core.affinity.cpu6.get(),
g_cfg.core.affinity.cpu7.get()
};
for (std::size_t i = 0; i < std::size(affinities); ++i) {
if (affinities[i] == group || affinities[i] == thread_class::general) {
mask |= 1ull < i;
}
}
return mask;
#endif
detect_cpu_layout();
if (const auto thread_count = utils::get_thread_count())
@ -3205,7 +3243,7 @@ void thread_ctrl::set_thread_affinity_mask(u64 mask)
thread_affinity_policy_data_t policy = { static_cast<integer_t>(std::countr_zero(mask)) };
thread_port_t mach_thread = pthread_mach_thread_np(pthread_self());
thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, reinterpret_cast<thread_policy_t>(&policy), !mask ? 0 : 1);
#elif !defined(ANDROID) && (defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__))
#elif (defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__))
if (!mask)
{
// Reset affinity mask
@ -3232,8 +3270,11 @@ void thread_ctrl::set_thread_affinity_mask(u64 mask)
break;
}
}
#ifdef ANDROID
if (int err = sched_setaffinity(::gettid(), sizeof(cpu_set_t), &cs))
#else
if (int err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cs))
#endif
{
sig_log.error("Failed to set thread affinity 0x%x: error %d.", mask, err);
}
@ -3257,11 +3298,15 @@ u64 thread_ctrl::get_thread_affinity_mask()
sig_log.error("Failed to get thread affinity mask.");
return 0;
#elif !defined(ANDROID) && (defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__))
#elif (defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__))
cpu_set_t cs;
CPU_ZERO(&cs);
#ifdef ANDROID
if (int err = sched_getaffinity(::gettid(), sizeof(cpu_set_t), &cs))
#else
if (int err = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cs))
#endif
{
sig_log.error("Failed to get thread affinity mask: error %d.", err);
return 0;

View file

@ -246,6 +246,16 @@ namespace aarch64
#endif
}
const char *get_cpu_name(int cpu)
{
const auto midr = read_MIDR_EL1(cpu);
const auto implementer_id = (midr >> 24) & 0xff;
const auto part_id = (midr >> 4) & 0xfff;
const auto part_info = find_cpu_part(implementer_id, part_id);
return part_info ? part_info->name : nullptr;
}
std::string get_cpu_name()
{
std::map<u64, int> core_layout;

View file

@ -37,6 +37,7 @@ namespace aarch64
"xzr", ".", "sp"
};
const char *get_cpu_name(int cpu);
std::string get_cpu_name();
std::string get_cpu_brand();
}

View file

@ -1,5 +1,6 @@
#pragma once
#include "Utilities/Thread.h"
#include "system_config_types.h"
#include "Utilities/Config.h"
@ -46,6 +47,22 @@ struct cfg_root : cfg::node
cfg::_bool accurate_cache_line_stores{ this, "Accurate Cache Line Stores", false };
cfg::_bool rsx_accurate_res_access{this, "Accurate RSX reservation access", false, true};
#ifdef ANDROID
struct node_affinity : cfg::node
{
public:
node_affinity(cfg::node* _this) : cfg::node(_this, "Affinity") {}
cfg::_enum<thread_class> cpu0{this, "CPU0", thread_class::general, true};
cfg::_enum<thread_class> cpu1{this, "CPU1", thread_class::general, true};
cfg::_enum<thread_class> cpu2{this, "CPU2", thread_class::general, true};
cfg::_enum<thread_class> cpu3{this, "CPU3", thread_class::general, true};
cfg::_enum<thread_class> cpu4{this, "CPU4", thread_class::general, true};
cfg::_enum<thread_class> cpu5{this, "CPU5", thread_class::general, true};
cfg::_enum<thread_class> cpu6{this, "CPU6", thread_class::general, true};
cfg::_enum<thread_class> cpu7{this, "CPU7", thread_class::general, true};
} affinity { this };
#endif
struct fifo_setting : public cfg::_enum<rsx_fifo_mode>
{
using _enum = cfg::_enum<rsx_fifo_mode>;

View file

@ -197,8 +197,7 @@ namespace utils
}
}
#elif __linux__
#ifndef ANDROID
#elif __linux__ && !defined(ANDROID)
m_previous_idle_times_per_cpu.resize(utils::get_thread_count(), 0.0);
m_previous_total_times_per_cpu.resize(utils::get_thread_count(), 0.0);
@ -289,7 +288,6 @@ namespace utils
{
perf_log.error("Failed to open /proc/stat (%s)", strerror(errno));
}
#endif
#else
total_usage = get_usage();
#endif