Merge change 376 into donut
* changes: Add support for changing a threads scheduler group. Three groups are available (default, background non interactive, foreground boost). Setting a thread priority to PRIORITY_BACKGROUND will transparently change groups to background
This commit is contained in:
@@ -176,6 +176,26 @@ public class Process {
|
||||
*/
|
||||
public static final int THREAD_PRIORITY_LESS_FAVORABLE = +1;
|
||||
|
||||
/**
|
||||
* Default thread group - gets a 'normal' share of the CPU
|
||||
* @hide
|
||||
*/
|
||||
public static final int THREAD_GROUP_DEFAULT = 0;
|
||||
|
||||
/**
|
||||
* Background non-interactive thread group - All threads in
|
||||
* this group are scheduled with a reduced share of the CPU.
|
||||
* @hide
|
||||
*/
|
||||
public static final int THREAD_GROUP_BG_NONINTERACTIVE = 1;
|
||||
|
||||
/**
|
||||
* Foreground 'boost' thread group - All threads in
|
||||
* this group are scheduled with an increased share of the CPU
|
||||
* @hide
|
||||
**/
|
||||
public static final int THREAD_GROUP_FG_BOOST = 2;
|
||||
|
||||
public static final int SIGNAL_QUIT = 3;
|
||||
public static final int SIGNAL_KILL = 9;
|
||||
public static final int SIGNAL_USR1 = 10;
|
||||
@@ -569,6 +589,21 @@ public class Process {
|
||||
*/
|
||||
public static final native void setThreadPriority(int tid, int priority)
|
||||
throws IllegalArgumentException, SecurityException;
|
||||
|
||||
/**
|
||||
* Sets the scheduling group for a thread.
|
||||
* @hide
|
||||
* @param tid The indentifier of the thread/process to change.
|
||||
* @param group The target group for this thread/process.
|
||||
*
|
||||
* @throws IllegalArgumentException Throws IllegalArgumentException if
|
||||
* <var>tid</var> does not exist.
|
||||
* @throws SecurityException Throws SecurityException if your process does
|
||||
* not have permission to modify the given thread, or to use the given
|
||||
* priority.
|
||||
*/
|
||||
public static final native void setThreadGroup(int tid, int group)
|
||||
throws IllegalArgumentException, SecurityException;
|
||||
|
||||
/**
|
||||
* Set the priority of the calling thread, based on Linux priorities. See
|
||||
|
||||
@@ -50,6 +50,16 @@ pid_t gettid() { return syscall(__NR_gettid);}
|
||||
#undef __KERNEL__
|
||||
#endif
|
||||
|
||||
#define ENABLE_CGROUP_ERR_LOGGING 0
|
||||
|
||||
/*
|
||||
* List of cgroup names which map to ANDROID_TGROUP_ values in Thread.h
|
||||
* and Process.java
|
||||
* These names are used to construct the path to the cgroup control dir
|
||||
*/
|
||||
|
||||
static const char *cgroup_names[] = { NULL, "bg_non_interactive", "fg_boost" };
|
||||
|
||||
using namespace android;
|
||||
|
||||
static void signalExceptionForPriorityError(JNIEnv* env, jobject obj, int err)
|
||||
@@ -73,6 +83,28 @@ static void signalExceptionForPriorityError(JNIEnv* env, jobject obj, int err)
|
||||
}
|
||||
}
|
||||
|
||||
static void signalExceptionForGroupError(JNIEnv* env, jobject obj, int err)
|
||||
{
|
||||
switch (err) {
|
||||
case EINVAL:
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
|
||||
break;
|
||||
case ESRCH:
|
||||
jniThrowException(env, "java/lang/IllegalArgumentException", "Given thread does not exist");
|
||||
break;
|
||||
case EPERM:
|
||||
jniThrowException(env, "java/lang/SecurityException", "No permission to modify given thread");
|
||||
break;
|
||||
case EACCES:
|
||||
jniThrowException(env, "java/lang/SecurityException", "No permission to set to given group");
|
||||
break;
|
||||
default:
|
||||
jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void fakeProcessEntry(void* arg)
|
||||
{
|
||||
String8* cls = (String8*)arg;
|
||||
@@ -164,9 +196,55 @@ jint android_os_Process_getGidForName(JNIEnv* env, jobject clazz, jstring name)
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int add_pid_to_cgroup(int pid, int grp)
|
||||
{
|
||||
FILE *fp;
|
||||
char path[255];
|
||||
int rc;
|
||||
|
||||
sprintf(path, "/dev/cpuctl/%s/tasks", (cgroup_names[grp] ? cgroup_names[grp] : ""));
|
||||
|
||||
if (!(fp = fopen(path, "w"))) {
|
||||
#if ENABLE_CGROUP_ERR_LOGGING
|
||||
LOGW("Unable to open %s (%s)\n", path, strerror(errno));
|
||||
#endif
|
||||
return -errno;
|
||||
}
|
||||
|
||||
rc = fprintf(fp, "%d", pid);
|
||||
fclose(fp);
|
||||
|
||||
if (rc < 0) {
|
||||
#if ENABLE_CGROUP_ERR_LOGGING
|
||||
LOGW("Unable to move pid %d to cgroup %s (%s)\n", pid,
|
||||
(cgroup_names[grp] ? cgroup_names[grp] : "<default>"),
|
||||
strerror(errno));
|
||||
#endif
|
||||
}
|
||||
|
||||
return (rc < 0) ? errno : 0;
|
||||
}
|
||||
|
||||
void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
|
||||
{
|
||||
if (grp > ANDROID_TGROUP_MAX || grp < 0) {
|
||||
signalExceptionForGroupError(env, clazz, EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (add_pid_to_cgroup(pid, grp))
|
||||
signalExceptionForGroupError(env, clazz, errno);
|
||||
}
|
||||
|
||||
void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz,
|
||||
jint pid, jint pri)
|
||||
{
|
||||
if (pri == ANDROID_PRIORITY_BACKGROUND) {
|
||||
add_pid_to_cgroup(pid, ANDROID_TGROUP_BG_NONINTERACT);
|
||||
} else if (getpriority(PRIO_PROCESS, pid) == ANDROID_PRIORITY_BACKGROUND) {
|
||||
add_pid_to_cgroup(pid, ANDROID_TGROUP_DEFAULT);
|
||||
}
|
||||
|
||||
if (setpriority(PRIO_PROCESS, pid, pri) < 0) {
|
||||
signalExceptionForPriorityError(env, clazz, errno);
|
||||
}
|
||||
@@ -741,6 +819,7 @@ static const JNINativeMethod methods[] = {
|
||||
{"setThreadPriority", "(II)V", (void*)android_os_Process_setThreadPriority},
|
||||
{"setThreadPriority", "(I)V", (void*)android_os_Process_setCallingThreadPriority},
|
||||
{"getThreadPriority", "(I)I", (void*)android_os_Process_getThreadPriority},
|
||||
{"setThreadGroup", "(II)V", (void*)android_os_Process_setThreadGroup},
|
||||
{"setOomAdj", "(II)Z", (void*)android_os_Process_setOomAdj},
|
||||
{"setArgV0", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
|
||||
{"setUid", "(I)I", (void*)android_os_Process_setUid},
|
||||
|
||||
@@ -79,6 +79,13 @@ enum {
|
||||
ANDROID_PRIORITY_LESS_FAVORABLE = +1,
|
||||
};
|
||||
|
||||
enum {
|
||||
ANDROID_TGROUP_DEFAULT = 0,
|
||||
ANDROID_TGROUP_BG_NONINTERACT = 1,
|
||||
ANDROID_TGROUP_FG_BOOST = 2,
|
||||
ANDROID_TGROUP_MAX = ANDROID_TGROUP_FG_BOOST,
|
||||
};
|
||||
|
||||
// Create and run a new thread.
|
||||
extern int androidCreateThread(android_thread_func_t, void *);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user