summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Tate <ctate@google.com>2009-12-03 15:24:36 -0800
committerChristopher Tate <ctate@google.com>2009-12-03 17:03:56 -0800
commit825bd26a95cb01c2a4d2e1d51492ab81dcecc373 (patch)
tree563723390f32c3360ff9e5737ccb3088b4a4dc52
parent46ef2b87d01a2df67074351d0078bf900550f343 (diff)
downloadcore-donut.tar.gz
DO NOT MERGE - backport Eclair utils for managing cgroupsdonut
-rw-r--r--include/arch/darwin-x86/AndroidConfig.h5
-rw-r--r--include/arch/linux-arm/AndroidConfig.h5
-rw-r--r--include/arch/linux-x86/AndroidConfig.h5
-rw-r--r--include/arch/target_linux-x86/AndroidConfig.h5
-rw-r--r--include/cutils/sched_policy.h36
-rw-r--r--libcutils/Android.mk3
-rw-r--r--libcutils/sched_policy.c229
-rw-r--r--toolbox/ps.c26
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,
+ &param);
+ }
+
+ 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);