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

Commit f1b56449 authored by Glenn Kasten's avatar Glenn Kasten
Browse files

Scheduling group cleanup

The C++ API for scheduling groups is going away, so use the C API.

Renumber THREAD_GROUP_* constants to have the same values as SP_*.
They are @hide so this should be OK.

The old THREAD_GROUP_FG_BOOST constant is removed, and replaced by a
(private) THREAD_GROUP_FOREGROUND constant that is just a placeholder
to correspond to SP_FOREGROUND.  It is not usable at this level.

Improved performance of android_os_Process_setProcessGroup:
avoid unnecessary syscall to getpriority for each tid.

Fixed error handling in android_os_Process_setThreadGroup.
It raises an exception if set_sched_policy() returns an error.

Add comments and fix typos in existing comments.

Change-Id: Ib922e92c945985c695ef0addbd2b83b8e82865f8
parent 362bcb06
Loading
Loading
Loading
Loading
+33 −11
Original line number Diff line number Diff line
@@ -266,25 +266,38 @@ public class Process {
     */
    public static final int SCHED_IDLE = 5;

    // Keep in sync with SP_* constants of enum type SchedPolicy
    // declared in system/core/include/cutils/sched_policy.h,
    // except THREAD_GROUP_DEFAULT does not correspond to any SP_* value.

    /**
     * Default thread group - gets a 'normal' share of the CPU
     * Default thread group -
     * has meaning with setProcessGroup() only, cannot be used with setThreadGroup().
     * When used with setProcessGroup(), the group of each thread in the process
     * is conditionally changed based on that thread's current priority, as follows:
     * threads with priority numerically less than THREAD_PRIORITY_BACKGROUND
     * are moved to foreground thread group.  All other threads are left unchanged.
     * @hide
     */
    public static final int THREAD_GROUP_DEFAULT = 0;
    public static final int THREAD_GROUP_DEFAULT = -1;

    /**
     * Background non-interactive thread group - All threads in
     * Background thread group - All threads in
     * this group are scheduled with a reduced share of the CPU.
     * Value is same as constant SP_BACKGROUND of enum SchedPolicy.
     * FIXME rename to THREAD_GROUP_BACKGROUND.
     * @hide
     */
    public static final int THREAD_GROUP_BG_NONINTERACTIVE = 1;
    public static final int THREAD_GROUP_BG_NONINTERACTIVE = 0;

    /**
     * Foreground 'boost' thread group - All threads in
     * this group are scheduled with an increased share of the CPU
     * Foreground thread group - All threads in
     * this group are scheduled with a normal share of the CPU.
     * Value is same as constant SP_FOREGROUND of enum SchedPolicy.
     * Not used at this level.
     * @hide
     **/
    public static final int THREAD_GROUP_FG_BOOST = 2;
    private static final int THREAD_GROUP_FOREGROUND = 1;

    public static final int SIGNAL_QUIT = 3;
    public static final int SIGNAL_KILL = 9;
@@ -672,28 +685,37 @@ public class Process {
    /**
     * 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.
     * @param tid The identifier of the thread to change.
     * @param group The target group for this thread from THREAD_GROUP_*.
     * 
     * @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.
     * If the thread is a thread group leader, that is it's gettid() == getpid(),
     * then the other threads in the same thread group are _not_ affected.
     */
    public static final native void setThreadGroup(int tid, int group)
            throws IllegalArgumentException, SecurityException;

    /**
     * Sets the scheduling group for a process and all child threads
     * @hide
     * @param pid The indentifier of the process to change.
     * @param group The target group for this process.
     * @param pid The identifier of the process to change.
     * @param group The target group for this process from THREAD_GROUP_*.
     * 
     * @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.
     *
     * group == THREAD_GROUP_DEFAULT means to move all non-background priority
     * threads to the foreground scheduling group, but to leave background
     * priority threads alone.  group == THREAD_GROUP_BG_NONINTERACTIVE moves all
     * threads, regardless of priority, to the background scheduling group.
     * group == THREAD_GROUP_FOREGROUND is not allowed.
     */
    public static final native void setProcessGroup(int pid, int group)
            throws IllegalArgumentException, SecurityException;
+27 −13
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <cutils/sched_policy.h>
#include <utils/String8.h>
#include <utils/Vector.h>

@@ -49,6 +50,8 @@ Mutex gKeyCreateMutex;
static pthread_key_t gBgKey = -1;
#endif

// For both of these, err should be in the errno range (positive), not a status_t (negative)

static void signalExceptionForPriorityError(JNIEnv* env, int err)
{
    switch (err) {
@@ -168,27 +171,36 @@ jint android_os_Process_getGidForName(JNIEnv* env, jobject clazz, jstring name)
    return -1;
}

void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint grp)
{
    int res = androidSetThreadSchedulingGroup(pid, grp);
    ALOGV("%s tid=%d grp=%d", __func__, tid, grp);
    SchedPolicy sp = (SchedPolicy) grp;
    int res = set_sched_policy(tid, sp);
    if (res != NO_ERROR) {
        signalExceptionForGroupError(env, res == BAD_VALUE ? EINVAL : errno);
        return;
        signalExceptionForGroupError(env, -res);
    }
}

void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
{
    ALOGV("%s pid=%d grp=%d", __func__, pid, grp);
    DIR *d;
    FILE *fp;
    char proc_path[255];
    struct dirent *de;

    if (grp > ANDROID_TGROUP_MAX || grp < 0) {
    if ((grp == SP_FOREGROUND) || (grp > SP_MAX)) {
        signalExceptionForGroupError(env, EINVAL);
        return;
    }

    bool isDefault = false;
    if (grp < 0) {
        grp = SP_FOREGROUND;
        isDefault = true;
    }
    SchedPolicy sp = (SchedPolicy) grp;

#if POLICY_DEBUG
    char cmdline[32];
    int fd;
@@ -203,7 +215,7 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin
        close(fd);
    }

    if (grp == ANDROID_TGROUP_BG_NONINTERACT) {
    if (sp == SP_BACKGROUND) {
        ALOGD("setProcessGroup: vvv pid %d (%s)", pid, cmdline);
    } else {
        ALOGD("setProcessGroup: ^^^ pid %d (%s)", pid, cmdline);
@@ -230,16 +242,18 @@ void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jin
            continue;
        }

        if (isDefault) {
            t_pri = getpriority(PRIO_PROCESS, t_pid);

        if (grp == ANDROID_TGROUP_DEFAULT &&
            t_pri >= ANDROID_PRIORITY_BACKGROUND) {
            if (t_pri >= ANDROID_PRIORITY_BACKGROUND) {
                // This task wants to stay at background
                continue;
            }
        }

        if (androidSetThreadSchedulingGroup(t_pid, grp) != NO_ERROR) {
            signalExceptionForGroupError(env, errno);
        int err = set_sched_policy(t_pid, sp);
        if (err != NO_ERROR) {
            signalExceptionForGroupError(env, -err);
            break;
        }
    }