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 @@
                            &param);
     }
 
-    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;
 }