diff --git a/android/app/src/cpp/android_host_interface.cpp b/android/app/src/cpp/android_host_interface.cpp index 32424f3d3..ce6a80f44 100644 --- a/android/app/src/cpp/android_host_interface.cpp +++ b/android/app/src/cpp/android_host_interface.cpp @@ -22,6 +22,8 @@ #include "scmversion/scmversion.h" #include #include +#include +#include #include Log_SetChannel(AndroidHostInterface); @@ -952,6 +954,31 @@ DEFINE_JNI_ARGS_METHOD(jstring, AndroidHostInterface_getFullScmVersion, jobject g_scm_branch_str, __DATE__, __TIME__)); } +DEFINE_JNI_ARGS_METHOD(void, AndroidHostInterface_setThreadAffinity, jobject unused, jintArray cores) +{ + // https://github.com/googlearchive/android-audio-high-performance/blob/c232c21bf35d3bfea16537b781c526b8abdcc3cf/SimpleSynth/app/src/main/cpp/audio_player.cc + int length = env->GetArrayLength(cores); + int* p_cores = env->GetIntArrayElements(cores, nullptr); + + pid_t current_thread_id = gettid(); + cpu_set_t cpu_set; + CPU_ZERO(&cpu_set); + for (int i = 0; i < length; i++) + { + Log_InfoPrintf("Binding to CPU %d", p_cores[i]); + CPU_SET(p_cores[i], &cpu_set); + } + + int result = sched_setaffinity(current_thread_id, sizeof(cpu_set_t), &cpu_set); + if (result != 0) + Log_InfoPrintf("Thread affinity set."); + else + Log_ErrorPrintf("Error setting thread affinity: %d", result); + + env->ReleaseIntArrayElements(cores, p_cores, 0); +} + + DEFINE_JNI_ARGS_METHOD(jobject, AndroidHostInterface_create, jobject unused, jobject context_object, jstring user_directory) { diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/AndroidHostInterface.java b/android/app/src/main/java/com/github/stenzek/duckstation/AndroidHostInterface.java index cac1b4d00..5225fc55e 100644 --- a/android/app/src/main/java/com/github/stenzek/duckstation/AndroidHostInterface.java +++ b/android/app/src/main/java/com/github/stenzek/duckstation/AndroidHostInterface.java @@ -45,6 +45,8 @@ public class AndroidHostInterface { static public native String getFullScmVersion(); + static public native boolean setThreadAffinity(int[] cpus); + static public native AndroidHostInterface create(Context context, String userDirectory); public native boolean isEmulationThreadRunning(); diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/EmulationThread.java b/android/app/src/main/java/com/github/stenzek/duckstation/EmulationThread.java index 7210d8f8a..0bdcf25d9 100644 --- a/android/app/src/main/java/com/github/stenzek/duckstation/EmulationThread.java +++ b/android/app/src/main/java/com/github/stenzek/duckstation/EmulationThread.java @@ -1,5 +1,6 @@ package com.github.stenzek.duckstation; +import android.os.Build; import android.os.Process; import android.util.Log; import android.view.Surface; @@ -28,10 +29,25 @@ public class EmulationThread extends Thread { return thread; } + private void setExclusiveCores() { + try { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + int[] cores = Process.getExclusiveCores(); + if (cores == null || cores.length == 0) + throw new Exception("Invalid return value from getExclusiveCores()"); + + AndroidHostInterface.setThreadAffinity(cores); + } + } catch (Exception e) { + Log.e("EmulationThread", "getExclusiveCores() failed"); + } + } + @Override public void run() { try { Process.setThreadPriority(Process.THREAD_PRIORITY_MORE_FAVORABLE); + setExclusiveCores(); } catch (Exception e) { Log.i("EmulationThread", "Failed to set priority for emulation thread: " + e.getMessage()); }