sched_policy.c revision 805d67ab11c1bb21d494459d6167f5f67f0002eb
10384a98d6f61fa47ffde01c15e552f738e88fb94Raphael
2493dad966305a7fb555addd367532dd2af275a27San Mehat/* libs/cutils/sched_policy.c
3493dad966305a7fb555addd367532dd2af275a27San Mehat**
4493dad966305a7fb555addd367532dd2af275a27San Mehat** Copyright 2007, The Android Open Source Project
5493dad966305a7fb555addd367532dd2af275a27San Mehat**
6493dad966305a7fb555addd367532dd2af275a27San Mehat** Licensed under the Apache License, Version 2.0 (the "License");
7493dad966305a7fb555addd367532dd2af275a27San Mehat** you may not use this file except in compliance with the License.
8493dad966305a7fb555addd367532dd2af275a27San Mehat** You may obtain a copy of the License at
9493dad966305a7fb555addd367532dd2af275a27San Mehat**
10493dad966305a7fb555addd367532dd2af275a27San Mehat**     http://www.apache.org/licenses/LICENSE-2.0
11493dad966305a7fb555addd367532dd2af275a27San Mehat**
12493dad966305a7fb555addd367532dd2af275a27San Mehat** Unless required by applicable law or agreed to in writing, software
13493dad966305a7fb555addd367532dd2af275a27San Mehat** distributed under the License is distributed on an "AS IS" BASIS,
14493dad966305a7fb555addd367532dd2af275a27San Mehat** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15493dad966305a7fb555addd367532dd2af275a27San Mehat** See the License for the specific language governing permissions and
16493dad966305a7fb555addd367532dd2af275a27San Mehat** limitations under the License.
17493dad966305a7fb555addd367532dd2af275a27San Mehat*/
18493dad966305a7fb555addd367532dd2af275a27San Mehat
19493dad966305a7fb555addd367532dd2af275a27San Mehat#include <stdio.h>
20493dad966305a7fb555addd367532dd2af275a27San Mehat#include <stdlib.h>
21493dad966305a7fb555addd367532dd2af275a27San Mehat#include <unistd.h>
22493dad966305a7fb555addd367532dd2af275a27San Mehat#include <string.h>
23493dad966305a7fb555addd367532dd2af275a27San Mehat#include <errno.h>
24493dad966305a7fb555addd367532dd2af275a27San Mehat#include <fcntl.h>
250384a98d6f61fa47ffde01c15e552f738e88fb94Raphael
26d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat#define LOG_TAG "SchedPolicy"
27d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat#include "cutils/log.h"
28d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat
290384a98d6f61fa47ffde01c15e552f738e88fb94Raphael#ifdef HAVE_SCHED_H
300384a98d6f61fa47ffde01c15e552f738e88fb94Raphael
31493dad966305a7fb555addd367532dd2af275a27San Mehat#include <sched.h>
32493dad966305a7fb555addd367532dd2af275a27San Mehat
33493dad966305a7fb555addd367532dd2af275a27San Mehat#include <cutils/sched_policy.h>
34493dad966305a7fb555addd367532dd2af275a27San Mehat
353cd5b66ba05cffe38bfa4e2da9b93292ba0b073aSan Mehat#ifndef SCHED_NORMAL
363cd5b66ba05cffe38bfa4e2da9b93292ba0b073aSan Mehat  #define SCHED_NORMAL 0
373cd5b66ba05cffe38bfa4e2da9b93292ba0b073aSan Mehat#endif
383cd5b66ba05cffe38bfa4e2da9b93292ba0b073aSan Mehat
393cd5b66ba05cffe38bfa4e2da9b93292ba0b073aSan Mehat#ifndef SCHED_BATCH
403cd5b66ba05cffe38bfa4e2da9b93292ba0b073aSan Mehat  #define SCHED_BATCH 3
413cd5b66ba05cffe38bfa4e2da9b93292ba0b073aSan Mehat#endif
423cd5b66ba05cffe38bfa4e2da9b93292ba0b073aSan Mehat
43805d67ab11c1bb21d494459d6167f5f67f0002ebSan Mehat#define POLICY_DEBUG 0
44d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat
45c0dfca7ae1f6016461235552091c2cacacca82a2San Mehatstatic int __sys_supports_schedgroups = -1;
46c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat
47493dad966305a7fb555addd367532dd2af275a27San Mehatstatic int add_tid_to_cgroup(int tid, const char *grp_name)
48493dad966305a7fb555addd367532dd2af275a27San Mehat{
49493dad966305a7fb555addd367532dd2af275a27San Mehat    int fd;
50493dad966305a7fb555addd367532dd2af275a27San Mehat    char path[255];
51493dad966305a7fb555addd367532dd2af275a27San Mehat    char text[64];
52493dad966305a7fb555addd367532dd2af275a27San Mehat
53493dad966305a7fb555addd367532dd2af275a27San Mehat    sprintf(path, "/dev/cpuctl/%s/tasks", grp_name);
54493dad966305a7fb555addd367532dd2af275a27San Mehat
55805d67ab11c1bb21d494459d6167f5f67f0002ebSan Mehat    if ((fd = open(path, O_WRONLY)) < 0) {
56805d67ab11c1bb21d494459d6167f5f67f0002ebSan Mehat        LOGE("add_tid_to_cgroup failed to open '%s' (%s)\n", path, strerror(errno));
57493dad966305a7fb555addd367532dd2af275a27San Mehat        return -1;
58805d67ab11c1bb21d494459d6167f5f67f0002ebSan Mehat    }
59493dad966305a7fb555addd367532dd2af275a27San Mehat
60493dad966305a7fb555addd367532dd2af275a27San Mehat    sprintf(text, "%d", tid);
61493dad966305a7fb555addd367532dd2af275a27San Mehat    if (write(fd, text, strlen(text)) < 0) {
62493dad966305a7fb555addd367532dd2af275a27San Mehat        close(fd);
63493dad966305a7fb555addd367532dd2af275a27San Mehat        return -1;
64493dad966305a7fb555addd367532dd2af275a27San Mehat    }
65493dad966305a7fb555addd367532dd2af275a27San Mehat
66493dad966305a7fb555addd367532dd2af275a27San Mehat    close(fd);
67493dad966305a7fb555addd367532dd2af275a27San Mehat    return 0;
68493dad966305a7fb555addd367532dd2af275a27San Mehat}
69493dad966305a7fb555addd367532dd2af275a27San Mehat
70c0dfca7ae1f6016461235552091c2cacacca82a2San Mehatstatic inline void initialize()
71493dad966305a7fb555addd367532dd2af275a27San Mehat{
72493dad966305a7fb555addd367532dd2af275a27San Mehat    if (__sys_supports_schedgroups < 0) {
73493dad966305a7fb555addd367532dd2af275a27San Mehat        if (!access("/dev/cpuctl/tasks", F_OK)) {
74493dad966305a7fb555addd367532dd2af275a27San Mehat            __sys_supports_schedgroups = 1;
75493dad966305a7fb555addd367532dd2af275a27San Mehat        } else {
76493dad966305a7fb555addd367532dd2af275a27San Mehat            __sys_supports_schedgroups = 0;
77493dad966305a7fb555addd367532dd2af275a27San Mehat        }
78493dad966305a7fb555addd367532dd2af275a27San Mehat    }
79c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat}
80c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat
81c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat/*
82c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat * Try to get the scheduler group.
83c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat *
84c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat * The data from /proc/<pid>/cgroup looks like:
85c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat *  2:cpu:/bg_non_interactive
86c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat *
87c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat * We return the part after the "/", which will be an empty string for
88c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat * the default cgroup.  If the string is longer than "bufLen", the string
89c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat * will be truncated.
90c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat */
91c0dfca7ae1f6016461235552091c2cacacca82a2San Mehatstatic int getSchedulerGroup(int tid, char* buf, size_t bufLen)
92c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat{
93c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat#ifdef HAVE_ANDROID_OS
94c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    char pathBuf[32];
95c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    char readBuf[256];
96c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    ssize_t count;
97c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    int fd;
98c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat
99c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    snprintf(pathBuf, sizeof(pathBuf), "/proc/%d/cgroup", tid);
100c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    if ((fd = open(pathBuf, O_RDONLY)) < 0) {
101c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        return -1;
102c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    }
103c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat
104c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    count = read(fd, readBuf, sizeof(readBuf));
105c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    if (count <= 0) {
106c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        close(fd);
107c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        errno = ENODATA;
108c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        return -1;
109c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    }
110c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    close(fd);
111c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat
112c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    readBuf[--count] = '\0';    /* remove the '\n', now count==strlen */
113c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat
114c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    char* cp = strchr(readBuf, '/');
115c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    if (cp == NULL) {
116c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        readBuf[sizeof(readBuf)-1] = '\0';
117c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        errno = ENODATA;
118c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        return -1;
119c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    }
120c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat
121c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    memcpy(buf, cp+1, count);   /* count-1 for cp+1, count+1 for NUL */
122c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    return 0;
123c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat#else
124c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    errno = ENOSYS;
125c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    return -1;
126c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat#endif
127c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat}
128c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat
129c0dfca7ae1f6016461235552091c2cacacca82a2San Mehatint get_sched_policy(int tid, SchedPolicy *policy)
130c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat{
131c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    initialize();
132c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat
133c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    if (__sys_supports_schedgroups) {
134c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        char grpBuf[32];
135c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        if (getSchedulerGroup(tid, grpBuf, sizeof(grpBuf)) < 0)
136c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat            return -1;
137c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        if (grpBuf[0] == '\0') {
138c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat            *policy = SP_FOREGROUND;
139c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        } else if (!strcmp(grpBuf, "bg_non_interactive")) {
140c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat            *policy = SP_BACKGROUND;
141c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        } else {
142c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat            errno = ERANGE;
143c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat            return -1;
144c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        }
145c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    } else {
146c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        int rc = sched_getscheduler(tid);
147c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        if (rc < 0)
148c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat            return -1;
149c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        else if (rc == SCHED_NORMAL)
150c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat            *policy = SP_FOREGROUND;
151c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        else if (rc == SCHED_BATCH)
152c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat            *policy = SP_BACKGROUND;
153c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        else {
154c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat            errno = ERANGE;
155c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat            return -1;
156c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat        }
157c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    }
158c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    return 0;
159c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat}
160c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat
161c0dfca7ae1f6016461235552091c2cacacca82a2San Mehatint set_sched_policy(int tid, SchedPolicy policy)
162c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat{
163c0dfca7ae1f6016461235552091c2cacacca82a2San Mehat    initialize();
164493dad966305a7fb555addd367532dd2af275a27San Mehat
165d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat#if POLICY_DEBUG
166d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat    char statfile[64];
167d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat    char statline[1024];
168d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat    char thread_name[255];
169d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat    int fd;
170d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat
171d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat    sprintf(statfile, "/proc/%d/stat", tid);
172d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat    memset(thread_name, 0, sizeof(thread_name));
173d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat
174d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat    fd = open(statfile, O_RDONLY);
175d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat    if (fd >= 0) {
176d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat        int rc = read(fd, statline, 1023);
177d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat        close(fd);
178d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat        statline[rc] = 0;
179d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat        char *p = statline;
180d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat        char *q;
181d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat
182d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat        for (p = statline; *p != '('; p++);
183d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat        p++;
184d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat        for (q = p; *q != ')'; q++);
185d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat
186d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat        strncpy(thread_name, p, (q-p));
187d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat    }
188d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat    if (policy == SP_BACKGROUND) {
189d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat        LOGD("vvv tid %d (%s)", tid, thread_name);
190d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat    } else if (policy == SP_FOREGROUND) {
191d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat        LOGD("^^^ tid %d (%s)", tid, thread_name);
192d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat    } else {
193d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat        LOGD("??? tid %d (%s)", tid, thread_name);
194d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat    }
195d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat#endif
196d2e4e46ce4bc29c3328fccfbbbe0590eaa8713f7San Mehat
197493dad966305a7fb555addd367532dd2af275a27San Mehat    if (__sys_supports_schedgroups) {
198805d67ab11c1bb21d494459d6167f5f67f0002ebSan Mehat        const char *grp = "";
199493dad966305a7fb555addd367532dd2af275a27San Mehat
200493dad966305a7fb555addd367532dd2af275a27San Mehat        if (policy == SP_BACKGROUND) {
201493dad966305a7fb555addd367532dd2af275a27San Mehat            grp = "bg_non_interactive";
202493dad966305a7fb555addd367532dd2af275a27San Mehat        }
203493dad966305a7fb555addd367532dd2af275a27San Mehat
204493dad966305a7fb555addd367532dd2af275a27San Mehat        if (add_tid_to_cgroup(tid, grp)) {
205493dad966305a7fb555addd367532dd2af275a27San Mehat            if (errno != ESRCH && errno != ENOENT)
206493dad966305a7fb555addd367532dd2af275a27San Mehat                return -errno;
207493dad966305a7fb555addd367532dd2af275a27San Mehat        }
208493dad966305a7fb555addd367532dd2af275a27San Mehat    } else {
209493dad966305a7fb555addd367532dd2af275a27San Mehat        struct sched_param param;
210493dad966305a7fb555addd367532dd2af275a27San Mehat
211493dad966305a7fb555addd367532dd2af275a27San Mehat        param.sched_priority = 0;
212493dad966305a7fb555addd367532dd2af275a27San Mehat        sched_setscheduler(tid,
213493dad966305a7fb555addd367532dd2af275a27San Mehat                           (policy == SP_BACKGROUND) ?
214493dad966305a7fb555addd367532dd2af275a27San Mehat                            SCHED_BATCH : SCHED_NORMAL,
215493dad966305a7fb555addd367532dd2af275a27San Mehat                           &param);
216493dad966305a7fb555addd367532dd2af275a27San Mehat    }
217493dad966305a7fb555addd367532dd2af275a27San Mehat
218493dad966305a7fb555addd367532dd2af275a27San Mehat    return 0;
219493dad966305a7fb555addd367532dd2af275a27San Mehat}
2200384a98d6f61fa47ffde01c15e552f738e88fb94Raphael
2210384a98d6f61fa47ffde01c15e552f738e88fb94Raphael#endif /* HAVE_SCHED_H */
222