This commit is contained in:
Matt Borgerson 2023-08-01 01:33:55 -07:00
parent e5dd3cc1ce
commit c32cb4f6a3
4 changed files with 84 additions and 1 deletions

View file

@ -24,6 +24,7 @@
*/
#include "qemu/osdep.h"
#include "qemu/thread.h"
#include "sysemu/tcg.h"
#include "sysemu/replay.h"
#include "sysemu/cpu-timers.h"
@ -62,11 +63,61 @@ static void mttcg_force_rcu(Notifier *notify, void *data)
* current CPUState for a given thread.
*/
static void qemu_thread_set_affinity_simple(int core_id) {
int nbits =
#ifdef _WIN32
64
#else
sysconf(_SC_NPROCESSORS_ONLN);
#endif
unsigned long *bitmap = bitmap_new(nbits);
core_id = core_id % nbits;
set_bit(core_id, bitmap);
QemuThread thread;
qemu_thread_get_self(&thread);
int ret = qemu_thread_set_affinity(&thread, bitmap, nbits);
if (ret) {
fprintf(stderr, "Setting CPU affinity failed\n");
}
g_free(bitmap);
}
static void qemu_thread_clear_affinity(void) {
int nbits =
#ifdef _WIN32
64
#else
sysconf(_SC_NPROCESSORS_ONLN);
#endif
unsigned long *bitmap = bitmap_new(nbits);
for (int i = 0; i < nbits; i++) {
set_bit(i, bitmap);
}
QemuThread thread;
qemu_thread_get_self(&thread);
int ret = qemu_thread_set_affinity(&thread, bitmap, nbits);
if (ret) {
fprintf(stderr, "Setting CPU affinity failed\n");
}
g_free(bitmap);
}
#include "ui/xemu-settings.h"
static bool pinned = false;
static void *mttcg_cpu_thread_fn(void *arg)
{
MttcgForceRcuNotifier force_rcu;
CPUState *cpu = arg;
qemu_thread_set_affinity_simple(0);
assert(tcg_enabled());
g_assert(!icount_enabled());
@ -89,6 +140,15 @@ static void *mttcg_cpu_thread_fn(void *arg)
cpu->exit_request = 1;
do {
if (pinned != g_config.perf.pin_cpu_thread) {
if (g_config.perf.pin_cpu_thread) {
qemu_thread_set_affinity_simple(0);
} else {
qemu_thread_clear_affinity();
}
pinned = g_config.perf.pin_cpu_thread;
}
if (cpu_can_run(cpu)) {
int r;
qemu_mutex_unlock_iothread();

View file

@ -209,3 +209,6 @@ perf:
cache_shaders:
type: bool
default: true
pin_cpu_thread:
type: bool
default: false

View file

@ -58,6 +58,8 @@ void MainMenuGeneralView::Draw()
Toggle("Hard FPU emulation", &g_config.perf.hard_fpu,
"Use hardware-accelerated floating point emulation (requires restart)");
#endif
Toggle("Set CPU thread affinity", &g_config.perf.pin_cpu_thread,
"Set CPU thread affinity to Logical CPU 0");
Toggle("Cache shaders to disk", &g_config.perf.cache_shaders,
"Reduce stutter in games by caching previously generated shaders");

View file

@ -15,6 +15,7 @@
#include "qemu/thread.h"
#include "qemu/notify.h"
#include "qemu-thread-common.h"
#include "qemu/bitmap.h"
#include <process.h>
static bool name_threads;
@ -480,7 +481,24 @@ void qemu_thread_create(QemuThread *thread, const char *name,
int qemu_thread_set_affinity(QemuThread *thread, unsigned long *host_cpus,
unsigned long nbits)
{
return -ENOSYS;
DWORD_PTR affinity = 0;
DWORD_PTR affinity_prev;
unsigned long value;
assert(nbits <= 64);
value = find_first_bit(host_cpus, nbits);
while (value < nbits) {
affinity |= 1ULL << value;
value = find_next_bit(host_cpus, nbits, value + 1);
}
affinity_prev =
SetThreadAffinityMask(qemu_thread_get_handle(thread), affinity);
if (!affinity_prev) {
return -1;
}
return 0;
}
int qemu_thread_get_affinity(QemuThread *thread, unsigned long **host_cpus,