Merge "API to query which cores are exclusively assigned." into nyc-dev
am: 2612bbc0f5
* commit '2612bbc0f5ae5422ba3e8e685ae375b2b8626fda':
API to query which cores are exclusively assigned.
This commit is contained in:
@@ -29124,6 +29124,7 @@ package android.os {
|
||||
public class Process {
|
||||
ctor public Process();
|
||||
method public static final long getElapsedCpuTime();
|
||||
method public static final int[] getExclusiveCores();
|
||||
method public static final int getGidForName(java.lang.String);
|
||||
method public static final long getStartElapsedRealtime();
|
||||
method public static final long getStartUptimeMillis();
|
||||
|
||||
@@ -31412,6 +31412,7 @@ package android.os {
|
||||
public class Process {
|
||||
ctor public Process();
|
||||
method public static final long getElapsedCpuTime();
|
||||
method public static final int[] getExclusiveCores();
|
||||
method public static final int getGidForName(java.lang.String);
|
||||
method public static final long getStartElapsedRealtime();
|
||||
method public static final long getStartUptimeMillis();
|
||||
|
||||
@@ -29135,6 +29135,7 @@ package android.os {
|
||||
public class Process {
|
||||
ctor public Process();
|
||||
method public static final long getElapsedCpuTime();
|
||||
method public static final int[] getExclusiveCores();
|
||||
method public static final int getGidForName(java.lang.String);
|
||||
method public static final long getStartElapsedRealtime();
|
||||
method public static final long getStartUptimeMillis();
|
||||
|
||||
@@ -997,6 +997,31 @@ public class Process {
|
||||
public static final native int getProcessGroup(int pid)
|
||||
throws IllegalArgumentException, SecurityException;
|
||||
|
||||
/**
|
||||
* On some devices, the foreground process may have one or more CPU
|
||||
* cores exclusively reserved for it. This method can be used to
|
||||
* retrieve which cores that are (if any), so the calling process
|
||||
* can then use sched_setaffinity() to lock a thread to these cores.
|
||||
* Note that the calling process must currently be running in the
|
||||
* foreground for this method to return any cores.
|
||||
*
|
||||
* The CPU core(s) exclusively reserved for the foreground process will
|
||||
* stay reserved for as long as the process stays in the foreground.
|
||||
*
|
||||
* As soon as a process leaves the foreground, those CPU cores will
|
||||
* no longer be reserved for it, and will most likely be reserved for
|
||||
* the new foreground process. It's not necessary to change the affinity
|
||||
* of your process when it leaves the foreground (if you had previously
|
||||
* set it to use a reserved core); the OS will automatically take care
|
||||
* of resetting the affinity at that point.
|
||||
*
|
||||
* @return an array of integers, indicating the CPU cores exclusively
|
||||
* reserved for this process. The array will have length zero if no
|
||||
* CPU cores are exclusively reserved for this process at this point
|
||||
* in time.
|
||||
*/
|
||||
public static final native int[] getExclusiveCores();
|
||||
|
||||
/**
|
||||
* Set the priority of the calling thread, based on Linux priorities. See
|
||||
* {@link #setThreadPriority(int, int)} for more information.
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#define LOG_TAG "Process"
|
||||
|
||||
// To make sure cpu_set_t is included from sched.h
|
||||
#define _GNU_SOURCE 1
|
||||
#include <utils/Log.h>
|
||||
#include <binder/IPCThreadState.h>
|
||||
#include <binder/IServiceManager.h>
|
||||
@@ -288,6 +290,139 @@ jint android_os_Process_getProcessGroup(JNIEnv* env, jobject clazz, jint pid)
|
||||
return (int) sp;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_CPUSETS
|
||||
/** Sample CPUset list format:
|
||||
* 0-3,4,6-8
|
||||
*/
|
||||
static void parse_cpuset_cpus(char *cpus, cpu_set_t *cpu_set) {
|
||||
unsigned int start, end, matched, i;
|
||||
char *cpu_range = strtok(cpus, ",");
|
||||
while (cpu_range != NULL) {
|
||||
start = end = 0;
|
||||
matched = sscanf(cpu_range, "%u-%u", &start, &end);
|
||||
cpu_range = strtok(NULL, ",");
|
||||
if (start >= CPU_SETSIZE) {
|
||||
ALOGE("parse_cpuset_cpus: ignoring CPU number larger than %d.", CPU_SETSIZE);
|
||||
continue;
|
||||
} else if (end >= CPU_SETSIZE) {
|
||||
ALOGE("parse_cpuset_cpus: ignoring CPU numbers larger than %d.", CPU_SETSIZE);
|
||||
end = CPU_SETSIZE - 1;
|
||||
}
|
||||
if (matched == 1) {
|
||||
CPU_SET(start, cpu_set);
|
||||
} else if (matched == 2) {
|
||||
for (i = start; i <= end; i++) {
|
||||
CPU_SET(i, cpu_set);
|
||||
}
|
||||
} else {
|
||||
ALOGE("Failed to match cpus");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the CPUs assigned to the cpuset corresponding to the
|
||||
* SchedPolicy in the passed in cpu_set.
|
||||
*/
|
||||
static void get_cpuset_cores_for_policy(SchedPolicy policy, cpu_set_t *cpu_set)
|
||||
{
|
||||
FILE *file;
|
||||
const char *filename;
|
||||
|
||||
CPU_ZERO(cpu_set);
|
||||
|
||||
switch (policy) {
|
||||
case SP_BACKGROUND:
|
||||
filename = "/dev/cpuset/background/cpus";
|
||||
break;
|
||||
case SP_FOREGROUND:
|
||||
case SP_AUDIO_APP:
|
||||
case SP_AUDIO_SYS:
|
||||
filename = "/dev/cpuset/foreground/cpus";
|
||||
break;
|
||||
case SP_TOP_APP:
|
||||
filename = "/dev/cpuset/top-app/cpus";
|
||||
break;
|
||||
default:
|
||||
filename = NULL;
|
||||
}
|
||||
|
||||
if (!filename) return;
|
||||
|
||||
file = fopen(filename, "re");
|
||||
if (file != NULL) {
|
||||
// Parse cpus string
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t num_read = getline(&line, &len, file);
|
||||
fclose (file);
|
||||
if (num_read > 0) {
|
||||
parse_cpuset_cpus(line, cpu_set);
|
||||
} else {
|
||||
ALOGE("Failed to read %s", filename);
|
||||
}
|
||||
free(line);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Determine CPU cores exclusively assigned to the
|
||||
* cpuset corresponding to the SchedPolicy and store
|
||||
* them in the passed in cpu_set_t
|
||||
*/
|
||||
void get_exclusive_cpuset_cores(SchedPolicy policy, cpu_set_t *cpu_set) {
|
||||
#ifdef ENABLE_CPUSETS
|
||||
int i;
|
||||
cpu_set_t tmp_set;
|
||||
get_cpuset_cores_for_policy(policy, cpu_set);
|
||||
for (i = 0; i < SP_CNT; i++) {
|
||||
if ((SchedPolicy) i == policy) continue;
|
||||
get_cpuset_cores_for_policy((SchedPolicy)i, &tmp_set);
|
||||
// First get cores exclusive to one set or the other
|
||||
CPU_XOR(&tmp_set, cpu_set, &tmp_set);
|
||||
// Then get the ones only in cpu_set
|
||||
CPU_AND(cpu_set, cpu_set, &tmp_set);
|
||||
}
|
||||
#else
|
||||
(void) policy;
|
||||
CPU_ZERO(cpu_set);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
jintArray android_os_Process_getExclusiveCores(JNIEnv* env, jobject clazz) {
|
||||
SchedPolicy sp;
|
||||
cpu_set_t cpu_set;
|
||||
jintArray cpus;
|
||||
int pid = getpid();
|
||||
if (get_sched_policy(pid, &sp) != 0) {
|
||||
signalExceptionForGroupError(env, errno);
|
||||
return NULL;
|
||||
}
|
||||
get_exclusive_cpuset_cores(sp, &cpu_set);
|
||||
int num_cpus = CPU_COUNT(&cpu_set);
|
||||
cpus = env->NewIntArray(num_cpus);
|
||||
if (cpus == NULL) {
|
||||
jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jint* cpu_elements = env->GetIntArrayElements(cpus, 0);
|
||||
int count = 0;
|
||||
for (int i = 0; i < CPU_SETSIZE && count < num_cpus; i++) {
|
||||
if (CPU_ISSET(i, &cpu_set)) {
|
||||
cpu_elements[count++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
env->ReleaseIntArrayElements(cpus, cpu_elements, 0);
|
||||
return cpus;
|
||||
}
|
||||
|
||||
static void android_os_Process_setCanSelfBackground(JNIEnv* env, jobject clazz, jboolean bgOk) {
|
||||
// Establishes the calling thread as illegal to put into the background.
|
||||
// Typically used only for the system process's main looper.
|
||||
@@ -1053,6 +1188,7 @@ static const JNINativeMethod methods[] = {
|
||||
{"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup},
|
||||
{"setProcessGroup", "(II)V", (void*)android_os_Process_setProcessGroup},
|
||||
{"getProcessGroup", "(I)I", (void*)android_os_Process_getProcessGroup},
|
||||
{"getExclusiveCores", "()[I", (void*)android_os_Process_getExclusiveCores},
|
||||
{"setSwappiness", "(IZ)Z", (void*)android_os_Process_setSwappiness},
|
||||
{"setArgV0", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
|
||||
{"setUid", "(I)I", (void*)android_os_Process_setUid},
|
||||
|
||||
Reference in New Issue
Block a user