sched_policy.c revision c0dfca7ae1f6016461235552091c2cacacca82a2
1 2/* libs/cutils/sched_policy.c 3** 4** Copyright 2007, The Android Open Source Project 5** 6** Licensed under the Apache License, Version 2.0 (the "License"); 7** you may not use this file except in compliance with the License. 8** You may obtain a copy of the License at 9** 10** http://www.apache.org/licenses/LICENSE-2.0 11** 12** Unless required by applicable law or agreed to in writing, software 13** distributed under the License is distributed on an "AS IS" BASIS, 14** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15** See the License for the specific language governing permissions and 16** limitations under the License. 17*/ 18 19#include <stdio.h> 20#include <stdlib.h> 21#include <unistd.h> 22#include <string.h> 23#include <errno.h> 24#include <fcntl.h> 25 26#ifdef HAVE_SCHED_H 27 28#include <sched.h> 29 30#include <cutils/sched_policy.h> 31 32#ifndef SCHED_NORMAL 33 #define SCHED_NORMAL 0 34#endif 35 36#ifndef SCHED_BATCH 37 #define SCHED_BATCH 3 38#endif 39 40static int __sys_supports_schedgroups = -1; 41 42static int add_tid_to_cgroup(int tid, const char *grp_name) 43{ 44 int fd; 45 char path[255]; 46 char text[64]; 47 48 sprintf(path, "/dev/cpuctl/%s/tasks", grp_name); 49 50 if ((fd = open(path, O_WRONLY)) < 0) 51 return -1; 52 53 sprintf(text, "%d", tid); 54 if (write(fd, text, strlen(text)) < 0) { 55 close(fd); 56 return -1; 57 } 58 59 close(fd); 60 return 0; 61} 62 63static inline void initialize() 64{ 65 if (__sys_supports_schedgroups < 0) { 66 if (!access("/dev/cpuctl/tasks", F_OK)) { 67 __sys_supports_schedgroups = 1; 68 } else { 69 __sys_supports_schedgroups = 0; 70 } 71 } 72} 73 74/* 75 * Try to get the scheduler group. 76 * 77 * The data from /proc/<pid>/cgroup looks like: 78 * 2:cpu:/bg_non_interactive 79 * 80 * We return the part after the "/", which will be an empty string for 81 * the default cgroup. If the string is longer than "bufLen", the string 82 * will be truncated. 83 */ 84static int getSchedulerGroup(int tid, char* buf, size_t bufLen) 85{ 86#ifdef HAVE_ANDROID_OS 87 char pathBuf[32]; 88 char readBuf[256]; 89 ssize_t count; 90 int fd; 91 92 snprintf(pathBuf, sizeof(pathBuf), "/proc/%d/cgroup", tid); 93 if ((fd = open(pathBuf, O_RDONLY)) < 0) { 94 return -1; 95 } 96 97 count = read(fd, readBuf, sizeof(readBuf)); 98 if (count <= 0) { 99 close(fd); 100 errno = ENODATA; 101 return -1; 102 } 103 close(fd); 104 105 readBuf[--count] = '\0'; /* remove the '\n', now count==strlen */ 106 107 char* cp = strchr(readBuf, '/'); 108 if (cp == NULL) { 109 readBuf[sizeof(readBuf)-1] = '\0'; 110 errno = ENODATA; 111 return -1; 112 } 113 114 memcpy(buf, cp+1, count); /* count-1 for cp+1, count+1 for NUL */ 115 return 0; 116#else 117 errno = ENOSYS; 118 return -1; 119#endif 120} 121 122int get_sched_policy(int tid, SchedPolicy *policy) 123{ 124 initialize(); 125 126 if (__sys_supports_schedgroups) { 127 char grpBuf[32]; 128 if (getSchedulerGroup(tid, grpBuf, sizeof(grpBuf)) < 0) 129 return -1; 130 if (grpBuf[0] == '\0') { 131 *policy = SP_FOREGROUND; 132 } else if (!strcmp(grpBuf, "bg_non_interactive")) { 133 *policy = SP_BACKGROUND; 134 } else { 135 errno = ERANGE; 136 return -1; 137 } 138 } else { 139 int rc = sched_getscheduler(tid); 140 if (rc < 0) 141 return -1; 142 else if (rc == SCHED_NORMAL) 143 *policy = SP_FOREGROUND; 144 else if (rc == SCHED_BATCH) 145 *policy = SP_BACKGROUND; 146 else { 147 errno = ERANGE; 148 return -1; 149 } 150 } 151 return 0; 152} 153 154int set_sched_policy(int tid, SchedPolicy policy) 155{ 156 initialize(); 157 158 if (__sys_supports_schedgroups) { 159 const char *grp = NULL; 160 161 if (policy == SP_BACKGROUND) { 162 grp = "bg_non_interactive"; 163 } 164 165 if (add_tid_to_cgroup(tid, grp)) { 166 if (errno != ESRCH && errno != ENOENT) 167 return -errno; 168 } 169 } else { 170 struct sched_param param; 171 172 param.sched_priority = 0; 173 sched_setscheduler(tid, 174 (policy == SP_BACKGROUND) ? 175 SCHED_BATCH : SCHED_NORMAL, 176 ¶m); 177 } 178 179 return 0; 180} 181 182#endif /* HAVE_SCHED_H */ 183