aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/uapi/linux/prctl.h6
-rw-r--r--kernel/sys.c19
2 files changed, 25 insertions, 0 deletions
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index 80d4382cfe23..933ff2a9a032 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -179,6 +179,12 @@ struct prctl_mm_map {
#define PR_SET_THP_DISABLE 41
#define PR_GET_THP_DISABLE 42
+/* Sets the timerslack for arbitrary threads
+ * arg2 slack value, 0 means "use default"
+ * arg3 pid of the thread whose timer slack needs to be set
+ */
+#define PR_SET_TIMERSLACK_PID 43
+
#define PR_SET_VMA 0x53564d41
# define PR_SET_VMA_ANON_NAME 0
diff --git a/kernel/sys.c b/kernel/sys.c
index f2c175938243..787b19740b00 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -43,6 +43,7 @@
#include <linux/ctype.h>
#include <linux/mm.h>
#include <linux/mempolicy.h>
+#include <linux/sched.h>
#include <linux/compat.h>
#include <linux/syscalls.h>
@@ -2178,6 +2179,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
unsigned long, arg4, unsigned long, arg5)
{
struct task_struct *me = current;
+ struct task_struct *tsk;
unsigned char comm[sizeof(me->comm)];
long error;
@@ -2301,6 +2303,23 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
else
return -EINVAL;
break;
+ case PR_SET_TIMERSLACK_PID:
+ rcu_read_lock();
+ tsk = find_task_by_pid_ns((pid_t)arg3, &init_pid_ns);
+ if (tsk == NULL) {
+ rcu_read_unlock();
+ return -EINVAL;
+ }
+ get_task_struct(tsk);
+ rcu_read_unlock();
+ if (arg2 <= 0)
+ tsk->timer_slack_ns =
+ tsk->default_timer_slack_ns;
+ else
+ tsk->timer_slack_ns = arg2;
+ put_task_struct(tsk);
+ error = 0;
+ break;
default:
return -EINVAL;
}