Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3eab744d authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

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
parents 1fb758e9 e9d376b8
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -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;
@@ -570,6 +590,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
     * {@link #setThreadPriority(int, int)} for more information.
+79 −0
Original line number Diff line number Diff line
@@ -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},
+7 −0
Original line number Diff line number Diff line
@@ -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 *);