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 ¶m); 216493dad966305a7fb555addd367532dd2af275a27San Mehat } 217493dad966305a7fb555addd367532dd2af275a27San Mehat 218493dad966305a7fb555addd367532dd2af275a27San Mehat return 0; 219493dad966305a7fb555addd367532dd2af275a27San Mehat} 2200384a98d6f61fa47ffde01c15e552f738e88fb94Raphael 2210384a98d6f61fa47ffde01c15e552f738e88fb94Raphael#endif /* HAVE_SCHED_H */ 222