sched_policy: Add support for /proc/<tid>/timerslack_ns over PR_SET_TIMERSLACK_PID
The PR_SET_TIMERSLACK_PID number has collided with upstream
changes a number of times, and thus the number is not consistent
between AOSP common kernel versions.
In 4.6+, the upstream kernel added equivalent functionaity via
the /proc/<tid>/timerslack_ns entry.
This patch changes the sched_policy logic to support
/proc/<tid>/timerslack_ns if its available, falling back to the
older PR_SET_TIMERSLACK_PID method if not.
NOTE: Eventually PR_SET_TIMERSLACK_PID usage will need to be
removed as it is likely to conflict with valid future upstream
PR_* entries.
Also add missing O_CLOEXEC to other open calls in this file.
Change-Id: Iec0b8a62de0dc8bdd57b60df82bd4d31c5d64709
Signed-off-by: John Stultz <john.stultz@linaro.org>
diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c
index 7bb8223..d7b4b0b 100644
--- a/libcutils/sched_policy.c
+++ b/libcutils/sched_policy.c
@@ -160,7 +160,7 @@
FILE *fp;
snprintf(pathBuf, sizeof(pathBuf), "/proc/%d/cgroup", tid);
- if (!(fp = fopen(pathBuf, "r"))) {
+ if (!(fp = fopen(pathBuf, "re"))) {
return -1;
}
@@ -292,6 +292,27 @@
#endif
}
+static void set_timerslack_ns(int tid, unsigned long long slack) {
+ char buf[64];
+
+ /* v4.6+ kernels support the /proc/<tid>/timerslack_ns interface. */
+ snprintf(buf, sizeof(buf), "/proc/%d/timerslack_ns", tid);
+ int fd = open(buf, O_WRONLY | O_CLOEXEC);
+ if (fd != -1) {
+ int len = snprintf(buf, sizeof(buf), "%llu", slack);
+ if (write(fd, buf, len) != len) {
+ SLOGE("set_timerslack_ns write failed: %s\n", strerror(errno));
+ }
+ close(fd);
+ return;
+ }
+
+ /* If the above fails, try the old common.git PR_SET_TIMERSLACK_PID. */
+ if (prctl(PR_SET_TIMERSLACK_PID, slack, tid) == -1) {
+ SLOGE("set_timerslack_ns prctl failed: %s\n", strerror(errno));
+ }
+}
+
int set_sched_policy(int tid, SchedPolicy policy)
{
if (tid == 0) {
@@ -304,12 +325,11 @@
char statfile[64];
char statline[1024];
char thread_name[255];
- int fd;
snprintf(statfile, sizeof(statfile), "/proc/%d/stat", tid);
memset(thread_name, 0, sizeof(thread_name));
- fd = open(statfile, O_RDONLY);
+ int fd = open(statfile, O_RDONLY | O_CLOEXEC);
if (fd >= 0) {
int rc = read(fd, statline, 1023);
close(fd);
@@ -372,8 +392,8 @@
¶m);
}
- prctl(PR_SET_TIMERSLACK_PID,
- policy == SP_BACKGROUND ? TIMER_SLACK_BG : TIMER_SLACK_FG, tid);
+ set_timerslack_ns(tid, policy == SP_BACKGROUND ?
+ TIMER_SLACK_BG : TIMER_SLACK_FG);
return 0;
}