2017-12-12 11:21:47

by Claudio Scordino

[permalink] [raw]
Subject: [PATCH v3] sched/deadline: runtime overrun signal

From: Juri Lelli <[email protected]>

This patch adds the possibility of getting the delivery of a SIGXCPU
signal whenever there is a runtime overrun. The request is done through
the sched_flags field within the sched_attr structure.

Forward port of https://lkml.org/lkml/2009/10/16/170

Signed-off-by: Juri Lelli <[email protected]>
Signed-off-by: Claudio Scordino <[email protected]>
Signed-off-by: Luca Abeni <[email protected]>
Tested-by: Mathieu Poirier <[email protected]>
Cc: Tommaso Cucinotta <[email protected]>
CC: Peter Zijlstra <[email protected]>
CC: Ingo Molnar <[email protected]>
CC: Thomas Gleixner <[email protected]>
CC: LKML <[email protected]>
CC: linux-rt-users <[email protected]>
---
Changes from v2:

- do not use a dubious signed bitfield for the dl_overrun flag

Changes from v1:

- fix: do not send the signal in case of yield (reported by Mathieu Poirier)
- removed the deadline miss signal because not needed in most of the cases
---
include/linux/sched.h | 4 ++++
include/uapi/linux/sched.h | 1 +
kernel/sched/core.c | 3 ++-
kernel/sched/deadline.c | 7 +++++++
kernel/time/posix-cpu-timers.c | 20 ++++++++++++++++++++
5 files changed, 34 insertions(+), 1 deletion(-)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index 21991d6..a62a2f1 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -472,11 +472,15 @@ struct sched_dl_entity {
* has not been executed yet. This flag is useful to avoid race
* conditions between the inactive timer handler and the wakeup
* code.
+ *
+ * @dl_overrun tells if the task asked to be informed about runtime
+ * overruns.
*/
unsigned int dl_throttled : 1;
unsigned int dl_boosted : 1;
unsigned int dl_yielded : 1;
unsigned int dl_non_contending : 1;
+ unsigned int dl_overrun : 1;

/*
* Bandwidth enforcement timer. Each -deadline task has its
diff --git a/include/uapi/linux/sched.h b/include/uapi/linux/sched.h
index 30a9e51..beb8ecd 100644
--- a/include/uapi/linux/sched.h
+++ b/include/uapi/linux/sched.h
@@ -49,5 +49,6 @@
*/
#define SCHED_FLAG_RESET_ON_FORK 0x01
#define SCHED_FLAG_RECLAIM 0x02
+#define SCHED_FLAG_DL_OVERRUN 0x04

#endif /* _UAPI_LINUX_SCHED_H */
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 75554f3..5bb67af 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -4041,7 +4041,8 @@ static int __sched_setscheduler(struct task_struct *p,
}

if (attr->sched_flags &
- ~(SCHED_FLAG_RESET_ON_FORK | SCHED_FLAG_RECLAIM))
+ ~(SCHED_FLAG_RESET_ON_FORK | SCHED_FLAG_RECLAIM |
+ SCHED_FLAG_DL_OVERRUN))
return -EINVAL;

/*
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 2473736..72554d1 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -1155,6 +1155,12 @@ static void update_curr_dl(struct rq *rq)
throttle:
if (dl_runtime_exceeded(dl_se) || dl_se->dl_yielded) {
dl_se->dl_throttled = 1;
+
+ /* If requested, inform the user about runtime overruns. */
+ if (dl_runtime_exceeded(dl_se) &&
+ (dl_se->flags & SCHED_FLAG_DL_OVERRUN))
+ dl_se->dl_overrun = 1;
+
__dequeue_task_dl(rq, curr, 0);
if (unlikely(dl_se->dl_boosted || !start_dl_timer(curr)))
enqueue_task_dl(rq, curr, ENQUEUE_REPLENISH);
@@ -2566,6 +2572,7 @@ void __dl_clear_params(struct task_struct *p)
dl_se->dl_throttled = 0;
dl_se->dl_yielded = 0;
dl_se->dl_non_contending = 0;
+ dl_se->dl_overrun = 0;
}

bool dl_param_changed(struct task_struct *p, const struct sched_attr *attr)
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 1f27887a..48281d9 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -14,6 +14,7 @@
#include <linux/tick.h>
#include <linux/workqueue.h>
#include <linux/compat.h>
+#include <linux/sched/deadline.h>

#include "posix-timers.h"

@@ -791,6 +792,16 @@ check_timers_list(struct list_head *timers,
return 0;
}

+static inline void check_dl_overrun(struct task_struct *tsk)
+{
+ if (tsk->dl.dl_overrun) {
+ tsk->dl.dl_overrun = 0;
+ pr_info("runtime overrun: %s[%d]\n",
+ tsk->comm, task_pid_nr(tsk));
+ __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
+ }
+}
+
/*
* Check for any per-thread CPU timers that have fired and move them off
* the tsk->cpu_timers[N] list onto the firing list. Here we update the
@@ -804,6 +815,9 @@ static void check_thread_timers(struct task_struct *tsk,
u64 expires;
unsigned long soft;

+ if (dl_task(tsk))
+ check_dl_overrun(tsk);
+
/*
* If cputime_expires is zero, then there are no active
* per thread CPU timers.
@@ -906,6 +920,9 @@ static void check_process_timers(struct task_struct *tsk,
struct task_cputime cputime;
unsigned long soft;

+ if (dl_task(tsk))
+ check_dl_overrun(tsk);
+
/*
* If cputimer is not running, then there are no active
* process wide timers (POSIX 1.b, itimers, RLIMIT_CPU).
@@ -1111,6 +1128,9 @@ static inline int fastpath_timer_check(struct task_struct *tsk)
return 1;
}

+ if (dl_task(tsk) && tsk->dl.dl_overrun)
+ return 1;
+
return 0;
}

--
2.7.4


2017-12-12 11:50:46

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH v3] sched/deadline: runtime overrun signal


* Claudio Scordino <[email protected]> wrote:

> From: Juri Lelli <[email protected]>

> - ~(SCHED_FLAG_RESET_ON_FORK | SCHED_FLAG_RECLAIM))
> + ~(SCHED_FLAG_RESET_ON_FORK | SCHED_FLAG_RECLAIM |
> + SCHED_FLAG_DL_OVERRUN))

> + if (dl_runtime_exceeded(dl_se) &&
> + (dl_se->flags & SCHED_FLAG_DL_OVERRUN))

> + pr_info("runtime overrun: %s[%d]\n",
> + tsk->comm, task_pid_nr(tsk));

Guys,
please,
don't,
break
code lines
in a hard to
read
fashion, ok,
just to
pacify
checkpatch.pl

ok? :-)

Also, I'm not sure that pr_info() debug printout should be in an upstream version,
correct?

Thanks,

Ingo

2017-12-19 19:32:45

by Peter Zijlstra

[permalink] [raw]
Subject: Re: [PATCH v3] sched/deadline: runtime overrun signal

On Tue, Dec 12, 2017 at 12:50:40PM +0100, Ingo Molnar wrote:
>
> * Claudio Scordino <[email protected]> wrote:
>
> > From: Juri Lelli <[email protected]>
>
> > - ~(SCHED_FLAG_RESET_ON_FORK | SCHED_FLAG_RECLAIM))
> > + ~(SCHED_FLAG_RESET_ON_FORK | SCHED_FLAG_RECLAIM |
> > + SCHED_FLAG_DL_OVERRUN))

Introduced SCHED_FLAG_ALL for this

>
> > + if (dl_runtime_exceeded(dl_se) &&
> > + (dl_se->flags & SCHED_FLAG_DL_OVERRUN))

realigned this one

>
> > + pr_info("runtime overrun: %s[%d]\n",
> > + tsk->comm, task_pid_nr(tsk));

And simply took this out, you asked for it, no reason to tell world
about getting one.

Subject: [tip:sched/core] sched/deadline: Implement "runtime overrun signal" support

Commit-ID: 34be39305a77b8b1ec9f279163c7cdb6cc719b91
Gitweb: https://git.kernel.org/tip/34be39305a77b8b1ec9f279163c7cdb6cc719b91
Author: Juri Lelli <[email protected]>
AuthorDate: Tue, 12 Dec 2017 12:10:24 +0100
Committer: Ingo Molnar <[email protected]>
CommitDate: Wed, 10 Jan 2018 11:30:31 +0100

sched/deadline: Implement "runtime overrun signal" support

This patch adds the possibility of getting the delivery of a SIGXCPU
signal whenever there is a runtime overrun. The request is done through
the sched_flags field within the sched_attr structure.

Forward port of https://lkml.org/lkml/2009/10/16/170

Tested-by: Mathieu Poirier <[email protected]>
Signed-off-by: Juri Lelli <[email protected]>
Signed-off-by: Claudio Scordino <[email protected]>
Signed-off-by: Luca Abeni <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Cc: Tommaso Cucinotta <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
---
include/linux/sched.h | 4 ++++
include/uapi/linux/sched.h | 5 +++++
kernel/sched/core.c | 3 +--
kernel/sched/deadline.c | 7 +++++++
kernel/time/posix-cpu-timers.c | 18 ++++++++++++++++++
5 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/include/linux/sched.h b/include/linux/sched.h
index d258826..274a449 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -472,11 +472,15 @@ struct sched_dl_entity {
* has not been executed yet. This flag is useful to avoid race
* conditions between the inactive timer handler and the wakeup
* code.
+ *
+ * @dl_overrun tells if the task asked to be informed about runtime
+ * overruns.
*/
unsigned int dl_throttled : 1;
unsigned int dl_boosted : 1;
unsigned int dl_yielded : 1;
unsigned int dl_non_contending : 1;
+ unsigned int dl_overrun : 1;

/*
* Bandwidth enforcement timer. Each -deadline task has its
diff --git a/include/uapi/linux/sched.h b/include/uapi/linux/sched.h
index 30a9e51..22627f8 100644
--- a/include/uapi/linux/sched.h
+++ b/include/uapi/linux/sched.h
@@ -49,5 +49,10 @@
*/
#define SCHED_FLAG_RESET_ON_FORK 0x01
#define SCHED_FLAG_RECLAIM 0x02
+#define SCHED_FLAG_DL_OVERRUN 0x04
+
+#define SCHED_FLAG_ALL (SCHED_FLAG_RESET_ON_FORK | \
+ SCHED_FLAG_RECLAIM | \
+ SCHED_FLAG_DL_OVERRUN)

#endif /* _UAPI_LINUX_SCHED_H */
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index a794f81..e28391b 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -4085,8 +4085,7 @@ recheck:
return -EINVAL;
}

- if (attr->sched_flags &
- ~(SCHED_FLAG_RESET_ON_FORK | SCHED_FLAG_RECLAIM))
+ if (attr->sched_flags & ~SCHED_FLAG_ALL)
return -EINVAL;

/*
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index 2473736..4c666db 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -1155,6 +1155,12 @@ static void update_curr_dl(struct rq *rq)
throttle:
if (dl_runtime_exceeded(dl_se) || dl_se->dl_yielded) {
dl_se->dl_throttled = 1;
+
+ /* If requested, inform the user about runtime overruns. */
+ if (dl_runtime_exceeded(dl_se) &&
+ (dl_se->flags & SCHED_FLAG_DL_OVERRUN))
+ dl_se->dl_overrun = 1;
+
__dequeue_task_dl(rq, curr, 0);
if (unlikely(dl_se->dl_boosted || !start_dl_timer(curr)))
enqueue_task_dl(rq, curr, ENQUEUE_REPLENISH);
@@ -2566,6 +2572,7 @@ void __dl_clear_params(struct task_struct *p)
dl_se->dl_throttled = 0;
dl_se->dl_yielded = 0;
dl_se->dl_non_contending = 0;
+ dl_se->dl_overrun = 0;
}

bool dl_param_changed(struct task_struct *p, const struct sched_attr *attr)
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 1f27887a..cf50ea3 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -14,6 +14,7 @@
#include <linux/tick.h>
#include <linux/workqueue.h>
#include <linux/compat.h>
+#include <linux/sched/deadline.h>

#include "posix-timers.h"

@@ -791,6 +792,14 @@ check_timers_list(struct list_head *timers,
return 0;
}

+static inline void check_dl_overrun(struct task_struct *tsk)
+{
+ if (tsk->dl.dl_overrun) {
+ tsk->dl.dl_overrun = 0;
+ __group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
+ }
+}
+
/*
* Check for any per-thread CPU timers that have fired and move them off
* the tsk->cpu_timers[N] list onto the firing list. Here we update the
@@ -804,6 +813,9 @@ static void check_thread_timers(struct task_struct *tsk,
u64 expires;
unsigned long soft;

+ if (dl_task(tsk))
+ check_dl_overrun(tsk);
+
/*
* If cputime_expires is zero, then there are no active
* per thread CPU timers.
@@ -906,6 +918,9 @@ static void check_process_timers(struct task_struct *tsk,
struct task_cputime cputime;
unsigned long soft;

+ if (dl_task(tsk))
+ check_dl_overrun(tsk);
+
/*
* If cputimer is not running, then there are no active
* process wide timers (POSIX 1.b, itimers, RLIMIT_CPU).
@@ -1111,6 +1126,9 @@ static inline int fastpath_timer_check(struct task_struct *tsk)
return 1;
}

+ if (dl_task(tsk) && tsk->dl.dl_overrun)
+ return 1;
+
return 0;
}