diff options
author | Christopher Tate <ctate@google.com> | 2009-12-03 15:24:36 -0800 |
---|---|---|
committer | Christopher Tate <ctate@google.com> | 2009-12-03 17:03:56 -0800 |
commit | 825bd26a95cb01c2a4d2e1d51492ab81dcecc373 (patch) | |
tree | 563723390f32c3360ff9e5737ccb3088b4a4dc52 | |
parent | 46ef2b87d01a2df67074351d0078bf900550f343 (diff) | |
download | core-donut.tar.gz |
DO NOT MERGE - backport Eclair utils for managing cgroupsdonut
-rw-r--r-- | include/arch/darwin-x86/AndroidConfig.h | 5 | ||||
-rw-r--r-- | include/arch/linux-arm/AndroidConfig.h | 5 | ||||
-rw-r--r-- | include/arch/linux-x86/AndroidConfig.h | 5 | ||||
-rw-r--r-- | include/arch/target_linux-x86/AndroidConfig.h | 5 | ||||
-rw-r--r-- | include/cutils/sched_policy.h | 36 | ||||
-rw-r--r-- | libcutils/Android.mk | 3 | ||||
-rw-r--r-- | libcutils/sched_policy.c | 229 | ||||
-rw-r--r-- | toolbox/ps.c | 26 |
8 files changed, 310 insertions, 4 deletions
diff --git a/include/arch/darwin-x86/AndroidConfig.h b/include/arch/darwin-x86/AndroidConfig.h index 49f04e514..f7493051b 100644 --- a/include/arch/darwin-x86/AndroidConfig.h +++ b/include/arch/darwin-x86/AndroidConfig.h @@ -257,4 +257,9 @@ */ #define HAVE_WRITEV 1 +/* + * Define if <sched.h> exists. + */ +#define HAVE_SCHED_H 1 + #endif /*_ANDROID_CONFIG_H*/ diff --git a/include/arch/linux-arm/AndroidConfig.h b/include/arch/linux-arm/AndroidConfig.h index f32212749..72c13747f 100644 --- a/include/arch/linux-arm/AndroidConfig.h +++ b/include/arch/linux-arm/AndroidConfig.h @@ -302,4 +302,9 @@ */ #define HAVE_WRITEV 1 +/* + * Define if <sched.h> exists. + */ +#define HAVE_SCHED_H 1 + #endif /* _ANDROID_CONFIG_H */ diff --git a/include/arch/linux-x86/AndroidConfig.h b/include/arch/linux-x86/AndroidConfig.h index 6de75f8d1..c6d33c896 100644 --- a/include/arch/linux-x86/AndroidConfig.h +++ b/include/arch/linux-x86/AndroidConfig.h @@ -283,4 +283,9 @@ */ #define HAVE_WRITEV 1 +/* + * Define if <sched.h> exists. + */ +#define HAVE_SCHED_H 1 + #endif /*_ANDROID_CONFIG_H*/ diff --git a/include/arch/target_linux-x86/AndroidConfig.h b/include/arch/target_linux-x86/AndroidConfig.h index 4aa44f883..1d14ef2cd 100644 --- a/include/arch/target_linux-x86/AndroidConfig.h +++ b/include/arch/target_linux-x86/AndroidConfig.h @@ -293,4 +293,9 @@ */ #define HAVE_UNWIND_CONTEXT_STRUCT +/* + * Define if <sched.h> exists. + */ +#define HAVE_SCHED_H 1 + #endif /* _ANDROID_CONFIG_H */ diff --git a/include/cutils/sched_policy.h b/include/cutils/sched_policy.h new file mode 100644 index 000000000..eaf39939a --- /dev/null +++ b/include/cutils/sched_policy.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __CUTILS_SCHED_POLICY_H +#define __CUTILS_SCHED_POLICY_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + SP_BACKGROUND = 0, + SP_FOREGROUND = 1, +} SchedPolicy; + +extern int set_sched_policy(int tid, SchedPolicy policy); +extern int get_sched_policy(int tid, SchedPolicy *policy); + +#ifdef __cplusplus +} +#endif + +#endif /* __CUTILS_SCHED_POLICY_H */ diff --git a/libcutils/Android.mk b/libcutils/Android.mk index 18d0ee318..38a20931a 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -36,7 +36,8 @@ commonSources := \ record_stream.c \ process_name.c \ properties.c \ - threads.c + threads.c \ + sched_policy.c # some files must not be compiled when building against Mingw # they correspond to features not used by our host development tools diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c new file mode 100644 index 000000000..77b174b9c --- /dev/null +++ b/libcutils/sched_policy.c @@ -0,0 +1,229 @@ + +/* libs/cutils/sched_policy.c +** +** Copyright 2009, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> + +#define LOG_TAG "SchedPolicy" +#include "cutils/log.h" + +#ifdef HAVE_SCHED_H + +#include <sched.h> + +#include <cutils/sched_policy.h> + +#ifndef SCHED_NORMAL + #define SCHED_NORMAL 0 +#endif + +#ifndef SCHED_BATCH + #define SCHED_BATCH 3 +#endif + +#define POLICY_DEBUG 0 + +static int __sys_supports_schedgroups = -1; + +static int add_tid_to_cgroup(int tid, const char *grp_name) +{ + int fd; + char path[255]; + char text[64]; + + sprintf(path, "/dev/cpuctl/%s/tasks", grp_name); + + if ((fd = open(path, O_WRONLY)) < 0) { + LOGE("add_tid_to_cgroup failed to open '%s' (%s)\n", path, strerror(errno)); + return -1; + } + + sprintf(text, "%d", tid); + if (write(fd, text, strlen(text)) < 0) { + close(fd); + /* + * If the thread is in the process of exiting, + * don't flag an error + */ + if (errno == ESRCH) + return 0; + LOGW("add_tid_to_cgroup failed to write '%s' (%s)\n", path, + strerror(errno)); + return -1; + } + + close(fd); + return 0; +} + +static inline void initialize() +{ + if (__sys_supports_schedgroups < 0) { + if (!access("/dev/cpuctl/tasks", F_OK)) { + __sys_supports_schedgroups = 1; + } else { + __sys_supports_schedgroups = 0; + } + } +} + +/* + * Try to get the scheduler group. + * + * The data from /proc/<pid>/cgroup looks like: + * 2:cpu:/bg_non_interactive + * + * We return the part after the "/", which will be an empty string for + * the default cgroup. If the string is longer than "bufLen", the string + * will be truncated. + */ +static int getSchedulerGroup(int tid, char* buf, size_t bufLen) +{ +#ifdef HAVE_ANDROID_OS + char pathBuf[32]; + char readBuf[256]; + ssize_t count; + int fd; + + snprintf(pathBuf, sizeof(pathBuf), "/proc/%d/cgroup", tid); + if ((fd = open(pathBuf, O_RDONLY)) < 0) { + return -1; + } + + count = read(fd, readBuf, sizeof(readBuf)); + if (count <= 0) { + close(fd); + errno = ENODATA; + return -1; + } + close(fd); + + readBuf[--count] = '\0'; /* remove the '\n', now count==strlen */ + + char* cp = strchr(readBuf, '/'); + if (cp == NULL) { + readBuf[sizeof(readBuf)-1] = '\0'; + errno = ENODATA; + return -1; + } + + memcpy(buf, cp+1, count); /* count-1 for cp+1, count+1 for NUL */ + return 0; +#else + errno = ENOSYS; + return -1; +#endif +} + +int get_sched_policy(int tid, SchedPolicy *policy) +{ + initialize(); + + if (__sys_supports_schedgroups) { + char grpBuf[32]; + if (getSchedulerGroup(tid, grpBuf, sizeof(grpBuf)) < 0) + return -1; + if (grpBuf[0] == '\0') { + *policy = SP_FOREGROUND; + } else if (!strcmp(grpBuf, "bg_non_interactive")) { + *policy = SP_BACKGROUND; + } else { + errno = ERANGE; + return -1; + } + } else { + int rc = sched_getscheduler(tid); + if (rc < 0) + return -1; + else if (rc == SCHED_NORMAL) + *policy = SP_FOREGROUND; + else if (rc == SCHED_BATCH) + *policy = SP_BACKGROUND; + else { + errno = ERANGE; + return -1; + } + } + return 0; +} + +int set_sched_policy(int tid, SchedPolicy policy) +{ + initialize(); + +#if POLICY_DEBUG + char statfile[64]; + char statline[1024]; + char thread_name[255]; + int fd; + + sprintf(statfile, "/proc/%d/stat", tid); + memset(thread_name, 0, sizeof(thread_name)); + + fd = open(statfile, O_RDONLY); + if (fd >= 0) { + int rc = read(fd, statline, 1023); + close(fd); + statline[rc] = 0; + char *p = statline; + char *q; + + for (p = statline; *p != '('; p++); + p++; + for (q = p; *q != ')'; q++); + + strncpy(thread_name, p, (q-p)); + } + if (policy == SP_BACKGROUND) { + LOGD("vvv tid %d (%s)", tid, thread_name); + } else if (policy == SP_FOREGROUND) { + LOGD("^^^ tid %d (%s)", tid, thread_name); + } else { + LOGD("??? tid %d (%s)", tid, thread_name); + } +#endif + + if (__sys_supports_schedgroups) { + const char *grp = ""; + + if (policy == SP_BACKGROUND) { + grp = "bg_non_interactive"; + } + + if (add_tid_to_cgroup(tid, grp)) { + if (errno != ESRCH && errno != ENOENT) + return -errno; + } + } else { + struct sched_param param; + + param.sched_priority = 0; + sched_setscheduler(tid, + (policy == SP_BACKGROUND) ? + SCHED_BATCH : SCHED_NORMAL, + ¶m); + } + + return 0; +} + +#endif /* HAVE_SCHED_H */ diff --git a/toolbox/ps.c b/toolbox/ps.c index 3b86fa252..bc50cfa97 100644 --- a/toolbox/ps.c +++ b/toolbox/ps.c @@ -11,6 +11,8 @@ #include <pwd.h> +#include <cutils/sched_policy.h> + static char *nexttoksep(char **strp, char *sep) { @@ -24,6 +26,7 @@ static char *nexttok(char **strp) #define SHOW_PRIO 1 #define SHOW_TIME 2 +#define SHOW_POLICY 4 static int display_flags = 0; @@ -138,12 +141,26 @@ static int ps_line(int pid, int tid, char *namefilter) } if(!namefilter || !strncmp(name, namefilter, strlen(namefilter))) { - printf("%-8s %-5d %-5d %-5d %-5d", user, pid, ppid, vss / 1024, rss * 4); + printf("%-9s %-5d %-5d %-6d %-5d", user, pid, ppid, vss / 1024, rss * 4); if(display_flags&SHOW_PRIO) printf(" %-5d %-5d %-5d %-5d", prio, nice, rtprio, sched); + if (display_flags & SHOW_POLICY) { + SchedPolicy p; + if (get_sched_policy(pid, &p) < 0) + printf(" un "); + else { + if (p == SP_BACKGROUND) + printf(" bg "); + else if (p == SP_FOREGROUND) + printf(" fg "); + else + printf(" er "); + } + } printf(" %08x %08x %s %s", wchan, eip, state, cmdline[0] ? cmdline : name); if(display_flags&SHOW_TIME) printf(" (u:%d, s:%d)", utime, stime); + printf("\n"); } return 0; @@ -186,6 +203,8 @@ int ps_main(int argc, char **argv) threads = 1; } else if(!strcmp(argv[1],"-x")) { display_flags |= SHOW_TIME; + } else if(!strcmp(argv[1],"-P")) { + display_flags |= SHOW_POLICY; } else if(!strcmp(argv[1],"-p")) { display_flags |= SHOW_PRIO; } else if(isdigit(argv[1][0])){ @@ -197,8 +216,9 @@ int ps_main(int argc, char **argv) argv++; } - printf("USER PID PPID VSIZE RSS %sWCHAN PC NAME\n", - (display_flags&SHOW_PRIO)?"PRIO NICE RTPRI SCHED ":""); + printf("USER PID PPID VSIZE RSS %s %s WCHAN PC NAME\n", + (display_flags&SHOW_PRIO)?"PRIO NICE RTPRI SCHED ":"", + (display_flags&SHOW_POLICY)?"PCY " : ""); while((de = readdir(d)) != 0){ if(isdigit(de->d_name[0])){ int pid = atoi(de->d_name); |