linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation
@ 2019-08-21 19:08 Thomas Gleixner
  2019-08-21 19:08 ` [patch V2 01/38] posix-cpu-timers: Provide task validation functions Thomas Gleixner
                   ` (38 more replies)
  0 siblings, 39 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:08 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Folks!

This is the second version of that set. First one can be found here:

  https://lkml.kernel.org/r/20190819143141.221906747@linutronix.de

The following changes vs. V1:

  - Folded the synchronization callback patch into the original one and
    replaced the original one in tip timers/core as requested by Christoph

  - Merged the first couple of trivial patches into tip timers/core with
    Frederics reviewed-by picked up.

  - Dropped the sighand locking change as pointed out by Frederic

  - Dropped the last patch which switches to direct expiry mode as it got
    too ugly as the sighand locking change needed to be dropped. This will
    come with the next set on top of this which moves the expiry into task
    work context which was the initial reason for staring at this code.

  - Reworked the storage array after the patch which removes the temporary
    union and the abused struct task_cputime as requested by Ingo.

  - Fixed up a comment and the ugly hack in do_rlimit() which was needed to
    convert 0 expiry time to 1 which was required due to the 0 based checks
    which are now gone. (New)

  - Fixed typos in comments and changelogs (Ingo)

The series applies on top of:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core

and is available from git as well:

   git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git WIP.timers/core

Thanks,

	tglx

8<--------------
 include/linux/init_task.h      |   11 
 include/linux/posix-timers.h   |  121 ++++-
 include/linux/sched.h          |   29 -
 include/linux/sched/cputime.h  |   12 
 include/linux/sched/signal.h   |   14 
 include/linux/sched/types.h    |   23 
 include/linux/timerqueue.h     |   10 
 init/init_task.c               |    2 
 kernel/fork.c                  |   34 -
 kernel/sched/rt.c              |    6 
 kernel/sys.c                   |   16 
 kernel/time/itimer.c           |   11 
 kernel/time/posix-cpu-timers.c |  952 +++++++++++++++++++----------------------
 13 files changed, 616 insertions(+), 625 deletions(-)




^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 01/38] posix-cpu-timers: Provide task validation functions
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
@ 2019-08-21 19:08 ` Thomas Gleixner
  2019-08-21 22:33   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:08 ` [patch V2 02/38] posix-cpu-timers: Use common permission check in posix_cpu_clock_get() Thomas Gleixner
                   ` (37 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:08 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

The code contains three slightly different copies of validating whether a
given clock resolves to a valid task and whether the current caller has
permissions to access it.

Create central functions. Replace check_clock() as a first step and rename
it to something sensible.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |   65 +++++++++++++++++++++++++++--------------
 1 file changed, 44 insertions(+), 21 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -35,27 +35,52 @@ void update_rlimit_cpu(struct task_struc
 	spin_unlock_irq(&task->sighand->siglock);
 }
 
-static int check_clock(const clockid_t which_clock)
+/*
+ * Functions for validating access to tasks.
+ */
+static struct task_struct *lookup_task(const pid_t pid, bool thread)
 {
-	int error = 0;
 	struct task_struct *p;
-	const pid_t pid = CPUCLOCK_PID(which_clock);
 
-	if (CPUCLOCK_WHICH(which_clock) >= CPUCLOCK_MAX)
-		return -EINVAL;
+	if (!pid)
+		return thread ? current : current->group_leader;
 
-	if (pid == 0)
-		return 0;
+	p = find_task_by_vpid(pid);
+	if (!p || p == current)
+		return p;
+	if (thread)
+		return same_thread_group(p, current) ? p : NULL;
+	if (p == current)
+		return p;
+	return has_group_leader_pid(p) ? p : NULL;
+}
+
+static struct task_struct *__get_task_for_clock(const clockid_t clock,
+						bool getref)
+{
+	const bool thread = !!CPUCLOCK_PERTHREAD(clock);
+	const pid_t pid = CPUCLOCK_PID(clock);
+	struct task_struct *p;
+
+	if (CPUCLOCK_WHICH(clock) >= CPUCLOCK_MAX)
+		return NULL;
 
 	rcu_read_lock();
-	p = find_task_by_vpid(pid);
-	if (!p || !(CPUCLOCK_PERTHREAD(which_clock) ?
-		   same_thread_group(p, current) : has_group_leader_pid(p))) {
-		error = -EINVAL;
-	}
+	p = lookup_task(pid, thread);
+	if (p && getref)
+		get_task_struct(p);
 	rcu_read_unlock();
+	return p;
+}
 
-	return error;
+static inline struct task_struct *get_task_for_clock(const clockid_t clock)
+{
+	return __get_task_for_clock(clock, true);
+}
+
+static inline int validate_clock_permissions(const clockid_t clock)
+{
+	return __get_task_for_clock(clock, false) ? 0 : -EINVAL;
 }
 
 /*
@@ -125,7 +150,8 @@ static inline u64 virt_ticks(struct task
 static int
 posix_cpu_clock_getres(const clockid_t which_clock, struct timespec64 *tp)
 {
-	int error = check_clock(which_clock);
+	int error = validate_clock_permissions(which_clock);
+
 	if (!error) {
 		tp->tv_sec = 0;
 		tp->tv_nsec = ((NSEC_PER_SEC + HZ - 1) / HZ);
@@ -142,20 +168,17 @@ posix_cpu_clock_getres(const clockid_t w
 }
 
 static int
-posix_cpu_clock_set(const clockid_t which_clock, const struct timespec64 *tp)
+posix_cpu_clock_set(const clockid_t clock, const struct timespec64 *tp)
 {
+	int error = validate_clock_permissions(clock);
+
 	/*
 	 * You can never reset a CPU clock, but we check for other errors
 	 * in the call before failing with EPERM.
 	 */
-	int error = check_clock(which_clock);
-	if (error == 0) {
-		error = -EPERM;
-	}
-	return error;
+	return error ? : -EPERM;
 }
 
-
 /*
  * Sample a per-thread clock for the given task.
  */



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 02/38] posix-cpu-timers: Use common permission check in posix_cpu_clock_get()
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
  2019-08-21 19:08 ` [patch V2 01/38] posix-cpu-timers: Provide task validation functions Thomas Gleixner
@ 2019-08-21 19:08 ` Thomas Gleixner
  2019-08-21 23:40   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:08 ` [patch V2 03/38] posix-cpu-timers: Use common permission check in posix_cpu_timer_create() Thomas Gleixner
                   ` (36 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:08 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Replace the next slightly different copy of permission checks. That also
removes the necessarity to check the return value of the sample functions
because the clock id is already validated.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |   61 ++++++++++-------------------------------
 1 file changed, 16 insertions(+), 45 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -289,53 +289,24 @@ static int cpu_clock_sample_group(const
 	return 0;
 }
 
-static int posix_cpu_clock_get_task(struct task_struct *tsk,
-				    const clockid_t which_clock,
-				    struct timespec64 *tp)
+static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)
 {
-	int err = -EINVAL;
-	u64 rtn;
+	const clockid_t clkid = CPUCLOCK_WHICH(clock);
+	struct task_struct *tsk;
+	u64 t;
+
+	tsk = get_task_for_clock(clock);
+	if (!tsk)
+		return -EINVAL;
+
+	if (CPUCLOCK_PERTHREAD(clock))
+		cpu_clock_sample(clkid, tsk, &t);
+	else
+		cpu_clock_sample_group(clkid, tsk, &t);
+	put_task_struct(tsk);
 
-	if (CPUCLOCK_PERTHREAD(which_clock)) {
-		if (same_thread_group(tsk, current))
-			err = cpu_clock_sample(which_clock, tsk, &rtn);
-	} else {
-		if (tsk == current || thread_group_leader(tsk))
-			err = cpu_clock_sample_group(which_clock, tsk, &rtn);
-	}
-
-	if (!err)
-		*tp = ns_to_timespec64(rtn);
-
-	return err;
-}
-
-
-static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec64 *tp)
-{
-	const pid_t pid = CPUCLOCK_PID(which_clock);
-	int err = -EINVAL;
-
-	if (pid == 0) {
-		/*
-		 * Special case constant value for our own clocks.
-		 * We don't have to do any lookup to find ourselves.
-		 */
-		err = posix_cpu_clock_get_task(current, which_clock, tp);
-	} else {
-		/*
-		 * Find the given PID, and validate that the caller
-		 * should be able to see it.
-		 */
-		struct task_struct *p;
-		rcu_read_lock();
-		p = find_task_by_vpid(pid);
-		if (p)
-			err = posix_cpu_clock_get_task(p, which_clock, tp);
-		rcu_read_unlock();
-	}
-
-	return err;
+	*tp = ns_to_timespec64(t);
+	return 0;
 }
 
 /*



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 03/38] posix-cpu-timers: Use common permission check in posix_cpu_timer_create()
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
  2019-08-21 19:08 ` [patch V2 01/38] posix-cpu-timers: Provide task validation functions Thomas Gleixner
  2019-08-21 19:08 ` [patch V2 02/38] posix-cpu-timers: Use common permission check in posix_cpu_clock_get() Thomas Gleixner
@ 2019-08-21 19:08 ` Thomas Gleixner
  2019-08-21 23:49   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:08 ` [patch V2 04/38] posix-cpu-timers: Provide quick sample function for itimer Thomas Gleixner
                   ` (35 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:08 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Yet another copy of the same thing gone...

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |   35 +++--------------------------------
 1 file changed, 3 insertions(+), 32 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -316,44 +316,15 @@ static int posix_cpu_clock_get(const clo
  */
 static int posix_cpu_timer_create(struct k_itimer *new_timer)
 {
-	int ret = 0;
-	const pid_t pid = CPUCLOCK_PID(new_timer->it_clock);
-	struct task_struct *p;
+	struct task_struct *p = get_task_for_clock(new_timer->it_clock);
 
-	if (CPUCLOCK_WHICH(new_timer->it_clock) >= CPUCLOCK_MAX)
+	if (!p)
 		return -EINVAL;
 
 	new_timer->kclock = &clock_posix_cpu;
-
 	INIT_LIST_HEAD(&new_timer->it.cpu.entry);
-
-	rcu_read_lock();
-	if (CPUCLOCK_PERTHREAD(new_timer->it_clock)) {
-		if (pid == 0) {
-			p = current;
-		} else {
-			p = find_task_by_vpid(pid);
-			if (p && !same_thread_group(p, current))
-				p = NULL;
-		}
-	} else {
-		if (pid == 0) {
-			p = current->group_leader;
-		} else {
-			p = find_task_by_vpid(pid);
-			if (p && !has_group_leader_pid(p))
-				p = NULL;
-		}
-	}
 	new_timer->it.cpu.task = p;
-	if (p) {
-		get_task_struct(p);
-	} else {
-		ret = -EINVAL;
-	}
-	rcu_read_unlock();
-
-	return ret;
+	return 0;
 }
 
 /*



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 04/38] posix-cpu-timers: Provide quick sample function for itimer
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (2 preceding siblings ...)
  2019-08-21 19:08 ` [patch V2 03/38] posix-cpu-timers: Use common permission check in posix_cpu_timer_create() Thomas Gleixner
@ 2019-08-21 19:08 ` Thomas Gleixner
  2019-08-22 12:13   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:08 ` [patch V2 05/38] itimers: Use quick sample function Thomas Gleixner
                   ` (34 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:08 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

get_itimer() needs a sample of the current thread group cputime. It invokes
thread_group_cputimer() - which is a misnomer. That function also starts
eventually the group cputime accouting which is bogus because the
accounting is already active when a timer is armed.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/sched/cputime.h  |    2 +-
 kernel/time/posix-cpu-timers.c |   21 +++++++++++++++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)

--- a/include/linux/sched/cputime.h
+++ b/include/linux/sched/cputime.h
@@ -62,7 +62,7 @@ extern void cputime_adjust(struct task_c
  */
 void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times);
 void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times);
-
+void thread_group_sample_cputime(struct task_struct *tsk, struct task_cputime *times);
 
 /*
  * The following are functions that support scheduler-internal time accounting.
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -232,6 +232,27 @@ static inline void sample_cputime_atomic
 	times->sum_exec_runtime = atomic64_read(&atomic_times->sum_exec_runtime);
 }
 
+/**
+ * thread_group_sample_cputime - Sample cputime for a given task
+ * @tsk:	Task for which cputime needs to be started
+ * @iimes:	Storage for time samples
+ *
+ * Called from sys_getitimer() to calculate the expiry time of an active
+ * timer. That means group cputime accounting is already active. Called
+ * with task sighand lock held.
+ *
+ * Updates @times with an uptodate sample of the thread group cputimes.
+ */
+void thread_group_sample_cputime(struct task_struct *tsk,
+				struct task_cputime *times)
+{
+	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
+
+	WARN_ON_ONCE(!cputimer->running);
+
+	sample_cputime_atomic(times, &cputimer->cputime_atomic);
+}
+
 void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
 {
 	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 05/38] itimers: Use quick sample function
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (3 preceding siblings ...)
  2019-08-21 19:08 ` [patch V2 04/38] posix-cpu-timers: Provide quick sample function for itimer Thomas Gleixner
@ 2019-08-21 19:08 ` Thomas Gleixner
  2019-08-22 12:15   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:08 ` [patch V2 06/38] posix-cpu-timers: Sample directly in timer check Thomas Gleixner
                   ` (33 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:08 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

get_itimer() locks sighand lock and checks whether the timer is already
expired. If it is not expired then the thread group cputime accounting is
already enabled. Use the sampling function not the one which is meant for
starting a timer.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/itimer.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/kernel/time/itimer.c
+++ b/kernel/time/itimer.c
@@ -58,7 +58,7 @@ static void get_cpu_itimer(struct task_s
 		struct task_cputime cputime;
 		u64 t;
 
-		thread_group_cputimer(tsk, &cputime);
+		thread_group_sample_cputime(tsk, &cputime);
 		if (clock_id == CPUCLOCK_PROF)
 			t = cputime.utime + cputime.stime;
 		else



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 06/38] posix-cpu-timers: Sample directly in timer check
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (4 preceding siblings ...)
  2019-08-21 19:08 ` [patch V2 05/38] itimers: Use quick sample function Thomas Gleixner
@ 2019-08-21 19:08 ` Thomas Gleixner
  2019-08-22 12:30   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:08 ` [patch V2 07/38] posix-cpu-timers: Rename thread_group_cputimer() and make it static Thomas Gleixner
                   ` (32 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:08 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

The thread group accounting is active, otherwise the expiry function would
not be running. Sample the thread group time directly.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |    7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -914,16 +914,17 @@ static void check_process_timers(struct
 	if (!READ_ONCE(tsk->signal->cputimer.running))
 		return;
 
-        /*
+       /*
 	 * Signify that a thread is checking for process timers.
 	 * Write access to this field is protected by the sighand lock.
 	 */
 	sig->cputimer.checking_timer = true;
 
 	/*
-	 * Collect the current process totals.
+	 * Collect the current process totals. Group accounting is active
+	 * so the sample can be taken directly.
 	 */
-	thread_group_cputimer(tsk, &cputime);
+	sample_cputime_atomic(&cputime, &sig->cputimer.cputime_atomic);
 	utime = cputime.utime;
 	ptime = utime + cputime.stime;
 	sum_sched_runtime = cputime.sum_exec_runtime;



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 07/38] posix-cpu-timers: Rename thread_group_cputimer() and make it static
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (5 preceding siblings ...)
  2019-08-21 19:08 ` [patch V2 06/38] posix-cpu-timers: Sample directly in timer check Thomas Gleixner
@ 2019-08-21 19:08 ` Thomas Gleixner
  2019-08-22 12:41   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:08 ` [patch V2 08/38] posix-cpu-timers: Consolidate thread group sample code Thomas Gleixner
                   ` (31 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:08 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

thread_group_cputimer() is a complete misnomer. The function does two things:

 - For arming process wide timers it makes sure that the atomic time
   storage is up to date. If no cpu timer is armed yet, then the atomic
   time storage is not updated by the scheduler for performance reasons.

   In that case a full summing up of all threads needs to be done and the
   update needs to be enabled.

- Samples the current time into the caller supplied storage.

Rename it to thread_group_start_cputime(), make it static and fixup the
callsite.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/sched/cputime.h  |    1 -
 kernel/time/posix-cpu-timers.c |   17 +++++++++++++++--
 2 files changed, 15 insertions(+), 3 deletions(-)

--- a/include/linux/sched/cputime.h
+++ b/include/linux/sched/cputime.h
@@ -61,7 +61,6 @@ extern void cputime_adjust(struct task_c
  * Thread group CPU time accounting.
  */
 void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times);
-void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times);
 void thread_group_sample_cputime(struct task_struct *tsk, struct task_cputime *times);
 
 /*
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -253,7 +253,20 @@ void thread_group_sample_cputime(struct
 	sample_cputime_atomic(times, &cputimer->cputime_atomic);
 }
 
-void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
+/**
+ * thread_group_start_cputime - Start cputime and return a sample
+ * @tsk:	Task for which cputime needs to be started
+ * @iimes:	Storage for time samples
+ *
+ * The thread group cputime accouting is avoided when there are no posix
+ * CPU timers armed. Before starting a timer it's required to check whether
+ * the time accounting is active. If not, a full update of the atomic
+ * accounting store needs to be done and the accounting enabled.
+ *
+ * Updates @times with an uptodate sample of the thread group cputimes.
+ */
+static void
+thread_group_start_cputime(struct task_struct *tsk, struct task_cputime *times)
 {
 	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
 	struct task_cputime sum;
@@ -536,7 +549,7 @@ static int cpu_timer_sample_group(const
 {
 	struct task_cputime cputime;
 
-	thread_group_cputimer(p, &cputime);
+	thread_group_start_cputime(p, &cputime);
 	switch (CPUCLOCK_WHICH(which_clock)) {
 	default:
 		return -EINVAL;



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 08/38] posix-cpu-timers: Consolidate thread group sample code
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (6 preceding siblings ...)
  2019-08-21 19:08 ` [patch V2 07/38] posix-cpu-timers: Rename thread_group_cputimer() and make it static Thomas Gleixner
@ 2019-08-21 19:08 ` Thomas Gleixner
  2019-08-22 13:49   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:08 ` [patch V2 09/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_set() Thomas Gleixner
                   ` (30 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:08 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

cpu_clock_sample_group() and cpu_timer_sample_group() are almost the
same. Before the rename one called thread_group_cputimer() and the other
thread_group_cputime(). Really intuitive function names.

Consolidate the functions and also avoid the thread traversal when
the thread group's accounting is already active.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Fixed typos
---
 kernel/time/posix-cpu-timers.c |   59 +++++++++++++----------------------------
 1 file changed, 20 insertions(+), 39 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -294,29 +294,37 @@ thread_group_start_cputime(struct task_s
 }
 
 /*
- * Sample a process (thread group) clock for the given group_leader task.
- * Must be called with task sighand lock held for safe while_each_thread()
- * traversal.
+ * Sample a process (thread group) clock for the given task clkid. If the
+ * group's cputime accounting is already enabled, read the atomic
+ * store. Otherwise a full update is required.  Task's sighand lock must be
+ * held to protect the task traversal on a full update.
  */
 static int cpu_clock_sample_group(const clockid_t which_clock,
 				  struct task_struct *p,
-				  u64 *sample)
+				  u64 *sample, bool start)
 {
+	struct thread_group_cputimer *cputimer = &p->signal->cputimer;
 	struct task_cputime cputime;
 
+	if (!READ_ONCE(cputimer->running)) {
+		if (start)
+			thread_group_start_cputime(p, &cputime);
+		else
+			thread_group_cputime(p, &cputime);
+	} else {
+		sample_cputime_atomic(&cputime, &cputimer->cputime_atomic);
+	}
+
 	switch (CPUCLOCK_WHICH(which_clock)) {
 	default:
 		return -EINVAL;
 	case CPUCLOCK_PROF:
-		thread_group_cputime(p, &cputime);
 		*sample = cputime.utime + cputime.stime;
 		break;
 	case CPUCLOCK_VIRT:
-		thread_group_cputime(p, &cputime);
 		*sample = cputime.utime;
 		break;
 	case CPUCLOCK_SCHED:
-		thread_group_cputime(p, &cputime);
 		*sample = cputime.sum_exec_runtime;
 		break;
 	}
@@ -336,7 +344,7 @@ static int posix_cpu_clock_get(const clo
 	if (CPUCLOCK_PERTHREAD(clock))
 		cpu_clock_sample(clkid, tsk, &t);
 	else
-		cpu_clock_sample_group(clkid, tsk, &t);
+		cpu_clock_sample_group(clkid, tsk, &t, false);
 	put_task_struct(tsk);
 
 	*tp = ns_to_timespec64(t);
@@ -540,33 +548,6 @@ static void cpu_timer_fire(struct k_itim
 }
 
 /*
- * Sample a process (thread group) timer for the given group_leader task.
- * Must be called with task sighand lock held for safe while_each_thread()
- * traversal.
- */
-static int cpu_timer_sample_group(const clockid_t which_clock,
-				  struct task_struct *p, u64 *sample)
-{
-	struct task_cputime cputime;
-
-	thread_group_start_cputime(p, &cputime);
-	switch (CPUCLOCK_WHICH(which_clock)) {
-	default:
-		return -EINVAL;
-	case CPUCLOCK_PROF:
-		*sample = cputime.utime + cputime.stime;
-		break;
-	case CPUCLOCK_VIRT:
-		*sample = cputime.utime;
-		break;
-	case CPUCLOCK_SCHED:
-		*sample = cputime.sum_exec_runtime;
-		break;
-	}
-	return 0;
-}
-
-/*
  * Guts of sys_timer_settime for CPU timers.
  * This is called with the timer locked and interrupts disabled.
  * If we return TIMER_RETRY, it's necessary to release the timer's lock
@@ -627,7 +608,7 @@ static int posix_cpu_timer_set(struct k_
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
 		cpu_clock_sample(timer->it_clock, p, &val);
 	} else {
-		cpu_timer_sample_group(timer->it_clock, p, &val);
+		cpu_clock_sample_group(timer->it_clock, p, &val, true);
 	}
 
 	if (old) {
@@ -755,7 +736,7 @@ static void posix_cpu_timer_get(struct k
 			timer->it.cpu.expires = 0;
 			return;
 		} else {
-			cpu_timer_sample_group(timer->it_clock, p, &now);
+			cpu_clock_sample_group(timer->it_clock, p, &now, false);
 			unlock_task_sighand(p, &flags);
 		}
 	}
@@ -1042,7 +1023,7 @@ static void posix_cpu_timer_rearm(struct
 			/* If the process is dying, no need to rearm */
 			goto unlock;
 		}
-		cpu_timer_sample_group(timer->it_clock, p, &now);
+		cpu_clock_sample_group(timer->it_clock, p, &now, true);
 		bump_cpu_timer(timer, now);
 		/* Leave the sighand locked for the call below.  */
 	}
@@ -1211,7 +1192,7 @@ void set_process_cpu_timer(struct task_s
 	if (WARN_ON_ONCE(clock_idx >= CPUCLOCK_SCHED))
 		return;
 
-	ret = cpu_timer_sample_group(clock_idx, tsk, &now);
+	ret = cpu_clock_sample_group(clock_idx, tsk, &now, true);
 
 	if (oldval && ret != -EINVAL) {
 		/*



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 09/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_set()
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (7 preceding siblings ...)
  2019-08-21 19:08 ` [patch V2 08/38] posix-cpu-timers: Consolidate thread group sample code Thomas Gleixner
@ 2019-08-21 19:08 ` Thomas Gleixner
  2019-08-22 13:58   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:08 ` [patch V2 10/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_get() Thomas Gleixner
                   ` (29 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:08 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Extract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it
as argument to the sample functions. That allows to simplify them once all
callers are fixed.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |   11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -556,10 +556,11 @@ static void cpu_timer_fire(struct k_itim
 static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
 			       struct itimerspec64 *new, struct itimerspec64 *old)
 {
-	unsigned long flags;
-	struct sighand_struct *sighand;
-	struct task_struct *p = timer->it.cpu.task;
+	clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
 	u64 old_expires, new_expires, old_incr, val;
+	struct task_struct *p = timer->it.cpu.task;
+	struct sighand_struct *sighand;
+	unsigned long flags;
 	int ret;
 
 	if (WARN_ON_ONCE(!p))
@@ -606,9 +607,9 @@ static int posix_cpu_timer_set(struct k_
 	 * check if it's already passed.  In short, we need a sample.
 	 */
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		cpu_clock_sample(timer->it_clock, p, &val);
+		cpu_clock_sample(clkid, p, &val);
 	} else {
-		cpu_clock_sample_group(timer->it_clock, p, &val, true);
+		cpu_clock_sample_group(clkid, p, &val, true);
 	}
 
 	if (old) {



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 10/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_get()
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (8 preceding siblings ...)
  2019-08-21 19:08 ` [patch V2 09/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_set() Thomas Gleixner
@ 2019-08-21 19:08 ` Thomas Gleixner
  2019-08-22 14:07   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:08 ` [patch V2 11/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_rearm() Thomas Gleixner
                   ` (28 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:08 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Extract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it
as argument to the sample functions. That allows to simplify them once all
callers are fixed.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -699,6 +699,7 @@ static int posix_cpu_timer_set(struct k_
 
 static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp)
 {
+	clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
 	struct task_struct *p = timer->it.cpu.task;
 	u64 now;
 
@@ -717,7 +718,7 @@ static void posix_cpu_timer_get(struct k
 	 * Sample the clock to take the difference with the expiry time.
 	 */
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		cpu_clock_sample(timer->it_clock, p, &now);
+		cpu_clock_sample(clkid, p, &now);
 	} else {
 		struct sighand_struct *sighand;
 		unsigned long flags;
@@ -737,7 +738,7 @@ static void posix_cpu_timer_get(struct k
 			timer->it.cpu.expires = 0;
 			return;
 		} else {
-			cpu_clock_sample_group(timer->it_clock, p, &now, false);
+			cpu_clock_sample_group(clkid, p, &now, false);
 			unlock_task_sighand(p, &flags);
 		}
 	}



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 11/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_rearm()
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (9 preceding siblings ...)
  2019-08-21 19:08 ` [patch V2 10/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_get() Thomas Gleixner
@ 2019-08-21 19:08 ` Thomas Gleixner
  2019-08-22 14:12   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:08 ` [patch V2 12/38] posix-cpu-timers: Remove pointless return value check Thomas Gleixner
                   ` (27 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:08 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Extract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it
as argument to the sample functions. That allows to simplify them once all
callers are fixed.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -987,6 +987,7 @@ static void check_process_timers(struct
  */
 static void posix_cpu_timer_rearm(struct k_itimer *timer)
 {
+	clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
 	struct task_struct *p = timer->it.cpu.task;
 	struct sighand_struct *sighand;
 	unsigned long flags;
@@ -999,7 +1000,7 @@ static void posix_cpu_timer_rearm(struct
 	 * Fetch the current sample and update the timer's expiry time.
 	 */
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		cpu_clock_sample(timer->it_clock, p, &now);
+		cpu_clock_sample(clkid, p, &now);
 		bump_cpu_timer(timer, now);
 		if (unlikely(p->exit_state))
 			return;
@@ -1025,7 +1026,7 @@ static void posix_cpu_timer_rearm(struct
 			/* If the process is dying, no need to rearm */
 			goto unlock;
 		}
-		cpu_clock_sample_group(timer->it_clock, p, &now, true);
+		cpu_clock_sample_group(clkid, p, &now, true);
 		bump_cpu_timer(timer, now);
 		/* Leave the sighand locked for the call below.  */
 	}



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 12/38] posix-cpu-timers: Remove pointless return value check
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (10 preceding siblings ...)
  2019-08-21 19:08 ` [patch V2 11/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_rearm() Thomas Gleixner
@ 2019-08-21 19:08 ` Thomas Gleixner
  2019-08-22 14:15   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 13/38] posix-cpu-timers: Simplify sample functions Thomas Gleixner
                   ` (26 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:08 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

set_process_cpu_timer() checks already whether the clock id is valid. No
point in checking the return value of the sample function. That allows to
simplify the sample function later.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1190,14 +1190,13 @@ void set_process_cpu_timer(struct task_s
 			   u64 *newval, u64 *oldval)
 {
 	u64 now;
-	int ret;
 
 	if (WARN_ON_ONCE(clock_idx >= CPUCLOCK_SCHED))
 		return;
 
-	ret = cpu_clock_sample_group(clock_idx, tsk, &now, true);
+	cpu_clock_sample_group(clock_idx, tsk, &now, true);
 
-	if (oldval && ret != -EINVAL) {
+	if (oldval) {
 		/*
 		 * We are setting itimer. The *oldval is absolute and we update
 		 * it to be relative, *newval argument is relative and we update



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 13/38] posix-cpu-timers: Simplify sample functions
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (11 preceding siblings ...)
  2019-08-21 19:08 ` [patch V2 12/38] posix-cpu-timers: Remove pointless return value check Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-22 14:20   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 14/38] posix-cpu-timers: Get rid of pointer indirection Thomas Gleixner
                   ` (25 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

All callers hand in a valdiated clock id. Remove the return value which was
unchecked in most places anyway.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |   28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -180,14 +180,12 @@ posix_cpu_clock_set(const clockid_t cloc
 }
 
 /*
- * Sample a per-thread clock for the given task.
+ * Sample a per-thread clock for the given task. clkid is validated.
  */
-static int cpu_clock_sample(const clockid_t which_clock,
-			    struct task_struct *p, u64 *sample)
+static void cpu_clock_sample(const clockid_t clkid, struct task_struct *p,
+			     u64 *sample)
 {
-	switch (CPUCLOCK_WHICH(which_clock)) {
-	default:
-		return -EINVAL;
+	switch (clkid) {
 	case CPUCLOCK_PROF:
 		*sample = prof_ticks(p);
 		break;
@@ -197,8 +195,9 @@ static int cpu_clock_sample(const clocki
 	case CPUCLOCK_SCHED:
 		*sample = task_sched_runtime(p);
 		break;
+	default:
+		WARN_ON_ONCE(1);
 	}
-	return 0;
 }
 
 /*
@@ -297,11 +296,11 @@ thread_group_start_cputime(struct task_s
  * Sample a process (thread group) clock for the given task clkid. If the
  * group's cputime accounting is already enabled, read the atomic
  * store. Otherwise a full update is required.  Task's sighand lock must be
- * held to protect the task traversal on a full update.
+ * held to protect the task traversal on a full update. clkid is already
+ * validated.
  */
-static int cpu_clock_sample_group(const clockid_t which_clock,
-				  struct task_struct *p,
-				  u64 *sample, bool start)
+static void cpu_clock_sample_group(const clockid_t clkid, struct task_struct *p,
+				   u64 *sample, bool start)
 {
 	struct thread_group_cputimer *cputimer = &p->signal->cputimer;
 	struct task_cputime cputime;
@@ -315,9 +314,7 @@ static int cpu_clock_sample_group(const
 		sample_cputime_atomic(&cputime, &cputimer->cputime_atomic);
 	}
 
-	switch (CPUCLOCK_WHICH(which_clock)) {
-	default:
-		return -EINVAL;
+	switch (clkid) {
 	case CPUCLOCK_PROF:
 		*sample = cputime.utime + cputime.stime;
 		break;
@@ -327,8 +324,9 @@ static int cpu_clock_sample_group(const
 	case CPUCLOCK_SCHED:
 		*sample = cputime.sum_exec_runtime;
 		break;
+	default:
+		WARN_ON_ONCE(1);
 	}
-	return 0;
 }
 
 static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 14/38] posix-cpu-timers: Get rid of pointer indirection
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (12 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 13/38] posix-cpu-timers: Simplify sample functions Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-22 14:41   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 15/38] posix-cpu-timers: Sample task times once in expiry check Thomas Gleixner
                   ` (24 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Now that the sample functions have no return value anymore, the result can
simply be returned instead of using pointer indirection.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |   50 ++++++++++++++++++-----------------------
 1 file changed, 22 insertions(+), 28 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -182,22 +182,19 @@ posix_cpu_clock_set(const clockid_t cloc
 /*
  * Sample a per-thread clock for the given task. clkid is validated.
  */
-static void cpu_clock_sample(const clockid_t clkid, struct task_struct *p,
-			     u64 *sample)
+static u64 cpu_clock_sample(const clockid_t clkid, struct task_struct *p)
 {
 	switch (clkid) {
 	case CPUCLOCK_PROF:
-		*sample = prof_ticks(p);
-		break;
+		return prof_ticks(p);
 	case CPUCLOCK_VIRT:
-		*sample = virt_ticks(p);
-		break;
+		return virt_ticks(p);
 	case CPUCLOCK_SCHED:
-		*sample = task_sched_runtime(p);
-		break;
+		return task_sched_runtime(p);
 	default:
 		WARN_ON_ONCE(1);
 	}
+	return 0;
 }
 
 /*
@@ -299,8 +296,8 @@ thread_group_start_cputime(struct task_s
  * held to protect the task traversal on a full update. clkid is already
  * validated.
  */
-static void cpu_clock_sample_group(const clockid_t clkid, struct task_struct *p,
-				   u64 *sample, bool start)
+static u64 cpu_clock_sample_group(const clockid_t clkid, struct task_struct *p,
+				  bool start)
 {
 	struct thread_group_cputimer *cputimer = &p->signal->cputimer;
 	struct task_cputime cputime;
@@ -316,17 +313,15 @@ static void cpu_clock_sample_group(const
 
 	switch (clkid) {
 	case CPUCLOCK_PROF:
-		*sample = cputime.utime + cputime.stime;
-		break;
+		return cputime.utime + cputime.stime;
 	case CPUCLOCK_VIRT:
-		*sample = cputime.utime;
-		break;
+		return cputime.utime;
 	case CPUCLOCK_SCHED:
-		*sample = cputime.sum_exec_runtime;
-		break;
+		return cputime.sum_exec_runtime;
 	default:
 		WARN_ON_ONCE(1);
 	}
+	return 0;
 }
 
 static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)
@@ -340,9 +335,9 @@ static int posix_cpu_clock_get(const clo
 		return -EINVAL;
 
 	if (CPUCLOCK_PERTHREAD(clock))
-		cpu_clock_sample(clkid, tsk, &t);
+		t = cpu_clock_sample(clkid, tsk);
 	else
-		cpu_clock_sample_group(clkid, tsk, &t, false);
+		t = cpu_clock_sample_group(clkid, tsk, false);
 	put_task_struct(tsk);
 
 	*tp = ns_to_timespec64(t);
@@ -604,11 +599,10 @@ static int posix_cpu_timer_set(struct k_
 	 * times (in arm_timer).  With an absolute time, we must
 	 * check if it's already passed.  In short, we need a sample.
 	 */
-	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		cpu_clock_sample(clkid, p, &val);
-	} else {
-		cpu_clock_sample_group(clkid, p, &val, true);
-	}
+	if (CPUCLOCK_PERTHREAD(timer->it_clock))
+		val = cpu_clock_sample(clkid, p);
+	else
+		val = cpu_clock_sample_group(clkid, p, true);
 
 	if (old) {
 		if (old_expires == 0) {
@@ -716,7 +710,7 @@ static void posix_cpu_timer_get(struct k
 	 * Sample the clock to take the difference with the expiry time.
 	 */
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		cpu_clock_sample(clkid, p, &now);
+		now = cpu_clock_sample(clkid, p);
 	} else {
 		struct sighand_struct *sighand;
 		unsigned long flags;
@@ -736,7 +730,7 @@ static void posix_cpu_timer_get(struct k
 			timer->it.cpu.expires = 0;
 			return;
 		} else {
-			cpu_clock_sample_group(clkid, p, &now, false);
+			now = cpu_clock_sample_group(clkid, p, false);
 			unlock_task_sighand(p, &flags);
 		}
 	}
@@ -998,7 +992,7 @@ static void posix_cpu_timer_rearm(struct
 	 * Fetch the current sample and update the timer's expiry time.
 	 */
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		cpu_clock_sample(clkid, p, &now);
+		now = cpu_clock_sample(clkid, p);
 		bump_cpu_timer(timer, now);
 		if (unlikely(p->exit_state))
 			return;
@@ -1024,7 +1018,7 @@ static void posix_cpu_timer_rearm(struct
 			/* If the process is dying, no need to rearm */
 			goto unlock;
 		}
-		cpu_clock_sample_group(clkid, p, &now, true);
+		now = cpu_clock_sample_group(clkid, p, true);
 		bump_cpu_timer(timer, now);
 		/* Leave the sighand locked for the call below.  */
 	}
@@ -1192,7 +1186,7 @@ void set_process_cpu_timer(struct task_s
 	if (WARN_ON_ONCE(clock_idx >= CPUCLOCK_SCHED))
 		return;
 
-	cpu_clock_sample_group(clock_idx, tsk, &now, true);
+	now = cpu_clock_sample_group(clock_idx, tsk, true);
 
 	if (oldval) {
 		/*



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 15/38] posix-cpu-timers: Sample task times once in expiry check
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (13 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 14/38] posix-cpu-timers: Get rid of pointer indirection Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-22 15:00   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 16/38] posix-cpu-timers: Move prof/virt_ticks into caller Thomas Gleixner
                   ` (23 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Sampling the task times twice does not make sense. Do it once.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |   10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -785,9 +785,9 @@ static inline void check_dl_overrun(stru
 static void check_thread_timers(struct task_struct *tsk,
 				struct list_head *firing)
 {
-	struct list_head *timers = tsk->cpu_timers;
 	struct task_cputime *tsk_expires = &tsk->cputime_expires;
-	u64 expires;
+	struct list_head *timers = tsk->cpu_timers;
+	u64 expires, stime, utime;
 	unsigned long soft;
 
 	if (dl_task(tsk))
@@ -800,10 +800,12 @@ static void check_thread_timers(struct t
 	if (task_cputime_zero(&tsk->cputime_expires))
 		return;
 
-	expires = check_timers_list(timers, firing, prof_ticks(tsk));
+	task_cputime(tsk, &utime, &stime);
+
+	expires = check_timers_list(timers, firing, utime + stime);
 	tsk_expires->prof_exp = expires;
 
-	expires = check_timers_list(++timers, firing, virt_ticks(tsk));
+	expires = check_timers_list(++timers, firing, utime);
 	tsk_expires->virt_exp = expires;
 
 	tsk_expires->sched_exp = check_timers_list(++timers, firing,



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 16/38] posix-cpu-timers: Move prof/virt_ticks into caller
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (14 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 15/38] posix-cpu-timers: Sample task times once in expiry check Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-22 15:05   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 17/38] posix-cpu-timers: Create a container struct Thomas Gleixner
                   ` (22 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

The functions have only one caller left. No point in having them.

Move the almost duplicated code into the caller and simplify it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |   30 +++++++++---------------------
 1 file changed, 9 insertions(+), 21 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -130,23 +130,6 @@ static inline int task_cputime_zero(cons
 	return 0;
 }
 
-static inline u64 prof_ticks(struct task_struct *p)
-{
-	u64 utime, stime;
-
-	task_cputime(p, &utime, &stime);
-
-	return utime + stime;
-}
-static inline u64 virt_ticks(struct task_struct *p)
-{
-	u64 utime, stime;
-
-	task_cputime(p, &utime, &stime);
-
-	return utime;
-}
-
 static int
 posix_cpu_clock_getres(const clockid_t which_clock, struct timespec64 *tp)
 {
@@ -184,13 +167,18 @@ posix_cpu_clock_set(const clockid_t cloc
  */
 static u64 cpu_clock_sample(const clockid_t clkid, struct task_struct *p)
 {
+	u64 utime, stime;
+
+	if (clkid == CPUCLOCK_SCHED)
+		return task_sched_runtime(p);
+
+	task_cputime(p, &utime, &stime);
+
 	switch (clkid) {
 	case CPUCLOCK_PROF:
-		return prof_ticks(p);
+		return utime + stime;
 	case CPUCLOCK_VIRT:
-		return virt_ticks(p);
-	case CPUCLOCK_SCHED:
-		return task_sched_runtime(p);
+		return utime;
 	default:
 		WARN_ON_ONCE(1);
 	}



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 17/38] posix-cpu-timers: Create a container struct
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (15 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 16/38] posix-cpu-timers: Move prof/virt_ticks into caller Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-22 15:32   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 19/38] posix-cpu-timers: Move expiry cache into struct posix_cputimers Thomas Gleixner
                   ` (21 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Per task/process data of posix CPU timers is all over the place which
makes the code hard to follow and requires ifdeffery.

Create a container to hold all this information in one place, so data is
consolidated and the ifdeffery can be confined to the posix timer header
file and removed from places like fork.

As a first step, move the cpu_timers list head array into the new struct
and clean up the initializers and simplify fork. The remaining #ifdef in
fork will be removed later.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Have an empty struct for POSIX_TIMERS=n so ifdefs can be avoided
---
 include/linux/init_task.h      |   11 -----------
 include/linux/posix-timers.h   |   34 ++++++++++++++++++++++++++++++++++
 include/linux/sched.h          |    4 +++-
 include/linux/sched/signal.h   |    5 +++--
 kernel/fork.c                  |   11 ++++-------
 kernel/time/posix-cpu-timers.c |   20 ++++++++++----------
 6 files changed, 54 insertions(+), 31 deletions(-)

--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -36,17 +36,6 @@ extern struct cred init_cred;
 #define INIT_PREV_CPUTIME(x)
 #endif
 
-#ifdef CONFIG_POSIX_TIMERS
-#define INIT_CPU_TIMERS(s)						\
-	.cpu_timers = {							\
-		LIST_HEAD_INIT(s.cpu_timers[0]),			\
-		LIST_HEAD_INIT(s.cpu_timers[1]),			\
-		LIST_HEAD_INIT(s.cpu_timers[2]),			\
-	},
-#else
-#define INIT_CPU_TIMERS(s)
-#endif
-
 #define INIT_TASK_COMM "swapper"
 
 /* Attach to the init_task data structure for proper alignment */
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -62,6 +62,40 @@ static inline int clockid_to_fd(const cl
 	return ~(clk >> 3);
 }
 
+/**
+ * posix_cputimers - Container for posix CPU timer related data
+ * @cpu_timers:		List heads to queue posix CPU timers
+ *
+ * Used in task_struct and signal_struct
+ */
+struct posix_cputimers {
+	struct list_head	cpu_timers[CPUCLOCK_MAX];
+};
+
+static inline void posix_cputimers_init(struct posix_cputimers *pct)
+{
+	INIT_LIST_HEAD(&pct->cpu_timers[0]);
+	INIT_LIST_HEAD(&pct->cpu_timers[1]);
+	INIT_LIST_HEAD(&pct->cpu_timers[2]);
+}
+
+#ifdef CONFIG_POSIX_TIMERS
+/* Init task static initializer */
+#define INIT_CPU_TIMERLISTS(c)	{					\
+	LIST_HEAD_INIT(c.cpu_timers[0]),				\
+	LIST_HEAD_INIT(c.cpu_timers[1]),				\
+	LIST_HEAD_INIT(c.cpu_timers[2]),				\
+}
+
+#define INIT_CPU_TIMERS(s)						\
+	.posix_cputimers = {						\
+		.cpu_timers = INIT_CPU_TIMERLISTS(s.posix_cputimers),	\
+	},
+#else
+struct posix_cputimers { };
+#define INIT_CPU_TIMERS(s)
+#endif
+
 #define REQUEUE_PENDING 1
 
 /**
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -28,6 +28,7 @@
 #include <linux/signal_types.h>
 #include <linux/mm_types_task.h>
 #include <linux/task_io_accounting.h>
+#include <linux/posix-timers.h>
 #include <linux/rseq.h>
 
 /* task_struct member predeclarations (sorted alphabetically): */
@@ -878,8 +879,9 @@ struct task_struct {
 
 #ifdef CONFIG_POSIX_TIMERS
 	struct task_cputime		cputime_expires;
-	struct list_head		cpu_timers[3];
 #endif
+	/* Empty if CONFIG_POSIX_CPUTIMERS=n */
+	struct posix_cputimers		posix_cputimers;
 
 	/* Process credentials: */
 
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -9,6 +9,7 @@
 #include <linux/sched/task.h>
 #include <linux/cred.h>
 #include <linux/refcount.h>
+#include <linux/posix-timers.h>
 
 /*
  * Types defining task->signal and task->sighand and APIs using them:
@@ -151,9 +152,9 @@ struct signal_struct {
 	/* Earliest-expiration cache. */
 	struct task_cputime cputime_expires;
 
-	struct list_head cpu_timers[3];
-
 #endif
+	/* Empty if CONFIG_POSIX_TIMERS=n */
+	struct posix_cputimers posix_cputimers;
 
 	/* PID/PID hash table linkage. */
 	struct pid *pids[PIDTYPE_MAX];
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1523,6 +1523,7 @@ void __cleanup_sighand(struct sighand_st
  */
 static void posix_cpu_timers_init_group(struct signal_struct *sig)
 {
+	struct posix_cputimers *pct = &sig->posix_cputimers;
 	unsigned long cpu_limit;
 
 	cpu_limit = READ_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur);
@@ -1531,10 +1532,7 @@ static void posix_cpu_timers_init_group(
 		sig->cputimer.running = true;
 	}
 
-	/* The timer lists. */
-	INIT_LIST_HEAD(&sig->cpu_timers[0]);
-	INIT_LIST_HEAD(&sig->cpu_timers[1]);
-	INIT_LIST_HEAD(&sig->cpu_timers[2]);
+	posix_cputimers_init(pct);
 }
 #else
 static inline void posix_cpu_timers_init_group(struct signal_struct *sig) { }
@@ -1649,9 +1647,8 @@ static void posix_cpu_timers_init(struct
 	tsk->cputime_expires.prof_exp = 0;
 	tsk->cputime_expires.virt_exp = 0;
 	tsk->cputime_expires.sched_exp = 0;
-	INIT_LIST_HEAD(&tsk->cpu_timers[0]);
-	INIT_LIST_HEAD(&tsk->cpu_timers[1]);
-	INIT_LIST_HEAD(&tsk->cpu_timers[2]);
+
+	posix_cputimers_init(&tsk->posix_cputimers);
 }
 #else
 static inline void posix_cpu_timers_init(struct task_struct *tsk) { }
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -407,11 +407,11 @@ static void cleanup_timers_list(struct l
  *
  * This must be called with the siglock held.
  */
-static void cleanup_timers(struct list_head *head)
+static void cleanup_timers(struct posix_cputimers *pct)
 {
-	cleanup_timers_list(head);
-	cleanup_timers_list(++head);
-	cleanup_timers_list(++head);
+	cleanup_timers_list(&pct->cpu_timers[CPUCLOCK_PROF]);
+	cleanup_timers_list(&pct->cpu_timers[CPUCLOCK_VIRT]);
+	cleanup_timers_list(&pct->cpu_timers[CPUCLOCK_SCHED]);
 }
 
 /*
@@ -421,11 +421,11 @@ static void cleanup_timers(struct list_h
  */
 void posix_cpu_timers_exit(struct task_struct *tsk)
 {
-	cleanup_timers(tsk->cpu_timers);
+	cleanup_timers(&tsk->posix_cputimers);
 }
 void posix_cpu_timers_exit_group(struct task_struct *tsk)
 {
-	cleanup_timers(tsk->signal->cpu_timers);
+	cleanup_timers(&tsk->signal->posix_cputimers);
 }
 
 static inline int expires_gt(u64 expires, u64 new_exp)
@@ -446,10 +446,10 @@ static void arm_timer(struct k_itimer *t
 	struct cpu_timer_list *next;
 
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		head = p->cpu_timers;
+		head = p->posix_cputimers.cpu_timers;
 		cputime_expires = &p->cputime_expires;
 	} else {
-		head = p->signal->cpu_timers;
+		head = p->signal->posix_cputimers.cpu_timers;
 		cputime_expires = &p->signal->cputime_expires;
 	}
 	head += CPUCLOCK_WHICH(timer->it_clock);
@@ -773,8 +773,8 @@ static inline void check_dl_overrun(stru
 static void check_thread_timers(struct task_struct *tsk,
 				struct list_head *firing)
 {
+	struct list_head *timers = tsk->posix_cputimers.cpu_timers;
 	struct task_cputime *tsk_expires = &tsk->cputime_expires;
-	struct list_head *timers = tsk->cpu_timers;
 	u64 expires, stime, utime;
 	unsigned long soft;
 
@@ -879,9 +879,9 @@ static void check_process_timers(struct
 				 struct list_head *firing)
 {
 	struct signal_struct *const sig = tsk->signal;
+	struct list_head *timers = sig->posix_cputimers.cpu_timers;
 	u64 utime, ptime, virt_expires, prof_expires;
 	u64 sum_sched_runtime, sched_expires;
-	struct list_head *timers = sig->cpu_timers;
 	struct task_cputime cputime;
 	unsigned long soft;
 



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 19/38] posix-cpu-timers: Move expiry cache into struct posix_cputimers
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (16 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 17/38] posix-cpu-timers: Create a container struct Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-22 16:29   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 20/38] posix-cpu-timers: Provide array based access to expiry cache Thomas Gleixner
                   ` (20 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

The expiry cache belongs into the posix_cputimers container where the other
cpu timers information is.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Adapt to previous change of empty struct and move the group init out of
    line to avoid include hell.
---
 include/linux/posix-timers.h   |   24 ++++++++++++++++++++-
 include/linux/sched.h          |    8 -------
 include/linux/sched/signal.h   |    3 --
 kernel/fork.c                  |   25 ++--------------------
 kernel/sched/rt.c              |    6 +++--
 kernel/time/posix-cpu-timers.c |   45 ++++++++++++++++++++++++-----------------
 6 files changed, 57 insertions(+), 54 deletions(-)

--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -62,24 +62,43 @@ static inline int clockid_to_fd(const cl
 	return ~(clk >> 3);
 }
 
+/*
+ * Alternate field names for struct task_cputime when used on cache
+ * expirations. Will go away soon.
+ */
+#define virt_exp			utime
+#define prof_exp			stime
+#define sched_exp			sum_exec_runtime
+
+#ifdef CONFIG_POSIX_TIMERS
 /**
  * posix_cputimers - Container for posix CPU timer related data
+ * @cputime_expires:	Earliest-expiration cache
  * @cpu_timers:		List heads to queue posix CPU timers
  *
  * Used in task_struct and signal_struct
  */
 struct posix_cputimers {
+	struct task_cputime	cputime_expires;
 	struct list_head	cpu_timers[CPUCLOCK_MAX];
 };
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
 {
+	memset(&pct->cputime_expires, 0, sizeof(pct->cputime_expires));
 	INIT_LIST_HEAD(&pct->cpu_timers[0]);
 	INIT_LIST_HEAD(&pct->cpu_timers[1]);
 	INIT_LIST_HEAD(&pct->cpu_timers[2]);
 }
 
-#ifdef CONFIG_POSIX_TIMERS
+void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit);
+
+static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct,
+					       u64 runtime)
+{
+	pct->cputime_expires.sched_exp = runtime;
+}
+
 /* Init task static initializer */
 #define INIT_CPU_TIMERLISTS(c)	{					\
 	LIST_HEAD_INIT(c.cpu_timers[0]),				\
@@ -94,6 +113,9 @@ static inline void posix_cputimers_init(
 #else
 struct posix_cputimers { };
 #define INIT_CPU_TIMERS(s)
+static inline void posix_cputimers_init(struct posix_cputimers *pct) { }
+static inline void posix_cputimers_group_init(struct posix_cputimers *pct,
+					      u64 cpu_limit) { }
 #endif
 
 #define REQUEUE_PENDING 1
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -246,11 +246,6 @@ struct prev_cputime {
 #endif
 };
 
-/* Alternate field names when used on cache expirations: */
-#define virt_exp			utime
-#define prof_exp			stime
-#define sched_exp			sum_exec_runtime
-
 enum vtime_state {
 	/* Task is sleeping or running in a CPU with VTIME inactive: */
 	VTIME_INACTIVE = 0,
@@ -862,9 +857,6 @@ struct task_struct {
 	unsigned long			min_flt;
 	unsigned long			maj_flt;
 
-#ifdef CONFIG_POSIX_TIMERS
-	struct task_cputime		cputime_expires;
-#endif
 	/* Empty if CONFIG_POSIX_CPUTIMERS=n */
 	struct posix_cputimers		posix_cputimers;
 
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -149,9 +149,6 @@ struct signal_struct {
 	 */
 	struct thread_group_cputimer cputimer;
 
-	/* Earliest-expiration cache. */
-	struct task_cputime cputime_expires;
-
 #endif
 	/* Empty if CONFIG_POSIX_TIMERS=n */
 	struct posix_cputimers posix_cputimers;
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1527,12 +1527,9 @@ static void posix_cpu_timers_init_group(
 	unsigned long cpu_limit;
 
 	cpu_limit = READ_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur);
-	if (cpu_limit != RLIM_INFINITY) {
-		sig->cputime_expires.prof_exp = cpu_limit * NSEC_PER_SEC;
+	posix_cputimers_group_init(pct, cpu_limit);
+	if (cpu_limit != RLIM_INFINITY)
 		sig->cputimer.running = true;
-	}
-
-	posix_cputimers_init(pct);
 }
 #else
 static inline void posix_cpu_timers_init_group(struct signal_struct *sig) { }
@@ -1638,22 +1635,6 @@ static void rt_mutex_init_task(struct ta
 #endif
 }
 
-#ifdef CONFIG_POSIX_TIMERS
-/*
- * Initialize POSIX timer handling for a single task.
- */
-static void posix_cpu_timers_init(struct task_struct *tsk)
-{
-	tsk->cputime_expires.prof_exp = 0;
-	tsk->cputime_expires.virt_exp = 0;
-	tsk->cputime_expires.sched_exp = 0;
-
-	posix_cputimers_init(&tsk->posix_cputimers);
-}
-#else
-static inline void posix_cpu_timers_init(struct task_struct *tsk) { }
-#endif
-
 static inline void init_task_pid_links(struct task_struct *task)
 {
 	enum pid_type type;
@@ -1932,7 +1913,7 @@ static __latent_entropy struct task_stru
 	task_io_accounting_init(&p->ioac);
 	acct_clear_integrals(p);
 
-	posix_cpu_timers_init(p);
+	posix_cputimers_init(&p->posix_cputimers);
 
 	p->io_context = NULL;
 	audit_set_context(p, NULL);
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -2305,8 +2305,10 @@ static void watchdog(struct rq *rq, stru
 		}
 
 		next = DIV_ROUND_UP(min(soft, hard), USEC_PER_SEC/HZ);
-		if (p->rt.timeout > next)
-			p->cputime_expires.sched_exp = p->se.sum_exec_runtime;
+		if (p->rt.timeout > next) {
+			posix_cputimers_rt_watchdog(&p->posix_cputimers,
+						    p->se.sum_exec_runtime);
+		}
 	}
 }
 #else
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -20,11 +20,18 @@
 
 static void posix_cpu_timer_rearm(struct k_itimer *timer);
 
+void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit)
+{
+	posix_cputimers_init(pct);
+	if (cpu_limit != RLIM_INFINITY)
+		pct->cputime_expires.prof_exp = cpu_limit * NSEC_PER_SEC;
+}
+
 /*
  * Called after updating RLIMIT_CPU to run cpu timer and update
- * tsk->signal->cputime_expires expiration cache if necessary. Needs
- * siglock protection since other code may update expiration cache as
- * well.
+ * tsk->signal->posix_cputimers.cputime_expires expiration cache if
+ * necessary. Needs siglock protection since other code may update
+ * expiration cache as well.
  */
 void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new)
 {
@@ -447,10 +454,10 @@ static void arm_timer(struct k_itimer *t
 
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
 		head = p->posix_cputimers.cpu_timers;
-		cputime_expires = &p->cputime_expires;
+		cputime_expires = &p->posix_cputimers.cputime_expires;
 	} else {
 		head = p->signal->posix_cputimers.cpu_timers;
-		cputime_expires = &p->signal->cputime_expires;
+		cputime_expires = &p->signal->posix_cputimers.cputime_expires;
 	}
 	head += CPUCLOCK_WHICH(timer->it_clock);
 
@@ -774,7 +781,7 @@ static void check_thread_timers(struct t
 				struct list_head *firing)
 {
 	struct list_head *timers = tsk->posix_cputimers.cpu_timers;
-	struct task_cputime *tsk_expires = &tsk->cputime_expires;
+	struct task_cputime *tsk_expires = &tsk->posix_cputimers.cputime_expires;
 	u64 expires, stime, utime;
 	unsigned long soft;
 
@@ -785,7 +792,7 @@ static void check_thread_timers(struct t
 	 * If cputime_expires is zero, then there are no active
 	 * per thread CPU timers.
 	 */
-	if (task_cputime_zero(&tsk->cputime_expires))
+	if (task_cputime_zero(tsk_expires))
 		return;
 
 	task_cputime(tsk, &utime, &stime);
@@ -954,10 +961,10 @@ static void check_process_timers(struct
 			prof_expires = x;
 	}
 
-	sig->cputime_expires.prof_exp = prof_expires;
-	sig->cputime_expires.virt_exp = virt_expires;
-	sig->cputime_expires.sched_exp = sched_expires;
-	if (task_cputime_zero(&sig->cputime_expires))
+	sig->posix_cputimers.cputime_expires.prof_exp = prof_expires;
+	sig->posix_cputimers.cputime_expires.virt_exp = virt_expires;
+	sig->posix_cputimers.cputime_expires.sched_exp = sched_expires;
+	if (task_cputime_zero(&sig->posix_cputimers.cputime_expires))
 		stop_process_timers(sig);
 
 	sig->cputimer.checking_timer = false;
@@ -1058,12 +1065,13 @@ static inline int fastpath_timer_check(s
 {
 	struct signal_struct *sig;
 
-	if (!task_cputime_zero(&tsk->cputime_expires)) {
+	if (!task_cputime_zero(&tsk->posix_cputimers.cputime_expires)) {
 		struct task_cputime task_sample;
 
 		task_cputime(tsk, &task_sample.utime, &task_sample.stime);
 		task_sample.sum_exec_runtime = tsk->se.sum_exec_runtime;
-		if (task_cputime_expired(&task_sample, &tsk->cputime_expires))
+		if (task_cputime_expired(&task_sample,
+					 &tsk->posix_cputimers.cputime_expires))
 			return 1;
 	}
 
@@ -1088,7 +1096,8 @@ static inline int fastpath_timer_check(s
 
 		sample_cputime_atomic(&group_sample, &sig->cputimer.cputime_atomic);
 
-		if (task_cputime_expired(&group_sample, &sig->cputime_expires))
+		if (task_cputime_expired(&group_sample,
+					 &sig->posix_cputimers.cputime_expires))
 			return 1;
 	}
 
@@ -1204,12 +1213,12 @@ void set_process_cpu_timer(struct task_s
 	 */
 	switch (clock_idx) {
 	case CPUCLOCK_PROF:
-		if (expires_gt(tsk->signal->cputime_expires.prof_exp, *newval))
-			tsk->signal->cputime_expires.prof_exp = *newval;
+		if (expires_gt(tsk->signal->posix_cputimers.cputime_expires.prof_exp, *newval))
+			tsk->signal->posix_cputimers.cputime_expires.prof_exp = *newval;
 		break;
 	case CPUCLOCK_VIRT:
-		if (expires_gt(tsk->signal->cputime_expires.virt_exp, *newval))
-			tsk->signal->cputime_expires.virt_exp = *newval;
+		if (expires_gt(tsk->signal->posix_cputimers.cputime_expires.virt_exp, *newval))
+			tsk->signal->posix_cputimers.cputime_expires.virt_exp = *newval;
 		break;
 	}
 



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 20/38] posix-cpu-timers: Provide array based access to expiry cache
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (17 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 19/38] posix-cpu-timers: Move expiry cache into struct posix_cputimers Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-23 17:33   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 21/38] posix-cpu-timers: Simplify timer queueing Thomas Gleixner
                   ` (19 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Using struct task_cputime for the expiry cache is a pretty odd choice and
comes with magic defines to rename the fields for usage in the expiry
cache.

struct task_cputime is basically a u64 array with 3 members, but it has
distinct members.

The expiry cache content is different than the content of task_cputime
because

  expiry[PROF]  = task_cputime.stime + task_cputime.utime
  expiry[VIRT]  = task_cputime.utime
  expiry[SCHED] = task_cputime.sum_exec_runtime

So there is no direct mapping between task_cputime and the expiry cache and
the #define based remapping is just a horrible hack.

Having the expiry cache array based allows further simplification of the
expiry code.

To avoid an all in one cleanup which is hard to review add a temporary
anonymous union into struct task_cputime which allows array based access to
it. That requires to reorder the members. Add a build time sanity check to
validate that the members are at the same place.

The union and the build time checks will be removed after conversion.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/posix-timers.h   |   24 ++++++++++++++++++------
 include/linux/sched/types.h    |    4 ++--
 kernel/time/posix-cpu-timers.c |   12 +++++++++++-
 3 files changed, 31 insertions(+), 9 deletions(-)

--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -65,27 +65,39 @@ static inline int clockid_to_fd(const cl
 /*
  * Alternate field names for struct task_cputime when used on cache
  * expirations. Will go away soon.
+ *
+ * stime corresponds to CLOCKCPU_PROF
+ * utime corresponds to CLOCKCPU_VIRT
+ * sum_exex_runtime corresponds to CLOCKCPU_SCHED
+ *
+ * The ordering is currently enforced so struct task_cputime and the
+ * expiries array in struct posix_cputimers are equivalent.
  */
-#define virt_exp			utime
 #define prof_exp			stime
+#define virt_exp			utime
 #define sched_exp			sum_exec_runtime
 
 #ifdef CONFIG_POSIX_TIMERS
 /**
  * posix_cputimers - Container for posix CPU timer related data
- * @cputime_expires:	Earliest-expiration cache
+ * @cputime_expires:	Earliest-expiration cache task_cputime based
+ * @expiries:		Earliest-expiration cache array based
  * @cpu_timers:		List heads to queue posix CPU timers
  *
  * Used in task_struct and signal_struct
  */
 struct posix_cputimers {
-	struct task_cputime	cputime_expires;
-	struct list_head	cpu_timers[CPUCLOCK_MAX];
+	/* Temporary union until all users are cleaned up */
+	union {
+		struct task_cputime	cputime_expires;
+		u64			expiries[CPUCLOCK_MAX];
+	};
+	struct list_head		cpu_timers[CPUCLOCK_MAX];
 };
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
 {
-	memset(&pct->cputime_expires, 0, sizeof(pct->cputime_expires));
+	memset(&pct->expiries, 0, sizeof(pct->expiries));
 	INIT_LIST_HEAD(&pct->cpu_timers[0]);
 	INIT_LIST_HEAD(&pct->cpu_timers[1]);
 	INIT_LIST_HEAD(&pct->cpu_timers[2]);
@@ -96,7 +108,7 @@ void posix_cputimers_group_init(struct p
 static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct,
 					       u64 runtime)
 {
-	pct->cputime_expires.sched_exp = runtime;
+	pct->expiries[CPUCLOCK_SCHED] = runtime;
 }
 
 /* Init task static initializer */
--- a/include/linux/sched/types.h
+++ b/include/linux/sched/types.h
@@ -6,8 +6,8 @@
 
 /**
  * struct task_cputime - collected CPU time counts
- * @utime:		time spent in user mode, in nanoseconds
  * @stime:		time spent in kernel mode, in nanoseconds
+ * @utime:		time spent in user mode, in nanoseconds
  * @sum_exec_runtime:	total time spent on the CPU, in nanoseconds
  *
  * This structure groups together three kinds of CPU time that are tracked for
@@ -15,8 +15,8 @@
  * these counts together and treat all three of them in parallel.
  */
 struct task_cputime {
-	u64				utime;
 	u64				stime;
+	u64				utime;
 	unsigned long long		sum_exec_runtime;
 };
 
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -18,13 +18,23 @@
 
 #include "posix-timers.h"
 
+static inline void temporary_check(void)
+{
+	BUILD_BUG_ON(offsetof(struct task_cputime, stime) !=
+		     CPUCLOCK_PROF * sizeof(u64));
+	BUILD_BUG_ON(offsetof(struct task_cputime, utime) !=
+		     CPUCLOCK_VIRT * sizeof(u64));
+	BUILD_BUG_ON(offsetof(struct task_cputime, sum_exec_runtime) !=
+		     CPUCLOCK_SCHED * sizeof(u64));
+}
+
 static void posix_cpu_timer_rearm(struct k_itimer *timer);
 
 void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit)
 {
 	posix_cputimers_init(pct);
 	if (cpu_limit != RLIM_INFINITY)
-		pct->cputime_expires.prof_exp = cpu_limit * NSEC_PER_SEC;
+		pct->expiries[CPUCLOCK_PROF] = cpu_limit * NSEC_PER_SEC;
 }
 
 /*



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 21/38] posix-cpu-timers: Simplify timer queueing
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (18 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 20/38] posix-cpu-timers: Provide array based access to expiry cache Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-23 17:51   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 22/38] posix-cpu-timers: Simplify set_process_cpu_timer() Thomas Gleixner
                   ` (18 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Now that the expiry cache can be accessed as an array, the per clock
checking can be reduced to just comparing the corresponding array elements.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |   57 +++++++++++++++--------------------------
 1 file changed, 22 insertions(+), 35 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -456,20 +456,20 @@ static inline int expires_gt(u64 expires
  */
 static void arm_timer(struct k_itimer *timer)
 {
+	struct cpu_timer_list *const nt = &timer->it.cpu;
+	int clkidx = CPUCLOCK_WHICH(timer->it_clock);
+	u64 *cpuexp, newexp = timer->it.cpu.expires;
 	struct task_struct *p = timer->it.cpu.task;
 	struct list_head *head, *listpos;
-	struct task_cputime *cputime_expires;
-	struct cpu_timer_list *const nt = &timer->it.cpu;
 	struct cpu_timer_list *next;
 
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		head = p->posix_cputimers.cpu_timers;
-		cputime_expires = &p->posix_cputimers.cputime_expires;
+		head = p->posix_cputimers.cpu_timers + clkidx;
+		cpuexp = p->posix_cputimers.expiries + clkidx;
 	} else {
-		head = p->signal->posix_cputimers.cpu_timers;
-		cputime_expires = &p->signal->posix_cputimers.cputime_expires;
+		head = p->signal->posix_cputimers.cpu_timers + clkidx;
+		cpuexp = p->signal->posix_cputimers.expiries + clkidx;
 	}
-	head += CPUCLOCK_WHICH(timer->it_clock);
 
 	listpos = head;
 	list_for_each_entry(next, head, entry) {
@@ -479,35 +479,22 @@ static void arm_timer(struct k_itimer *t
 	}
 	list_add(&nt->entry, listpos);
 
-	if (listpos == head) {
-		u64 exp = nt->expires;
+	if (listpos != head)
+		return;
 
-		/*
-		 * We are the new earliest-expiring POSIX 1.b timer, hence
-		 * need to update expiration cache. Take into account that
-		 * for process timers we share expiration cache with itimers
-		 * and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME.
-		 */
-
-		switch (CPUCLOCK_WHICH(timer->it_clock)) {
-		case CPUCLOCK_PROF:
-			if (expires_gt(cputime_expires->prof_exp, exp))
-				cputime_expires->prof_exp = exp;
-			break;
-		case CPUCLOCK_VIRT:
-			if (expires_gt(cputime_expires->virt_exp, exp))
-				cputime_expires->virt_exp = exp;
-			break;
-		case CPUCLOCK_SCHED:
-			if (expires_gt(cputime_expires->sched_exp, exp))
-				cputime_expires->sched_exp = exp;
-			break;
-		}
-		if (CPUCLOCK_PERTHREAD(timer->it_clock))
-			tick_dep_set_task(p, TICK_DEP_BIT_POSIX_TIMER);
-		else
-			tick_dep_set_signal(p->signal, TICK_DEP_BIT_POSIX_TIMER);
-	}
+	/*
+	 * We are the new earliest-expiring POSIX 1.b timer, hence
+	 * need to update expiration cache. Take into account that
+	 * for process timers we share expiration cache with itimers
+	 * and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME.
+	 */
+	if (expires_gt(*cpuexp, newexp))
+		*cpuexp = newexp;
+
+	if (CPUCLOCK_PERTHREAD(timer->it_clock))
+		tick_dep_set_task(p, TICK_DEP_BIT_POSIX_TIMER);
+	else
+		tick_dep_set_signal(p->signal, TICK_DEP_BIT_POSIX_TIMER);
 }
 
 /*



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 22/38] posix-cpu-timers: Simplify set_process_cpu_timer()
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (19 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 21/38] posix-cpu-timers: Simplify timer queueing Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-23 18:00   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 23/38] posix-cpu-timers: Switch check_*_timers() to array cache Thomas Gleixner
                   ` (17 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

The expiry cache can now be accessed as an array. Replace the per clock
checks with a simple comparison of the clock indexed array member.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |   24 ++++++++----------------
 1 file changed, 8 insertions(+), 16 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1174,15 +1174,15 @@ void run_posix_cpu_timers(void)
  * Set one of the process-wide special case CPU timers or RLIMIT_CPU.
  * The tsk->sighand->siglock must be held by the caller.
  */
-void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
+void set_process_cpu_timer(struct task_struct *tsk, unsigned int clkid,
 			   u64 *newval, u64 *oldval)
 {
-	u64 now;
+	u64 now, *expiry = tsk->signal->posix_cputimers.expiries + clkid;
 
-	if (WARN_ON_ONCE(clock_idx >= CPUCLOCK_SCHED))
+	if (WARN_ON_ONCE(clkid >= CPUCLOCK_SCHED))
 		return;
 
-	now = cpu_clock_sample_group(clock_idx, tsk, true);
+	now = cpu_clock_sample_group(clkid, tsk, true);
 
 	if (oldval) {
 		/*
@@ -1205,19 +1205,11 @@ void set_process_cpu_timer(struct task_s
 	}
 
 	/*
-	 * Update expiration cache if we are the earliest timer, or eventually
-	 * RLIMIT_CPU limit is earlier than prof_exp cpu timer expire.
+	 * Update expiration cache if this is the earliest timer. CPUCLOCK_PROF
+	 * expiry cache is also used by RLIMIT_CPU!.
 	 */
-	switch (clock_idx) {
-	case CPUCLOCK_PROF:
-		if (expires_gt(tsk->signal->posix_cputimers.cputime_expires.prof_exp, *newval))
-			tsk->signal->posix_cputimers.cputime_expires.prof_exp = *newval;
-		break;
-	case CPUCLOCK_VIRT:
-		if (expires_gt(tsk->signal->posix_cputimers.cputime_expires.virt_exp, *newval))
-			tsk->signal->posix_cputimers.cputime_expires.virt_exp = *newval;
-		break;
-	}
+	if (expires_gt(*expiry, *newval))
+		*expiry = *newval;
 
 	tick_dep_set_signal(tsk->signal, TICK_DEP_BIT_POSIX_TIMER);
 }



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 23/38] posix-cpu-timers: Switch check_*_timers() to array cache
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (20 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 22/38] posix-cpu-timers: Simplify set_process_cpu_timer() Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-23 18:13   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 24/38] posix-cpu-timers: Remove the odd field rename defines Thomas Gleixner
                   ` (16 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Use the array based expiry cache in check_thread_timers() and convert the
store in check_process_timers() for consistency.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |   26 +++++++++++---------------
 1 file changed, 11 insertions(+), 15 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -778,8 +778,7 @@ static void check_thread_timers(struct t
 				struct list_head *firing)
 {
 	struct list_head *timers = tsk->posix_cputimers.cpu_timers;
-	struct task_cputime *tsk_expires = &tsk->posix_cputimers.cputime_expires;
-	u64 expires, stime, utime;
+	u64 stime, utime, *expires = tsk->posix_cputimers.expiries;
 	unsigned long soft;
 
 	if (dl_task(tsk))
@@ -789,19 +788,14 @@ static void check_thread_timers(struct t
 	 * If cputime_expires is zero, then there are no active
 	 * per thread CPU timers.
 	 */
-	if (task_cputime_zero(tsk_expires))
+	if (task_cputime_zero(&tsk->posix_cputimers.cputime_expires))
 		return;
 
 	task_cputime(tsk, &utime, &stime);
 
-	expires = check_timers_list(timers, firing, utime + stime);
-	tsk_expires->prof_exp = expires;
-
-	expires = check_timers_list(++timers, firing, utime);
-	tsk_expires->virt_exp = expires;
-
-	tsk_expires->sched_exp = check_timers_list(++timers, firing,
-						   tsk->se.sum_exec_runtime);
+	*expires++ = check_timers_list(timers, firing, utime + stime);
+	*expires++ = check_timers_list(++timers, firing, utime);
+	*expires = check_timers_list(++timers, firing, tsk->se.sum_exec_runtime);
 
 	/*
 	 * Check for the special case thread timers.
@@ -839,7 +833,8 @@ static void check_thread_timers(struct t
 			__group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
 		}
 	}
-	if (task_cputime_zero(tsk_expires))
+
+	if (task_cputime_zero(&tsk->posix_cputimers.cputime_expires))
 		tick_dep_clear_task(tsk, TICK_DEP_BIT_POSIX_TIMER);
 }
 
@@ -958,9 +953,10 @@ static void check_process_timers(struct
 			prof_expires = x;
 	}
 
-	sig->posix_cputimers.cputime_expires.prof_exp = prof_expires;
-	sig->posix_cputimers.cputime_expires.virt_exp = virt_expires;
-	sig->posix_cputimers.cputime_expires.sched_exp = sched_expires;
+	sig->posix_cputimers.expiries[CPUCLOCK_PROF] = prof_expires;
+	sig->posix_cputimers.expiries[CPUCLOCK_VIRT] = virt_expires;
+	sig->posix_cputimers.expiries[CPUCLOCK_SCHED] = sched_expires;
+
 	if (task_cputime_zero(&sig->posix_cputimers.cputime_expires))
 		stop_process_timers(sig);
 



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 24/38] posix-cpu-timers: Remove the odd field rename defines
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (21 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 23/38] posix-cpu-timers: Switch check_*_timers() to array cache Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-23 18:36   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 25/38] posix-cpu-timers: Provide array based sample functions Thomas Gleixner
                   ` (15 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

The last users of the odd define based renaming of struct task_cputime
members are gone. Good riddance.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/posix-timers.h |   15 ---------------
 1 file changed, 15 deletions(-)

--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -62,21 +62,6 @@ static inline int clockid_to_fd(const cl
 	return ~(clk >> 3);
 }
 
-/*
- * Alternate field names for struct task_cputime when used on cache
- * expirations. Will go away soon.
- *
- * stime corresponds to CLOCKCPU_PROF
- * utime corresponds to CLOCKCPU_VIRT
- * sum_exex_runtime corresponds to CLOCKCPU_SCHED
- *
- * The ordering is currently enforced so struct task_cputime and the
- * expiries array in struct posix_cputimers are equivalent.
- */
-#define prof_exp			stime
-#define virt_exp			utime
-#define sched_exp			sum_exec_runtime
-
 #ifdef CONFIG_POSIX_TIMERS
 /**
  * posix_cputimers - Container for posix CPU timer related data



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 25/38] posix-cpu-timers: Provide array based sample functions
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (22 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 24/38] posix-cpu-timers: Remove the odd field rename defines Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-23 22:08   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 26/38] posix-cpu-timers: Make expiry checks array based Thomas Gleixner
                   ` (14 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Instead of using task_cputime and doing the addition of utime and stime at
all call sites, it's way simpler to have a sample array which allows
indexed based checks against the expiry cache array.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |   26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -202,6 +202,32 @@ static u64 cpu_clock_sample(const clocki
 	return 0;
 }
 
+static inline void store_samples(u64 *samples, u64 stime, u64 utime, u64 rtime)
+{
+	samples[CPUCLOCK_PROF] = stime + utime;
+	samples[CPUCLOCK_VIRT] = utime;
+	samples[CPUCLOCK_SCHED] = rtime;
+}
+
+static void task_sample_cputime(struct task_struct *p, u64 *samples)
+{
+	u64 stime, utime;
+
+	task_cputime(p, &utime, &stime);
+	store_samples(samples, stime, utime, p->se.sum_exec_runtime);
+}
+
+static void proc_sample_cputime_atomic(struct task_cputime_atomic *at,
+				       u64 *samples)
+{
+	u64 stime, utime, rtime;
+
+	utime = atomic64_read(&at->utime);
+	stime = atomic64_read(&at->stime);
+	rtime = atomic64_read(&at->sum_exec_runtime);
+	store_samples(samples, stime, utime, rtime);
+}
+
 /*
  * Set cputime to sum_cputime if sum_cputime > cputime. Use cmpxchg
  * to avoid race conditions with concurrent updates to cputime.



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 26/38] posix-cpu-timers: Make expiry checks array based
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (23 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 25/38] posix-cpu-timers: Provide array based sample functions Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-23 22:44   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 27/38] posix-cpu-timers: Remove cputime_expires Thomas Gleixner
                   ` (13 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

The expiry cache is an array indexed by clock ids. The new sample functions
allow to retrieve a corresponding array of samples.

Convert the fastpath expiry checks to make use of the new sample functions
and do the comparisons on the sample and the expiry array.

Make the check for the expiry array being zero array based as well.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/posix-cpu-timers.c |   85 +++++++++++++++++------------------------
 1 file changed, 36 insertions(+), 49 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -39,7 +39,7 @@ void posix_cputimers_group_init(struct p
 
 /*
  * Called after updating RLIMIT_CPU to run cpu timer and update
- * tsk->signal->posix_cputimers.cputime_expires expiration cache if
+ * tsk->signal->posix_cputimers.expiries expiration cache if
  * necessary. Needs siglock protection since other code may update
  * expiration cache as well.
  */
@@ -132,19 +132,9 @@ static void bump_cpu_timer(struct k_itim
 	}
 }
 
-/**
- * task_cputime_zero - Check a task_cputime struct for all zero fields.
- *
- * @cputime:	The struct to compare.
- *
- * Checks @cputime to see if all fields are zero.  Returns true if all fields
- * are zero, false if any field is nonzero.
- */
-static inline int task_cputime_zero(const struct task_cputime *cputime)
+static inline bool expiry_cache_is_zero(const u64 *ec)
 {
-	if (!cputime->utime && !cputime->stime && !cputime->sum_exec_runtime)
-		return 1;
-	return 0;
+	return !(ec[CPUCLOCK_PROF] | ec[CPUCLOCK_VIRT] | ec[CPUCLOCK_SCHED]);
 }
 
 static int
@@ -811,10 +801,10 @@ static void check_thread_timers(struct t
 		check_dl_overrun(tsk);
 
 	/*
-	 * If cputime_expires is zero, then there are no active
-	 * per thread CPU timers.
+	 * If the expiry cache is zero, then there are no active per thread
+	 * CPU timers.
 	 */
-	if (task_cputime_zero(&tsk->posix_cputimers.cputime_expires))
+	if (expiry_cache_is_zero(tsk->posix_cputimers.expiries))
 		return;
 
 	task_cputime(tsk, &utime, &stime);
@@ -860,7 +850,7 @@ static void check_thread_timers(struct t
 		}
 	}
 
-	if (task_cputime_zero(&tsk->posix_cputimers.cputime_expires))
+	if (expiry_cache_is_zero(tsk->posix_cputimers.expiries))
 		tick_dep_clear_task(tsk, TICK_DEP_BIT_POSIX_TIMER);
 }
 
@@ -983,7 +973,7 @@ static void check_process_timers(struct
 	sig->posix_cputimers.expiries[CPUCLOCK_VIRT] = virt_expires;
 	sig->posix_cputimers.expiries[CPUCLOCK_SCHED] = sched_expires;
 
-	if (task_cputime_zero(&sig->posix_cputimers.cputime_expires))
+	if (expiry_cache_is_zero(sig->posix_cputimers.expiries))
 		stop_process_timers(sig);
 
 	sig->cputimer.checking_timer = false;
@@ -1048,26 +1038,23 @@ static void posix_cpu_timer_rearm(struct
 }
 
 /**
- * task_cputime_expired - Compare two task_cputime entities.
+ * task_cputimers_expired - Compare two task_cputime entities.
  *
- * @sample:	The task_cputime structure to be checked for expiration.
- * @expires:	Expiration times, against which @sample will be checked.
+ * @samples:	Array of current samples for the CPUCLOCK clocks
+ * @expiries:	Array of expiry values for the CPUCLOCK clocks
  *
- * Checks @sample against @expires to see if any field of @sample has expired.
- * Returns true if any field of the former is greater than the corresponding
- * field of the latter if the latter field is set.  Otherwise returns false.
+ * Returns true if any mmember of @samples is greater than the corresponding
+ * member of @expiries if that member is non zero. False otherwise
  */
-static inline int task_cputime_expired(const struct task_cputime *sample,
-					const struct task_cputime *expires)
+static inline bool task_cputimers_expired(const u64 *sample, const u64 *expiries)
 {
-	if (expires->utime && sample->utime >= expires->utime)
-		return 1;
-	if (expires->stime && sample->utime + sample->stime >= expires->stime)
-		return 1;
-	if (expires->sum_exec_runtime != 0 &&
-	    sample->sum_exec_runtime >= expires->sum_exec_runtime)
-		return 1;
-	return 0;
+	int i;
+
+	for (i = 0; i < CPUCLOCK_MAX; i++) {
+		if (expiries[i] && sample[i] >= expiries[i])
+			return true;
+	}
+	return false;
 }
 
 /**
@@ -1080,18 +1067,17 @@ static inline int task_cputime_expired(c
  * timers and compare them with the corresponding expiration times.  Return
  * true if a timer has expired, else return false.
  */
-static inline int fastpath_timer_check(struct task_struct *tsk)
+static inline bool fastpath_timer_check(struct task_struct *tsk)
 {
+	u64 *expiries = tsk->posix_cputimers.expiries;
 	struct signal_struct *sig;
 
-	if (!task_cputime_zero(&tsk->posix_cputimers.cputime_expires)) {
-		struct task_cputime task_sample;
+	if (!expiry_cache_is_zero(expiries)) {
+		u64 samples[CPUCLOCK_MAX];
 
-		task_cputime(tsk, &task_sample.utime, &task_sample.stime);
-		task_sample.sum_exec_runtime = tsk->se.sum_exec_runtime;
-		if (task_cputime_expired(&task_sample,
-					 &tsk->posix_cputimers.cputime_expires))
-			return 1;
+		task_sample_cputime(tsk, samples);
+		if (task_cputimers_expired(samples, expiries))
+			return true;
 	}
 
 	sig = tsk->signal;
@@ -1111,19 +1097,20 @@ static inline int fastpath_timer_check(s
 	 */
 	if (READ_ONCE(sig->cputimer.running) &&
 	    !READ_ONCE(sig->cputimer.checking_timer)) {
-		struct task_cputime group_sample;
+		u64 samples[CPUCLOCK_MAX];
 
-		sample_cputime_atomic(&group_sample, &sig->cputimer.cputime_atomic);
+		proc_sample_cputime_atomic(&sig->cputimer.cputime_atomic,
+					   samples);
 
-		if (task_cputime_expired(&group_sample,
-					 &sig->posix_cputimers.cputime_expires))
-			return 1;
+		if (task_cputimers_expired(samples,
+					   sig->posix_cputimers.expiries))
+			return true;
 	}
 
 	if (dl_task(tsk) && tsk->dl.dl_overrun)
-		return 1;
+		return true;
 
-	return 0;
+	return false;
 }
 
 /*



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 27/38] posix-cpu-timers: Remove cputime_expires
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (24 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 26/38] posix-cpu-timers: Make expiry checks array based Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-23 22:50   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 28/38] posix-cpu-timers: Restructure expiry array Thomas Gleixner
                   ` (12 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

The last users of the magic struct cputime based expiry cache are
gone. Remove the leftovers.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/posix-timers.h   |    9 ++-------
 kernel/time/posix-cpu-timers.c |   10 ----------
 2 files changed, 2 insertions(+), 17 deletions(-)

--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -65,19 +65,14 @@ static inline int clockid_to_fd(const cl
 #ifdef CONFIG_POSIX_TIMERS
 /**
  * posix_cputimers - Container for posix CPU timer related data
- * @cputime_expires:	Earliest-expiration cache task_cputime based
  * @expiries:		Earliest-expiration cache array based
  * @cpu_timers:		List heads to queue posix CPU timers
  *
  * Used in task_struct and signal_struct
  */
 struct posix_cputimers {
-	/* Temporary union until all users are cleaned up */
-	union {
-		struct task_cputime	cputime_expires;
-		u64			expiries[CPUCLOCK_MAX];
-	};
-	struct list_head		cpu_timers[CPUCLOCK_MAX];
+	u64			expiries[CPUCLOCK_MAX];
+	struct list_head	cpu_timers[CPUCLOCK_MAX];
 };
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -18,16 +18,6 @@
 
 #include "posix-timers.h"
 
-static inline void temporary_check(void)
-{
-	BUILD_BUG_ON(offsetof(struct task_cputime, stime) !=
-		     CPUCLOCK_PROF * sizeof(u64));
-	BUILD_BUG_ON(offsetof(struct task_cputime, utime) !=
-		     CPUCLOCK_VIRT * sizeof(u64));
-	BUILD_BUG_ON(offsetof(struct task_cputime, sum_exec_runtime) !=
-		     CPUCLOCK_SCHED * sizeof(u64));
-}
-
 static void posix_cpu_timer_rearm(struct k_itimer *timer);
 
 void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit)



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 28/38] posix-cpu-timers: Restructure expiry array
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (25 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 27/38] posix-cpu-timers: Remove cputime_expires Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-26 16:32   ` Frederic Weisbecker
  2019-08-26 21:06   ` [patch V2 28/38] " Frederic Weisbecker
  2019-08-21 19:09 ` [patch V2 29/38] posix-cpu-timers: Switch thread group sampling to array Thomas Gleixner
                   ` (11 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Now that the abused struct task_cputime is gone, it's more natural to
bundle the expiry cache and the list head of each clock into a struct and
have an array of those structs.

Follow the hrtimer naming convention of 'bases' and rename the expiry cache
to 'nextevt' and adapt all usage sites.

Generates also better code .text size shrinks by 80 bytes.

Suggested-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: New patch
---
 include/linux/posix-timers.h   |   41 ++++++++++------
 kernel/time/posix-cpu-timers.c |  104 +++++++++++++++++++++--------------------
 2 files changed, 82 insertions(+), 63 deletions(-)

--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -63,24 +63,33 @@ static inline int clockid_to_fd(const cl
 }
 
 #ifdef CONFIG_POSIX_TIMERS
+
 /**
- * posix_cputimers - Container for posix CPU timer related data
- * @expiries:		Earliest-expiration cache array based
+ * posix_cputimer_base - Container per posix CPU clock
+ * @nextevt:		Earliest-expiration cache
  * @cpu_timers:		List heads to queue posix CPU timers
+ */
+struct posix_cputimer_base {
+	u64			nextevt;
+	struct list_head	cpu_timers;
+};
+
+/**
+ * posix_cputimers - Container for posix CPU timer related data
+ * @bases:		Base container for posix CPU clocks
  *
  * Used in task_struct and signal_struct
  */
 struct posix_cputimers {
-	u64			expiries[CPUCLOCK_MAX];
-	struct list_head	cpu_timers[CPUCLOCK_MAX];
+	struct posix_cputimer_base	bases[CPUCLOCK_MAX];
 };
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
 {
-	memset(&pct->expiries, 0, sizeof(pct->expiries));
-	INIT_LIST_HEAD(&pct->cpu_timers[0]);
-	INIT_LIST_HEAD(&pct->cpu_timers[1]);
-	INIT_LIST_HEAD(&pct->cpu_timers[2]);
+	memset(pct->bases, 0, sizeof(pct->bases));
+	INIT_LIST_HEAD(&pct->bases[0].cpu_timers);
+	INIT_LIST_HEAD(&pct->bases[1].cpu_timers);
+	INIT_LIST_HEAD(&pct->bases[2].cpu_timers);
 }
 
 void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit);
@@ -88,19 +97,23 @@ void posix_cputimers_group_init(struct p
 static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct,
 					       u64 runtime)
 {
-	pct->expiries[CPUCLOCK_SCHED] = runtime;
+	pct->bases[CPUCLOCK_SCHED].nextevt = runtime;
 }
 
 /* Init task static initializer */
-#define INIT_CPU_TIMERLISTS(c)	{					\
-	LIST_HEAD_INIT(c.cpu_timers[0]),				\
-	LIST_HEAD_INIT(c.cpu_timers[1]),				\
-	LIST_HEAD_INIT(c.cpu_timers[2]),				\
+#define INIT_CPU_TIMERBASE(b) {						\
+	.cpu_timers = LIST_HEAD_INIT(b.cpu_timers),			\
+}
+
+#define INIT_CPU_TIMERBASES(b) {					\
+	INIT_CPU_TIMERBASE(b[0]),					\
+	INIT_CPU_TIMERBASE(b[1]),					\
+	INIT_CPU_TIMERBASE(b[2]),					\
 }
 
 #define INIT_CPU_TIMERS(s)						\
 	.posix_cputimers = {						\
-		.cpu_timers = INIT_CPU_TIMERLISTS(s.posix_cputimers),	\
+		.bases = INIT_CPU_TIMERBASES(s.posix_cputimers.bases),	\
 	},
 #else
 struct posix_cputimers { };
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -24,13 +24,13 @@ void posix_cputimers_group_init(struct p
 {
 	posix_cputimers_init(pct);
 	if (cpu_limit != RLIM_INFINITY)
-		pct->expiries[CPUCLOCK_PROF] = cpu_limit * NSEC_PER_SEC;
+		pct->bases[CPUCLOCK_PROF].nextevt = cpu_limit * NSEC_PER_SEC;
 }
 
 /*
  * Called after updating RLIMIT_CPU to run cpu timer and update
- * tsk->signal->posix_cputimers.expiries expiration cache if
- * necessary. Needs siglock protection since other code may update
+ * tsk->signal->posix_cputimers.bases[clock].nextevt expiration cache if
+ * necessary. Needs siglock protection since other code may update the
  * expiration cache as well.
  */
 void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new)
@@ -122,9 +122,11 @@ static void bump_cpu_timer(struct k_itim
 	}
 }
 
-static inline bool expiry_cache_is_zero(const u64 *ec)
+static inline bool expiry_cache_is_zero(const struct posix_cputimers *pct)
 {
-	return !(ec[CPUCLOCK_PROF] | ec[CPUCLOCK_VIRT] | ec[CPUCLOCK_SCHED]);
+	return !(pct->bases[CPUCLOCK_PROF].nextevt |
+		 pct->bases[CPUCLOCK_VIRT].nextevt |
+		 pct->bases[CPUCLOCK_SCHED].nextevt);
 }
 
 static int
@@ -432,9 +434,9 @@ static void cleanup_timers_list(struct l
  */
 static void cleanup_timers(struct posix_cputimers *pct)
 {
-	cleanup_timers_list(&pct->cpu_timers[CPUCLOCK_PROF]);
-	cleanup_timers_list(&pct->cpu_timers[CPUCLOCK_VIRT]);
-	cleanup_timers_list(&pct->cpu_timers[CPUCLOCK_SCHED]);
+	cleanup_timers_list(&pct->bases[CPUCLOCK_PROF].cpu_timers);
+	cleanup_timers_list(&pct->bases[CPUCLOCK_VIRT].cpu_timers);
+	cleanup_timers_list(&pct->bases[CPUCLOCK_SCHED].cpu_timers);
 }
 
 /*
@@ -464,21 +466,19 @@ static void arm_timer(struct k_itimer *t
 {
 	struct cpu_timer_list *const nt = &timer->it.cpu;
 	int clkidx = CPUCLOCK_WHICH(timer->it_clock);
-	u64 *cpuexp, newexp = timer->it.cpu.expires;
 	struct task_struct *p = timer->it.cpu.task;
+	u64 newexp = timer->it.cpu.expires;
+	struct posix_cputimer_base *base;
 	struct list_head *head, *listpos;
 	struct cpu_timer_list *next;
 
-	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		head = p->posix_cputimers.cpu_timers + clkidx;
-		cpuexp = p->posix_cputimers.expiries + clkidx;
-	} else {
-		head = p->signal->posix_cputimers.cpu_timers + clkidx;
-		cpuexp = p->signal->posix_cputimers.expiries + clkidx;
-	}
+	if (CPUCLOCK_PERTHREAD(timer->it_clock))
+		base = p->posix_cputimers.bases + clkidx;
+	else
+		base = p->signal->posix_cputimers.bases + clkidx;
 
-	listpos = head;
-	list_for_each_entry(next, head, entry) {
+	listpos = head = &base->cpu_timers;
+	list_for_each_entry(next,head, entry) {
 		if (nt->expires < next->expires)
 			break;
 		listpos = &next->entry;
@@ -494,8 +494,8 @@ static void arm_timer(struct k_itimer *t
 	 * for process timers we share expiration cache with itimers
 	 * and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME.
 	 */
-	if (expires_gt(*cpuexp, newexp))
-		*cpuexp = newexp;
+	if (expires_gt(base->nextevt, newexp))
+		base->nextevt = newexp;
 
 	if (CPUCLOCK_PERTHREAD(timer->it_clock))
 		tick_dep_set_task(p, TICK_DEP_BIT_POSIX_TIMER);
@@ -783,9 +783,9 @@ static inline void check_dl_overrun(stru
 static void check_thread_timers(struct task_struct *tsk,
 				struct list_head *firing)
 {
-	struct list_head *timers = tsk->posix_cputimers.cpu_timers;
-	u64 stime, utime, *expires = tsk->posix_cputimers.expiries;
+	struct posix_cputimer_base *base = tsk->posix_cputimers.bases;
 	unsigned long soft;
+	u64 stime, utime;
 
 	if (dl_task(tsk))
 		check_dl_overrun(tsk);
@@ -794,14 +794,18 @@ static void check_thread_timers(struct t
 	 * If the expiry cache is zero, then there are no active per thread
 	 * CPU timers.
 	 */
-	if (expiry_cache_is_zero(tsk->posix_cputimers.expiries))
+	if (expiry_cache_is_zero(&tsk->posix_cputimers))
 		return;
 
 	task_cputime(tsk, &utime, &stime);
 
-	*expires++ = check_timers_list(timers, firing, utime + stime);
-	*expires++ = check_timers_list(++timers, firing, utime);
-	*expires = check_timers_list(++timers, firing, tsk->se.sum_exec_runtime);
+	base->nextevt = check_timers_list(&base->cpu_timers, firing,
+					  utime + stime);
+	base++;
+	base->nextevt = check_timers_list(&base->cpu_timers, firing, utime);
+	base++;
+	base->nextevt = check_timers_list(&base->cpu_timers, firing,
+					  tsk->se.sum_exec_runtime);
 
 	/*
 	 * Check for the special case thread timers.
@@ -840,7 +844,7 @@ static void check_thread_timers(struct t
 		}
 	}
 
-	if (expiry_cache_is_zero(tsk->posix_cputimers.expiries))
+	if (expiry_cache_is_zero(&tsk->posix_cputimers))
 		tick_dep_clear_task(tsk, TICK_DEP_BIT_POSIX_TIMER);
 }
 
@@ -884,7 +888,7 @@ static void check_process_timers(struct
 				 struct list_head *firing)
 {
 	struct signal_struct *const sig = tsk->signal;
-	struct list_head *timers = sig->posix_cputimers.cpu_timers;
+	struct posix_cputimer_base *base = sig->posix_cputimers.bases;
 	u64 utime, ptime, virt_expires, prof_expires;
 	u64 sum_sched_runtime, sched_expires;
 	struct task_cputime cputime;
@@ -912,9 +916,12 @@ static void check_process_timers(struct
 	ptime = utime + cputime.stime;
 	sum_sched_runtime = cputime.sum_exec_runtime;
 
-	prof_expires = check_timers_list(timers, firing, ptime);
-	virt_expires = check_timers_list(++timers, firing, utime);
-	sched_expires = check_timers_list(++timers, firing, sum_sched_runtime);
+	prof_expires = check_timers_list(&base[CPUCLOCK_PROF].cpu_timers,
+					 firing, ptime);
+	virt_expires = check_timers_list(&base[CPUCLOCK_VIRT].cpu_timers,
+					 firing, utime);
+	sched_expires = check_timers_list(&base[CLPCLOCK_SCHED].cpu_timers,
+					  firing, sum_sched_runtime);
 
 	/*
 	 * Check for the special case process timers.
@@ -959,11 +966,11 @@ static void check_process_timers(struct
 			prof_expires = x;
 	}
 
-	sig->posix_cputimers.expiries[CPUCLOCK_PROF] = prof_expires;
-	sig->posix_cputimers.expiries[CPUCLOCK_VIRT] = virt_expires;
-	sig->posix_cputimers.expiries[CPUCLOCK_SCHED] = sched_expires;
+	base[CPUCLOCK_PROF].nextevt = prof_expires;
+	base[CPUCLOCK_VIRT].nextevt = virt_expires;
+	base[CPUCLOCK_SCHED].nextevt = sched_expires;
 
-	if (expiry_cache_is_zero(sig->posix_cputimers.expiries))
+	if (expiry_cache_is_zero(&sig->posix_cputimers))
 		stop_process_timers(sig);
 
 	sig->cputimer.checking_timer = false;
@@ -1028,20 +1035,21 @@ static void posix_cpu_timer_rearm(struct
 }
 
 /**
- * task_cputimers_expired - Compare two task_cputime entities.
+ * task_cputimers_expired - Check whether posix CPU timers are expired
  *
  * @samples:	Array of current samples for the CPUCLOCK clocks
- * @expiries:	Array of expiry values for the CPUCLOCK clocks
+ * @pct:	Pointer to a posix_cputimers container
  *
- * Returns true if any mmember of @samples is greater than the corresponding
- * member of @expiries if that member is non zero. False otherwise
+ * Returns true if any member of @samples is greater than the corresponding
+ * member of @pct->bases[CLK].nextevt. False otherwise
  */
-static inline bool task_cputimers_expired(const u64 *sample, const u64 *expiries)
+static inline bool
+task_cputimers_expired(const u64 *sample, struct posix_cputimers *pct)
 {
 	int i;
 
 	for (i = 0; i < CPUCLOCK_MAX; i++) {
-		if (expiries[i] && sample[i] >= expiries[i])
+		if (sample[i] >= pct->bases[i].nextevt)
 			return true;
 	}
 	return false;
@@ -1059,14 +1067,13 @@ static inline bool task_cputimers_expire
  */
 static inline bool fastpath_timer_check(struct task_struct *tsk)
 {
-	u64 *expiries = tsk->posix_cputimers.expiries;
 	struct signal_struct *sig;
 
-	if (!expiry_cache_is_zero(expiries)) {
+	if (!expiry_cache_is_zero(&tsk->posix_cputimers)) {
 		u64 samples[CPUCLOCK_MAX];
 
 		task_sample_cputime(tsk, samples);
-		if (task_cputimers_expired(samples, expiries))
+		if (task_cputimers_expired(samples, &tsk->posix_cputimers))
 			return true;
 	}
 
@@ -1092,8 +1099,7 @@ static inline bool fastpath_timer_check(
 		proc_sample_cputime_atomic(&sig->cputimer.cputime_atomic,
 					   samples);
 
-		if (task_cputimers_expired(samples,
-					   sig->posix_cputimers.expiries))
+		if (task_cputimers_expired(samples, &sig->posix_cputimers))
 			return true;
 	}
 
@@ -1176,7 +1182,7 @@ void run_posix_cpu_timers(void)
 void set_process_cpu_timer(struct task_struct *tsk, unsigned int clkid,
 			   u64 *newval, u64 *oldval)
 {
-	u64 now, *expiry = tsk->signal->posix_cputimers.expiries + clkid;
+	u64 now, *nextevt = &tsk->signal->posix_cputimers.bases[clkid].nextevt;
 
 	if (WARN_ON_ONCE(clkid >= CPUCLOCK_SCHED))
 		return;
@@ -1207,8 +1213,8 @@ void set_process_cpu_timer(struct task_s
 	 * Update expiration cache if this is the earliest timer. CPUCLOCK_PROF
 	 * expiry cache is also used by RLIMIT_CPU!.
 	 */
-	if (expires_gt(*expiry, *newval))
-		*expiry = *newval;
+	if (expires_gt(*nextevt, *newval))
+		*nextevt = *newval;
 
 	tick_dep_set_signal(tsk->signal, TICK_DEP_BIT_POSIX_TIMER);
 }



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 29/38] posix-cpu-timers: Switch thread group sampling to array
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (26 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 28/38] posix-cpu-timers: Restructure expiry array Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-26 21:12   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 30/38] posix-cpu-timers: Respect INFINITY for hard RTTIME limit Thomas Gleixner
                   ` (10 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

That allows more simplifications in various places.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Adopt to the per clock base struct
---
 include/linux/sched/cputime.h  |    2 
 kernel/time/itimer.c           |   11 +---
 kernel/time/posix-cpu-timers.c |  104 +++++++++++++++++------------------------
 3 files changed, 49 insertions(+), 68 deletions(-)

--- a/include/linux/sched/cputime.h
+++ b/include/linux/sched/cputime.h
@@ -61,7 +61,7 @@ extern void cputime_adjust(struct task_c
  * Thread group CPU time accounting.
  */
 void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times);
-void thread_group_sample_cputime(struct task_struct *tsk, struct task_cputime *times);
+void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples);
 
 /*
  * The following are functions that support scheduler-internal time accounting.
--- a/kernel/time/itimer.c
+++ b/kernel/time/itimer.c
@@ -55,15 +55,10 @@ static void get_cpu_itimer(struct task_s
 	val = it->expires;
 	interval = it->incr;
 	if (val) {
-		struct task_cputime cputime;
-		u64 t;
+		u64 t, samples[CPUCLOCK_MAX];
 
-		thread_group_sample_cputime(tsk, &cputime);
-		if (clock_id == CPUCLOCK_PROF)
-			t = cputime.utime + cputime.stime;
-		else
-			/* CPUCLOCK_VIRT */
-			t = cputime.utime;
+		thread_group_sample_cputime(tsk, samples);
+		t = samples[clock_id];
 
 		if (val < t)
 			/* about to fire */
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -225,22 +225,14 @@ static inline void __update_gt_cputime(a
 	}
 }
 
-static void update_gt_cputime(struct task_cputime_atomic *cputime_atomic, struct task_cputime *sum)
+static void update_gt_cputime(struct task_cputime_atomic *cputime_atomic,
+			      struct task_cputime *sum)
 {
 	__update_gt_cputime(&cputime_atomic->utime, sum->utime);
 	__update_gt_cputime(&cputime_atomic->stime, sum->stime);
 	__update_gt_cputime(&cputime_atomic->sum_exec_runtime, sum->sum_exec_runtime);
 }
 
-/* Sample task_cputime_atomic values in "atomic_timers", store results in "times". */
-static inline void sample_cputime_atomic(struct task_cputime *times,
-					 struct task_cputime_atomic *atomic_times)
-{
-	times->utime = atomic64_read(&atomic_times->utime);
-	times->stime = atomic64_read(&atomic_times->stime);
-	times->sum_exec_runtime = atomic64_read(&atomic_times->sum_exec_runtime);
-}
-
 /**
  * thread_group_sample_cputime - Sample cputime for a given task
  * @tsk:	Task for which cputime needs to be started
@@ -252,20 +244,19 @@ static inline void sample_cputime_atomic
  *
  * Updates @times with an uptodate sample of the thread group cputimes.
  */
-void thread_group_sample_cputime(struct task_struct *tsk,
-				struct task_cputime *times)
+void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples)
 {
 	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
 
 	WARN_ON_ONCE(!cputimer->running);
 
-	sample_cputime_atomic(times, &cputimer->cputime_atomic);
+	proc_sample_cputime_atomic(&cputimer->cputime_atomic, samples);
 }
 
 /**
  * thread_group_start_cputime - Start cputime and return a sample
  * @tsk:	Task for which cputime needs to be started
- * @iimes:	Storage for time samples
+ * @samples:	Storage for time samples
  *
  * The thread group cputime accouting is avoided when there are no posix
  * CPU timers armed. Before starting a timer it's required to check whether
@@ -274,14 +265,14 @@ void thread_group_sample_cputime(struct
  *
  * Updates @times with an uptodate sample of the thread group cputimes.
  */
-static void
-thread_group_start_cputime(struct task_struct *tsk, struct task_cputime *times)
+static void thread_group_start_cputime(struct task_struct *tsk, u64 *samples)
 {
 	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
-	struct task_cputime sum;
 
 	/* Check if cputimer isn't running. This is accessed without locking. */
 	if (!READ_ONCE(cputimer->running)) {
+		struct task_cputime sum;
+
 		/*
 		 * The POSIX timer interface allows for absolute time expiry
 		 * values through the TIMER_ABSTIME flag, therefore we have
@@ -299,7 +290,15 @@ thread_group_start_cputime(struct task_s
 		 */
 		WRITE_ONCE(cputimer->running, true);
 	}
-	sample_cputime_atomic(times, &cputimer->cputime_atomic);
+	proc_sample_cputime_atomic(&cputimer->cputime_atomic, samples);
+}
+
+static void __thread_group_cputime(struct task_struct *tsk, u64 *samples)
+{
+	struct task_cputime ct;
+
+	thread_group_cputime(tsk, &ct);
+	store_samples(samples, ct.stime, ct.utime, ct.sum_exec_runtime);
 }
 
 /*
@@ -313,28 +312,18 @@ static u64 cpu_clock_sample_group(const
 				  bool start)
 {
 	struct thread_group_cputimer *cputimer = &p->signal->cputimer;
-	struct task_cputime cputime;
+	u64 samples[CPUCLOCK_MAX];
 
 	if (!READ_ONCE(cputimer->running)) {
 		if (start)
-			thread_group_start_cputime(p, &cputime);
+			thread_group_start_cputime(p, samples);
 		else
-			thread_group_cputime(p, &cputime);
+			__thread_group_cputime(p, samples);
 	} else {
-		sample_cputime_atomic(&cputime, &cputimer->cputime_atomic);
+		proc_sample_cputime_atomic(&cputimer->cputime_atomic, samples);
 	}
 
-	switch (clkid) {
-	case CPUCLOCK_PROF:
-		return cputime.utime + cputime.stime;
-	case CPUCLOCK_VIRT:
-		return cputime.utime;
-	case CPUCLOCK_SCHED:
-		return cputime.sum_exec_runtime;
-	default:
-		WARN_ON_ONCE(1);
-	}
-	return 0;
+	return samples[clkid];
 }
 
 static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)
@@ -889,9 +878,7 @@ static void check_process_timers(struct
 {
 	struct signal_struct *const sig = tsk->signal;
 	struct posix_cputimer_base *base = sig->posix_cputimers.bases;
-	u64 utime, ptime, virt_expires, prof_expires;
-	u64 sum_sched_runtime, sched_expires;
-	struct task_cputime cputime;
+	u64 virt_exp, prof_exp, sched_exp, samples[CPUCLOCK_MAX];
 	unsigned long soft;
 
 	/*
@@ -911,30 +898,29 @@ static void check_process_timers(struct
 	 * Collect the current process totals. Group accounting is active
 	 * so the sample can be taken directly.
 	 */
-	sample_cputime_atomic(&cputime, &sig->cputimer.cputime_atomic);
-	utime = cputime.utime;
-	ptime = utime + cputime.stime;
-	sum_sched_runtime = cputime.sum_exec_runtime;
-
-	prof_expires = check_timers_list(&base[CPUCLOCK_PROF].cpu_timers,
-					 firing, ptime);
-	virt_expires = check_timers_list(&base[CPUCLOCK_VIRT].cpu_timers,
-					 firing, utime);
-	sched_expires = check_timers_list(&base[CLPCLOCK_SCHED].cpu_timers,
-					  firing, sum_sched_runtime);
+	proc_sample_cputime_atomic(&sig->cputimer.cputime_atomic, samples);
+
+	prof_exp = check_timers_list(&base[CPUCLOCK_PROF].cpu_timers,
+				     firing, samples[CPUCLOCK_PROF]);
+	virt_exp = check_timers_list(&base[CPUCLOCK_VIRT].cpu_timers,
+				     firing, samples[CPUCLOCK_VIRT]);
+	sched_exp = check_timers_list(&base[CPUCLOCK_SCHED].cpu_timers,
+				      firing, samples[CPUCLOCK_SCHED]);
 
 	/*
 	 * Check for the special case process timers.
 	 */
-	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_PROF], &prof_expires, ptime,
-			 SIGPROF);
-	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_VIRT], &virt_expires, utime,
-			 SIGVTALRM);
+	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_PROF], &prof_exp,
+			 samples[CPUCLOCK_PROF], SIGPROF);
+	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_VIRT], &virt_exp,
+			 samples[CPUCLOCK_PROF], SIGVTALRM);
+
 	soft = task_rlimit(tsk, RLIMIT_CPU);
 	if (soft != RLIM_INFINITY) {
-		unsigned long psecs = div_u64(ptime, NSEC_PER_SEC);
+		u64 softns, ptime = samples[CPUCLOCK_PROF];
 		unsigned long hard = task_rlimit_max(tsk, RLIMIT_CPU);
-		u64 x;
+		unsigned long psecs = div_u64(ptime, NSEC_PER_SEC);
+
 		if (psecs >= hard) {
 			/*
 			 * At the hard limit, we just die.
@@ -961,14 +947,14 @@ static void check_process_timers(struct
 				sig->rlim[RLIMIT_CPU].rlim_cur = soft;
 			}
 		}
-		x = soft * NSEC_PER_SEC;
-		if (!prof_expires || x < prof_expires)
-			prof_expires = x;
+		softns = soft * NSEC_PER_SEC;
+		if (!prof_exp || softns < prof_exp)
+			prof_exp = softns;
 	}
 
-	base[CPUCLOCK_PROF].nextevt = prof_expires;
-	base[CPUCLOCK_VIRT].nextevt = virt_expires;
-	base[CPUCLOCK_SCHED].nextevt = sched_expires;
+	base[CPUCLOCK_PROF].nextevt = prof_exp;
+	base[CPUCLOCK_VIRT].nextevt = virt_exp;
+	base[CPUCLOCK_SCHED].nextevt = sched_exp;
 
 	if (expiry_cache_is_zero(&sig->posix_cputimers))
 		stop_process_timers(sig);



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 30/38] posix-cpu-timers: Respect INFINITY for hard RTTIME limit
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (27 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 29/38] posix-cpu-timers: Switch thread group sampling to array Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-26 21:19   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 31/38] rlimit: Rewrite non-sensical RLIMIT_CPU comment Thomas Gleixner
                   ` (9 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

The RTIME limit expiry code does not check the hard RTTIME limit for
INFINITY, i.e. being disabled.  Add it.

While this could be considered an ABI breakage if something would depend on
this behaviour. Though it's highly unlikely to have an effect because
RLIM_INFINITY is at minimum INT_MAX and the RTTIME limit is in seconds, so
the timer would fire after ~68 years.

Adding this obvious correct limit check also allows further consolidation
of that code and is a prerequisite for cleaning up the 0 based checks and
the rlimit setter code.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Documented the theoretical ABI breakage in the changelong
---
 kernel/time/posix-cpu-timers.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -921,7 +921,7 @@ static void check_process_timers(struct
 		unsigned long hard = task_rlimit_max(tsk, RLIMIT_CPU);
 		unsigned long psecs = div_u64(ptime, NSEC_PER_SEC);
 
-		if (psecs >= hard) {
+		if (hard != RLIM_INFINITY && psecs >= hard) {
 			/*
 			 * At the hard limit, we just die.
 			 * No need to calculate anything else now.



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 31/38] rlimit: Rewrite non-sensical RLIMIT_CPU comment
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (28 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 30/38] posix-cpu-timers: Respect INFINITY for hard RTTIME limit Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-26 21:41   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 32/38] posix-cpu-timers: Get rid of zero checks Thomas Gleixner
                   ` (8 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig,
	Andrew Morton, Jiri Slaby

The comment above the function which arms RLIMIT_CPU in the posix CPU timer
code makes no sense at all. It claims that the kernel does not return an
error code when it rejected the attempt to set RLIMIT_CPU. That's clearly
bogus as the code does an error check and the rlimit is only set and
activated when the permission checks are ok. In case of a rejection an
appropriate error code is returned.

This is a historical and outdated comment which got dragged along even when
the rlimit handling code was rewritten.

Replace it with an explanation why the setup function is not called when
the rlimit value is RLIM_INFINITY and how the 'disarming' is handled.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
---
 kernel/sys.c |    7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1576,10 +1576,9 @@ int do_prlimit(struct task_struct *tsk,
 	task_unlock(tsk->group_leader);
 
 	/*
-	 * RLIMIT_CPU handling.   Note that the kernel fails to return an error
-	 * code if it rejected the user's attempt to set RLIMIT_CPU.  This is a
-	 * very long-standing error, and fixing it now risks breakage of
-	 * applications, so we live with it
+	 * RLIMIT_CPU handling. Arm the posix CPU timer if the limit is not
+	 * infite. In case of RLIM_INFINITY the posix CPU timer code
+	 * ignores the rlimit.
 	 */
 	 if (!retval && new_rlim && resource == RLIMIT_CPU &&
 	     new_rlim->rlim_cur != RLIM_INFINITY &&



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 32/38] posix-cpu-timers: Get rid of zero checks
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (29 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 31/38] rlimit: Rewrite non-sensical RLIMIT_CPU comment Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-26 21:57   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 33/38] posix-cpu-timers: Consolidate timer expiry further Thomas Gleixner
                   ` (7 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Deactivation of the expiry cache is done by setting all clock caches to
0. That requires to have a check for zero in all places which update the
expiry cache:

	if (cache == 0 || new < cache)
		cache = new;

Use U64_MAX as the deactivated value, which allows to remove the zero
checks when updating the cache and reduces it to the obvious check:

	if (new < cache)
		cache = new;

This also removes the weird workaround in do_prlimit() which was required
to convert a RLIMIT_CPU value of 0 (immediate expiry) to 1 because handing
in 0 to the posix CPU timer code would have effectively disarmed it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Adopt to the per clock base struct and cleanup the rlimit setter code.
---
 include/linux/posix-timers.h   |    7 +++++--
 kernel/sys.c                   |    9 ---------
 kernel/time/posix-cpu-timers.c |   36 ++++++++++++++----------------------
 3 files changed, 19 insertions(+), 33 deletions(-)

--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -86,7 +86,9 @@ struct posix_cputimers {
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
 {
-	memset(pct->bases, 0, sizeof(pct->bases));
+	pct->bases[0].nextevt = U64_MAX;
+	pct->bases[1].nextevt = U64_MAX;
+	pct->bases[2].nextevt = U64_MAX;
 	INIT_LIST_HEAD(&pct->bases[0].cpu_timers);
 	INIT_LIST_HEAD(&pct->bases[1].cpu_timers);
 	INIT_LIST_HEAD(&pct->bases[2].cpu_timers);
@@ -102,7 +104,8 @@ static inline void posix_cputimers_rt_wa
 
 /* Init task static initializer */
 #define INIT_CPU_TIMERBASE(b) {						\
-	.cpu_timers = LIST_HEAD_INIT(b.cpu_timers),			\
+	.nextevt	= U64_MAX,					\
+	.cpu_timers	= LIST_HEAD_INIT(b.cpu_timers),			\
 }
 
 #define INIT_CPU_TIMERBASES(b) {					\
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1557,15 +1557,6 @@ int do_prlimit(struct task_struct *tsk,
 			retval = -EPERM;
 		if (!retval)
 			retval = security_task_setrlimit(tsk, resource, new_rlim);
-		if (resource == RLIMIT_CPU && new_rlim->rlim_cur == 0) {
-			/*
-			 * The caller is asking for an immediate RLIMIT_CPU
-			 * expiry.  But we use the zero value to mean "it was
-			 * never set".  So let's cheat and make it one second
-			 * instead
-			 */
-			new_rlim->rlim_cur = 1;
-		}
 	}
 	if (!retval) {
 		if (old_rlim)
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -122,11 +122,12 @@ static void bump_cpu_timer(struct k_itim
 	}
 }
 
-static inline bool expiry_cache_is_zero(const struct posix_cputimers *pct)
+/* Check whether all cache entries contain U64_MAX, i.e. eternal expiry time */
+static inline bool expiry_cache_is_inactive(const struct posix_cputimers *pct)
 {
-	return !(pct->bases[CPUCLOCK_PROF].nextevt |
-		 pct->bases[CPUCLOCK_VIRT].nextevt |
-		 pct->bases[CPUCLOCK_SCHED].nextevt);
+	return !(~pct->bases[CPUCLOCK_PROF].nextevt |
+		 ~pct->bases[CPUCLOCK_VIRT].nextevt |
+		 ~pct->bases[CPUCLOCK_SCHED].nextevt);
 }
 
 static int
@@ -442,11 +443,6 @@ void posix_cpu_timers_exit_group(struct
 	cleanup_timers(&tsk->signal->posix_cputimers);
 }
 
-static inline int expires_gt(u64 expires, u64 new_exp)
-{
-	return expires == 0 || expires > new_exp;
-}
-
 /*
  * Insert the timer on the appropriate list before any timers that
  * expire later.  This must be called with the sighand lock held.
@@ -483,7 +479,7 @@ static void arm_timer(struct k_itimer *t
 	 * for process timers we share expiration cache with itimers
 	 * and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME.
 	 */
-	if (expires_gt(base->nextevt, newexp))
+	if (newexp < base->nextevt)
 		base->nextevt = newexp;
 
 	if (CPUCLOCK_PERTHREAD(timer->it_clock))
@@ -753,7 +749,7 @@ check_timers_list(struct list_head *time
 		list_move_tail(&t->entry, firing);
 	}
 
-	return 0;
+	return U64_MAX;
 }
 
 static inline void check_dl_overrun(struct task_struct *tsk)
@@ -779,11 +775,7 @@ static void check_thread_timers(struct t
 	if (dl_task(tsk))
 		check_dl_overrun(tsk);
 
-	/*
-	 * If the expiry cache is zero, then there are no active per thread
-	 * CPU timers.
-	 */
-	if (expiry_cache_is_zero(&tsk->posix_cputimers))
+	if (expiry_cache_is_inactive(&tsk->posix_cputimers))
 		return;
 
 	task_cputime(tsk, &utime, &stime);
@@ -833,7 +825,7 @@ static void check_thread_timers(struct t
 		}
 	}
 
-	if (expiry_cache_is_zero(&tsk->posix_cputimers))
+	if (expiry_cache_is_inactive(&tsk->posix_cputimers))
 		tick_dep_clear_task(tsk, TICK_DEP_BIT_POSIX_TIMER);
 }
 
@@ -864,7 +856,7 @@ static void check_cpu_itimer(struct task
 		__group_send_sig_info(signo, SEND_SIG_PRIV, tsk);
 	}
 
-	if (it->expires && (!*expires || it->expires < *expires))
+	if (it->expires && it->expires < *expires)
 		*expires = it->expires;
 }
 
@@ -948,7 +940,7 @@ static void check_process_timers(struct
 			}
 		}
 		softns = soft * NSEC_PER_SEC;
-		if (!prof_exp || softns < prof_exp)
+		if (softns < prof_exp)
 			prof_exp = softns;
 	}
 
@@ -956,7 +948,7 @@ static void check_process_timers(struct
 	base[CPUCLOCK_VIRT].nextevt = virt_exp;
 	base[CPUCLOCK_SCHED].nextevt = sched_exp;
 
-	if (expiry_cache_is_zero(&sig->posix_cputimers))
+	if (expiry_cache_is_inactive(&sig->posix_cputimers))
 		stop_process_timers(sig);
 
 	sig->cputimer.checking_timer = false;
@@ -1055,7 +1047,7 @@ static inline bool fastpath_timer_check(
 {
 	struct signal_struct *sig;
 
-	if (!expiry_cache_is_zero(&tsk->posix_cputimers)) {
+	if (!expiry_cache_is_inactive(&tsk->posix_cputimers)) {
 		u64 samples[CPUCLOCK_MAX];
 
 		task_sample_cputime(tsk, samples);
@@ -1199,7 +1191,7 @@ void set_process_cpu_timer(struct task_s
 	 * Update expiration cache if this is the earliest timer. CPUCLOCK_PROF
 	 * expiry cache is also used by RLIMIT_CPU!.
 	 */
-	if (expires_gt(*nextevt, *newval))
+	if (*newval < *nextevt)
 		*nextevt = *newval;
 
 	tick_dep_set_signal(tsk->signal, TICK_DEP_BIT_POSIX_TIMER);



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 33/38] posix-cpu-timers: Consolidate timer expiry further
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (30 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 32/38] posix-cpu-timers: Get rid of zero checks Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-26 22:29   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 34/38] posix-cpu-timers: Get rid of 64bit divisions Thomas Gleixner
                   ` (6 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

With the array based samples and expiry cache, the expiry function can use
a loop to collect timers from the clock specific lists.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Adopt to the per clock base struct
---
 kernel/time/posix-cpu-timers.c |   63 +++++++++++++++++++----------------------
 1 file changed, 30 insertions(+), 33 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -752,6 +752,18 @@ check_timers_list(struct list_head *time
 	return U64_MAX;
 }
 
+static void collect_posix_cputimers(struct posix_cputimers *pct,
+				    u64 *samples, struct list_head *firing)
+{
+	struct posix_cputimer_base *base = pct->bases;
+	int i;
+
+	for (i = 0; i < CPUCLOCK_MAX; i++, base++) {
+		base->nextevt = check_timers_list(&base->cpu_timers, firing,
+						   samples[i]);
+	}
+}
+
 static inline void check_dl_overrun(struct task_struct *tsk)
 {
 	if (tsk->dl.dl_overrun) {
@@ -768,25 +780,18 @@ static inline void check_dl_overrun(stru
 static void check_thread_timers(struct task_struct *tsk,
 				struct list_head *firing)
 {
-	struct posix_cputimer_base *base = tsk->posix_cputimers.bases;
+	struct posix_cputimers *pct = &tsk->posix_cputimers;
+	u64 samples[CPUCLOCK_MAX];
 	unsigned long soft;
-	u64 stime, utime;
 
 	if (dl_task(tsk))
 		check_dl_overrun(tsk);
 
-	if (expiry_cache_is_inactive(&tsk->posix_cputimers))
+	if (expiry_cache_is_inactive(pct))
 		return;
 
-	task_cputime(tsk, &utime, &stime);
-
-	base->nextevt = check_timers_list(&base->cpu_timers, firing,
-					  utime + stime);
-	base++;
-	base->nextevt = check_timers_list(&base->cpu_timers, firing, utime);
-	base++;
-	base->nextevt = check_timers_list(&base->cpu_timers, firing,
-					  tsk->se.sum_exec_runtime);
+	task_sample_cputime(tsk, samples);
+	collect_posix_cputimers(pct, samples, firing);
 
 	/*
 	 * Check for the special case thread timers.
@@ -825,7 +830,7 @@ static void check_thread_timers(struct t
 		}
 	}
 
-	if (expiry_cache_is_inactive(&tsk->posix_cputimers))
+	if (expiry_cache_is_inactive(pct))
 		tick_dep_clear_task(tsk, TICK_DEP_BIT_POSIX_TIMER);
 }
 
@@ -869,15 +874,15 @@ static void check_process_timers(struct
 				 struct list_head *firing)
 {
 	struct signal_struct *const sig = tsk->signal;
-	struct posix_cputimer_base *base = sig->posix_cputimers.bases;
-	u64 virt_exp, prof_exp, sched_exp, samples[CPUCLOCK_MAX];
+	struct posix_cputimers *pct = &sig->posix_cputimers;
+	u64 samples[CPUCLOCK_MAX];
 	unsigned long soft;
 
 	/*
 	 * If cputimer is not running, then there are no active
 	 * process wide timers (POSIX 1.b, itimers, RLIMIT_CPU).
 	 */
-	if (!READ_ONCE(tsk->signal->cputimer.running))
+	if (!READ_ONCE(sig->cputimer.running))
 		return;
 
        /*
@@ -891,21 +896,17 @@ static void check_process_timers(struct
 	 * so the sample can be taken directly.
 	 */
 	proc_sample_cputime_atomic(&sig->cputimer.cputime_atomic, samples);
-
-	prof_exp = check_timers_list(&base[CPUCLOCK_PROF].cpu_timers,
-				     firing, samples[CPUCLOCK_PROF]);
-	virt_exp = check_timers_list(&base[CPUCLOCK_VIRT].cpu_timers,
-				     firing, samples[CPUCLOCK_VIRT]);
-	sched_exp = check_timers_list(&base[CPUCLOCK_SCHED].cpu_timers,
-				      firing, samples[CPUCLOCK_SCHED]);
+	collect_posix_cputimers(pct, samples, firing);
 
 	/*
 	 * Check for the special case process timers.
 	 */
-	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_PROF], &prof_exp,
+	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_PROF],
+			 &pct->bases[CPUCLOCK_PROF].nextevt,
 			 samples[CPUCLOCK_PROF], SIGPROF);
-	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_VIRT], &virt_exp,
-			 samples[CPUCLOCK_PROF], SIGVTALRM);
+	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_VIRT],
+			 &pct->bases[CPUCLOCK_VIRT].nextevt,
+			 samples[CPUCLOCK_VIRT], SIGVTALRM);
 
 	soft = task_rlimit(tsk, RLIMIT_CPU);
 	if (soft != RLIM_INFINITY) {
@@ -940,15 +941,11 @@ static void check_process_timers(struct
 			}
 		}
 		softns = soft * NSEC_PER_SEC;
-		if (softns < prof_exp)
-			prof_exp = softns;
+		if (softns < pct->bases[CPUCLOCK_PROF].nextevt)
+			pct->bases[CPUCLOCK_PROF].nextevt = softns;
 	}
 
-	base[CPUCLOCK_PROF].nextevt = prof_exp;
-	base[CPUCLOCK_VIRT].nextevt = virt_exp;
-	base[CPUCLOCK_SCHED].nextevt = sched_exp;
-
-	if (expiry_cache_is_inactive(&sig->posix_cputimers))
+	if (expiry_cache_is_inactive(pct))
 		stop_process_timers(sig);
 
 	sig->cputimer.checking_timer = false;



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 34/38] posix-cpu-timers: Get rid of 64bit divisions
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (31 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 33/38] posix-cpu-timers: Consolidate timer expiry further Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-26 22:51   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 35/38] posix-cpu-timers: Remove pointless comparisons Thomas Gleixner
                   ` (5 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Instead of dividing A to match the units of B it's more efficient to
multiply B to match the units of A.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Fix the dropped update of the expiry cache when the soft limit increased
---
 kernel/time/posix-cpu-timers.c |   24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -798,10 +798,11 @@ static void check_thread_timers(struct t
 	 */
 	soft = task_rlimit(tsk, RLIMIT_RTTIME);
 	if (soft != RLIM_INFINITY) {
+		/* Task RT timeout is accounted in jiffies. RTTIME is usec */
+		unsigned long rtim = tsk->rt.timeout * (USEC_PER_SEC / HZ);
 		unsigned long hard = task_rlimit_max(tsk, RLIMIT_RTTIME);
 
-		if (hard != RLIM_INFINITY &&
-		    tsk->rt.timeout > DIV_ROUND_UP(hard, USEC_PER_SEC/HZ)) {
+		if (hard != RLIM_INFINITY && rtim >= hard) {
 			/*
 			 * At the hard limit, we just die.
 			 * No need to calculate anything else now.
@@ -813,7 +814,7 @@ static void check_thread_timers(struct t
 			__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
 			return;
 		}
-		if (tsk->rt.timeout > DIV_ROUND_UP(soft, USEC_PER_SEC/HZ)) {
+		if (rtim >= soft) {
 			/*
 			 * At the soft limit, send a SIGXCPU every second.
 			 */
@@ -910,11 +911,13 @@ static void check_process_timers(struct
 
 	soft = task_rlimit(tsk, RLIMIT_CPU);
 	if (soft != RLIM_INFINITY) {
-		u64 softns, ptime = samples[CPUCLOCK_PROF];
+		/* RLIMIT_CPU is in seconds. Samples are nanoseconds */
 		unsigned long hard = task_rlimit_max(tsk, RLIMIT_CPU);
-		unsigned long psecs = div_u64(ptime, NSEC_PER_SEC);
+		u64 ptime = samples[CPUCLOCK_PROF];
+		u64 softns = (u64)soft * NSEC_PER_SEC;
+		u64 hardns = (u64)hard * NSEC_PER_SEC;
 
-		if (hard != RLIM_INFINITY && psecs >= hard) {
+		if (hard != RLIM_INFINITY && ptime >= hardns) {
 			/*
 			 * At the hard limit, we just die.
 			 * No need to calculate anything else now.
@@ -926,7 +929,7 @@ static void check_process_timers(struct
 			__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
 			return;
 		}
-		if (psecs >= soft) {
+		if (ptime >= softns) {
 			/*
 			 * At the soft limit, send a SIGXCPU every second.
 			 */
@@ -936,11 +939,12 @@ static void check_process_timers(struct
 			}
 			__group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
 			if (soft < hard) {
-				soft++;
-				sig->rlim[RLIMIT_CPU].rlim_cur = soft;
+				sig->rlim[RLIMIT_CPU].rlim_cur = soft + 1;
+				softns += NSEC_PER_SEC;
 			}
 		}
-		softns = soft * NSEC_PER_SEC;
+
+		/* Update the expiry cache */
 		if (softns < pct->bases[CPUCLOCK_PROF].nextevt)
 			pct->bases[CPUCLOCK_PROF].nextevt = softns;
 	}



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 35/38] posix-cpu-timers: Remove pointless comparisons
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (32 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 34/38] posix-cpu-timers: Get rid of 64bit divisions Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-26 22:59   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 36/38] posix-cpu-timers: Deduplicate rlimit handling Thomas Gleixner
                   ` (4 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

The soft RLIMIT expiry code checks whether the soft limit is greater than
the hard limit. That's pointless because if the soft RLIMIT is greater than
the hard RLIMIT then that code cannot be reached as the hard RLIMIT check
is before that and already killed the process.

Remove it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Fixup vs. the previous patch changes
---
 kernel/time/posix-cpu-timers.c |   16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -814,15 +814,14 @@ static void check_thread_timers(struct t
 			__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
 			return;
 		}
+
 		if (rtim >= soft) {
 			/*
 			 * At the soft limit, send a SIGXCPU every second.
 			 */
-			if (soft < hard) {
-				soft += USEC_PER_SEC;
-				tsk->signal->rlim[RLIMIT_RTTIME].rlim_cur =
-					soft;
-			}
+			soft += USEC_PER_SEC;
+			tsk->signal->rlim[RLIMIT_RTTIME].rlim_cur = soft;
+
 			if (print_fatal_signals) {
 				pr_info("RT Watchdog Timeout (soft): %s[%d]\n",
 					tsk->comm, task_pid_nr(tsk));
@@ -938,10 +937,9 @@ static void check_process_timers(struct
 					tsk->comm, task_pid_nr(tsk));
 			}
 			__group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
-			if (soft < hard) {
-				sig->rlim[RLIMIT_CPU].rlim_cur = soft + 1;
-				softns += NSEC_PER_SEC;
-			}
+
+			sig->rlim[RLIMIT_CPU].rlim_cur = soft + 1;
+			softns += NSEC_PER_SEC;
 		}
 
 		/* Update the expiry cache */



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 36/38] posix-cpu-timers: Deduplicate rlimit handling
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (33 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 35/38] posix-cpu-timers: Remove pointless comparisons Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-26 23:13   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 37/38] posix-cpu-timers: Move state tracking to struct posix_cputimers Thomas Gleixner
                   ` (3 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Both thread and process expiry functions have the same functionality for
sending signals for soft and hard RLIMITs duplicated in 4 different
ways.

Split it out into a common function and cleanup the callsites.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Restore the dropped (u64) casts
---
 kernel/time/posix-cpu-timers.c |   67 +++++++++++++++--------------------------
 1 file changed, 25 insertions(+), 42 deletions(-)

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -772,6 +772,20 @@ static inline void check_dl_overrun(stru
 	}
 }
 
+static bool check_rlimit(u64 time, u64 limit, int signo, bool rt, bool hard)
+{
+	if (time < limit)
+		return false;
+
+	if (print_fatal_signals) {
+		pr_info("%s Watchdog Timeout (%s): %s[%d]\n",
+			rt ? "RT" : "CPU", hard ? "hard" : "soft",
+			current->comm, task_pid_nr(current));
+	}
+	__group_send_sig_info(signo, SEND_SIG_PRIV, current);
+	return true;
+}
+
 /*
  * 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
@@ -799,34 +813,18 @@ static void check_thread_timers(struct t
 	soft = task_rlimit(tsk, RLIMIT_RTTIME);
 	if (soft != RLIM_INFINITY) {
 		/* Task RT timeout is accounted in jiffies. RTTIME is usec */
-		unsigned long rtim = tsk->rt.timeout * (USEC_PER_SEC / HZ);
+		unsigned long rttime = tsk->rt.timeout * (USEC_PER_SEC / HZ);
 		unsigned long hard = task_rlimit_max(tsk, RLIMIT_RTTIME);
 
-		if (hard != RLIM_INFINITY && rtim >= hard) {
-			/*
-			 * At the hard limit, we just die.
-			 * No need to calculate anything else now.
-			 */
-			if (print_fatal_signals) {
-				pr_info("CPU Watchdog Timeout (hard): %s[%d]\n",
-					tsk->comm, task_pid_nr(tsk));
-			}
-			__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
+		/* At the hard limit, send SIGKILL. No further action. */
+		if (hard != RLIM_INFINITY &&
+		    check_rlimit(rttime, hard, SIGKILL, true, true))
 			return;
-		}
 
-		if (rtim >= soft) {
-			/*
-			 * At the soft limit, send a SIGXCPU every second.
-			 */
+		/* At the soft limit, send a SIGXCPU every second */
+		if (check_rlimit(rttime, soft, SIGXCPU, true, false)) {
 			soft += USEC_PER_SEC;
 			tsk->signal->rlim[RLIMIT_RTTIME].rlim_cur = soft;
-
-			if (print_fatal_signals) {
-				pr_info("RT Watchdog Timeout (soft): %s[%d]\n",
-					tsk->comm, task_pid_nr(tsk));
-			}
-			__group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
 		}
 	}
 
@@ -916,28 +914,13 @@ static void check_process_timers(struct
 		u64 softns = (u64)soft * NSEC_PER_SEC;
 		u64 hardns = (u64)hard * NSEC_PER_SEC;
 
-		if (hard != RLIM_INFINITY && ptime >= hardns) {
-			/*
-			 * At the hard limit, we just die.
-			 * No need to calculate anything else now.
-			 */
-			if (print_fatal_signals) {
-				pr_info("RT Watchdog Timeout (hard): %s[%d]\n",
-					tsk->comm, task_pid_nr(tsk));
-			}
-			__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
+		/* At the hard limit, send SIGKILL. No further action. */
+		if (hard != RLIM_INFINITY &&
+		    check_rlimit(ptime, hardns, SIGKILL, false, true))
 			return;
-		}
-		if (ptime >= softns) {
-			/*
-			 * At the soft limit, send a SIGXCPU every second.
-			 */
-			if (print_fatal_signals) {
-				pr_info("CPU Watchdog Timeout (soft): %s[%d]\n",
-					tsk->comm, task_pid_nr(tsk));
-			}
-			__group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
 
+		/* At the soft limit, send a SIGXCPU every second */
+		if (check_rlimit(ptime, softns, SIGXCPU, false, false)) {
 			sig->rlim[RLIMIT_CPU].rlim_cur = soft + 1;
 			softns += NSEC_PER_SEC;
 		}



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 37/38] posix-cpu-timers: Move state tracking to struct posix_cputimers
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (34 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 36/38] posix-cpu-timers: Deduplicate rlimit handling Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-26 23:28   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-21 19:09 ` [patch V2 38/38] posix-cpu-timers: Utilize timerqueue for storage Thomas Gleixner
                   ` (2 subsequent siblings)
  38 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Put it where it belongs and clean up the ifdeffery in fork completely.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Adopt to the per clock base struct
---
 include/linux/posix-timers.h   |    8 ++++
 include/linux/sched/cputime.h  |    9 +++--
 include/linux/sched/signal.h   |    6 ---
 init/init_task.c               |    2 -
 kernel/fork.c                  |    6 ---
 kernel/time/posix-cpu-timers.c |   73 ++++++++++++++++++++++-------------------
 6 files changed, 54 insertions(+), 50 deletions(-)

--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -77,15 +77,23 @@ struct posix_cputimer_base {
 /**
  * posix_cputimers - Container for posix CPU timer related data
  * @bases:		Base container for posix CPU clocks
+ * @timers_active:	Timers are queued.
+ * @expiry_active:	Timer expiry is active. Used for
+ *			process wide timers to avoid multiple
+ *			task trying to handle expiry concurrently
  *
  * Used in task_struct and signal_struct
  */
 struct posix_cputimers {
 	struct posix_cputimer_base	bases[CPUCLOCK_MAX];
+	unsigned int			timers_active;
+	unsigned int			expiry_active;
 };
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
 {
+	pct->timers_active = 0;
+	pct->expiry_active = 0;
 	pct->bases[0].nextevt = U64_MAX;
 	pct->bases[1].nextevt = U64_MAX;
 	pct->bases[2].nextevt = U64_MAX;
--- a/include/linux/sched/cputime.h
+++ b/include/linux/sched/cputime.h
@@ -70,7 +70,7 @@ void thread_group_sample_cputime(struct
  */
 
 /**
- * get_running_cputimer - return &tsk->signal->cputimer if cputimer is running
+ * get_running_cputimer - return &tsk->signal->cputimer if cputimers are active
  *
  * @tsk:	Pointer to target task.
  */
@@ -80,8 +80,11 @@ struct thread_group_cputimer *get_runnin
 {
 	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
 
-	/* Check if cputimer isn't running. This is accessed without locking. */
-	if (!READ_ONCE(cputimer->running))
+	/*
+	 * Check whether posix CPU timers are active. If not the thread
+	 * group accounting is not active either. Lockless check.
+	 */
+	if (!READ_ONCE(tsk->signal->posix_cputimers.timers_active))
 		return NULL;
 
 	/*
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -57,18 +57,12 @@ struct task_cputime_atomic {
 /**
  * struct thread_group_cputimer - thread group interval timer counts
  * @cputime_atomic:	atomic thread group interval timers.
- * @running:		true when there are timers running and
- *			@cputime_atomic receives updates.
- * @checking_timer:	true when a thread in the group is in the
- *			process of checking for thread group timers.
  *
  * This structure contains the version of task_cputime, above, that is
  * used for thread group CPU timer calculations.
  */
 struct thread_group_cputimer {
 	struct task_cputime_atomic cputime_atomic;
-	bool running;
-	bool checking_timer;
 };
 
 struct multiprocess_signals {
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -30,8 +30,6 @@ static struct signal_struct init_signals
 	.posix_timers = LIST_HEAD_INIT(init_signals.posix_timers),
 	.cputimer	= {
 		.cputime_atomic	= INIT_CPUTIME_ATOMIC,
-		.running	= false,
-		.checking_timer = false,
 	},
 #endif
 	INIT_CPU_TIMERS(init_signals)
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1517,7 +1517,6 @@ void __cleanup_sighand(struct sighand_st
 	}
 }
 
-#ifdef CONFIG_POSIX_TIMERS
 /*
  * Initialize POSIX timer handling for a thread group.
  */
@@ -1528,12 +1527,7 @@ static void posix_cpu_timers_init_group(
 
 	cpu_limit = READ_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur);
 	posix_cputimers_group_init(pct, cpu_limit);
-	if (cpu_limit != RLIM_INFINITY)
-		sig->cputimer.running = true;
 }
-#else
-static inline void posix_cpu_timers_init_group(struct signal_struct *sig) { }
-#endif
 
 static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
 {
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -23,8 +23,10 @@ static void posix_cpu_timer_rearm(struct
 void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit)
 {
 	posix_cputimers_init(pct);
-	if (cpu_limit != RLIM_INFINITY)
+	if (cpu_limit != RLIM_INFINITY) {
 		pct->bases[CPUCLOCK_PROF].nextevt = cpu_limit * NSEC_PER_SEC;
+		pct->timers_active = true;
+	}
 }
 
 /*
@@ -248,8 +250,9 @@ static void update_gt_cputime(struct tas
 void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples)
 {
 	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
+	struct posix_cputimers *pct = &tsk->signal->posix_cputimers;
 
-	WARN_ON_ONCE(!cputimer->running);
+	WARN_ON_ONCE(!pct->timers_active);
 
 	proc_sample_cputime_atomic(&cputimer->cputime_atomic, samples);
 }
@@ -269,9 +272,10 @@ void thread_group_sample_cputime(struct
 static void thread_group_start_cputime(struct task_struct *tsk, u64 *samples)
 {
 	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
+	struct posix_cputimers *pct = &tsk->signal->posix_cputimers;
 
 	/* Check if cputimer isn't running. This is accessed without locking. */
-	if (!READ_ONCE(cputimer->running)) {
+	if (!READ_ONCE(pct->timers_active)) {
 		struct task_cputime sum;
 
 		/*
@@ -283,13 +287,13 @@ static void thread_group_start_cputime(s
 		update_gt_cputime(&cputimer->cputime_atomic, &sum);
 
 		/*
-		 * We're setting cputimer->running without a lock. Ensure
-		 * this only gets written to in one operation. We set
-		 * running after update_gt_cputime() as a small optimization,
-		 * but barriers are not required because update_gt_cputime()
+		 * We're setting timers_active without a lock. Ensure this
+		 * only gets written to in one operation. We set it after
+		 * update_gt_cputime() as a small optimization, but
+		 * barriers are not required because update_gt_cputime()
 		 * can handle concurrent updates.
 		 */
-		WRITE_ONCE(cputimer->running, true);
+		WRITE_ONCE(pct->timers_active, true);
 	}
 	proc_sample_cputime_atomic(&cputimer->cputime_atomic, samples);
 }
@@ -313,9 +317,10 @@ static u64 cpu_clock_sample_group(const
 				  bool start)
 {
 	struct thread_group_cputimer *cputimer = &p->signal->cputimer;
+	struct posix_cputimers *pct = &p->signal->posix_cputimers;
 	u64 samples[CPUCLOCK_MAX];
 
-	if (!READ_ONCE(cputimer->running)) {
+	if (!READ_ONCE(pct->timers_active)) {
 		if (start)
 			thread_group_start_cputime(p, samples);
 		else
@@ -834,10 +839,10 @@ static void check_thread_timers(struct t
 
 static inline void stop_process_timers(struct signal_struct *sig)
 {
-	struct thread_group_cputimer *cputimer = &sig->cputimer;
+	struct posix_cputimers *pct = &sig->posix_cputimers;
 
-	/* Turn off cputimer->running. This is done without locking. */
-	WRITE_ONCE(cputimer->running, false);
+	/* Turn off the active flag. This is done without locking. */
+	WRITE_ONCE(pct->timers_active, false);
 	tick_dep_clear_signal(sig, TICK_DEP_BIT_POSIX_TIMER);
 }
 
@@ -877,17 +882,17 @@ static void check_process_timers(struct
 	unsigned long soft;
 
 	/*
-	 * If cputimer is not running, then there are no active
-	 * process wide timers (POSIX 1.b, itimers, RLIMIT_CPU).
+	 * If there are no active process wide timers (POSIX 1.b, itimers,
+	 * RLIMIT_CPU) nothing to check.
 	 */
-	if (!READ_ONCE(sig->cputimer.running))
+	if (!READ_ONCE(pct->timers_active))
 		return;
 
        /*
 	 * Signify that a thread is checking for process timers.
 	 * Write access to this field is protected by the sighand lock.
 	 */
-	sig->cputimer.checking_timer = true;
+	pct->timers_active = true;
 
 	/*
 	 * Collect the current process totals. Group accounting is active
@@ -933,7 +938,7 @@ static void check_process_timers(struct
 	if (expiry_cache_is_inactive(pct))
 		stop_process_timers(sig);
 
-	sig->cputimer.checking_timer = false;
+	pct->expiry_active = false;
 }
 
 /*
@@ -1027,39 +1032,41 @@ task_cputimers_expired(const u64 *sample
  */
 static inline bool fastpath_timer_check(struct task_struct *tsk)
 {
+	struct posix_cputimers *pct = &tsk->posix_cputimers;
 	struct signal_struct *sig;
 
-	if (!expiry_cache_is_inactive(&tsk->posix_cputimers)) {
+	if (!expiry_cache_is_inactive(pct)) {
 		u64 samples[CPUCLOCK_MAX];
 
 		task_sample_cputime(tsk, samples);
-		if (task_cputimers_expired(samples, &tsk->posix_cputimers))
+		if (task_cputimers_expired(samples, pct))
 			return true;
 	}
 
 	sig = tsk->signal;
+	pct = &sig->posix_cputimers;
 	/*
-	 * Check if thread group timers expired when the cputimer is
-	 * running and no other thread in the group is already checking
-	 * for thread group cputimers. These fields are read without the
-	 * sighand lock. However, this is fine because this is meant to
-	 * be a fastpath heuristic to determine whether we should try to
-	 * acquire the sighand lock to check/handle timers.
+	 * Check if thread group timers expired when timers are active and
+	 * no other thread in the group is already handling expiry for
+	 * thread group cputimers. These fields are read without the
+	 * sighand lock. However, this is fine because this is meant to be
+	 * a fastpath heuristic to determine whether we should try to
+	 * acquire the sighand lock to handle timer expiry.
 	 *
-	 * In the worst case scenario, if 'running' or 'checking_timer' gets
-	 * set but the current thread doesn't see the change yet, we'll wait
-	 * until the next thread in the group gets a scheduler interrupt to
-	 * handle the timer. This isn't an issue in practice because these
-	 * types of delays with signals actually getting sent are expected.
+	 * In the worst case scenario, if concurrently timers_active is set
+	 * or expiry_active is cleared, but the current thread doesn't see
+	 * the change yet, the timer checks are delayed until the next
+	 * thread in the group gets a scheduler interrupt to handle the
+	 * timer. This isn't an issue in practice because these types of
+	 * delays with signals actually getting sent are expected.
 	 */
-	if (READ_ONCE(sig->cputimer.running) &&
-	    !READ_ONCE(sig->cputimer.checking_timer)) {
+	if (READ_ONCE(pct->timers_active) && !READ_ONCE(pct->expiry_active)) {
 		u64 samples[CPUCLOCK_MAX];
 
 		proc_sample_cputime_atomic(&sig->cputimer.cputime_atomic,
 					   samples);
 
-		if (task_cputimers_expired(samples, &sig->posix_cputimers))
+		if (task_cputimers_expired(samples, pct))
 			return true;
 	}
 



^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V2 38/38] posix-cpu-timers: Utilize timerqueue for storage
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (35 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 37/38] posix-cpu-timers: Move state tracking to struct posix_cputimers Thomas Gleixner
@ 2019-08-21 19:09 ` Thomas Gleixner
  2019-08-27  0:48   ` Frederic Weisbecker
  2019-08-22  0:54 ` [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Christoph Hellwig
       [not found] ` <20190821192920.909530418@linutronix.de>
  38 siblings, 1 reply; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-21 19:09 UTC (permalink / raw)
  To: LKML
  Cc: Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

Using a linear O(N) search for timer insertion affects execution time and
D-cache footprint badly with a larger number of timers.

Switch the storage to a timerqueue which is already used for hrtimers and
alarmtimers. It does not affect the size of struct k_itimer as it.alarm is
still larger.

The extra list head for the expiry list will go away later once the expiry
is moved into task work context.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Adopt to the per clock base struct
---
 include/linux/posix-timers.h   |   65 ++++++++++----
 include/linux/timerqueue.h     |   10 ++
 kernel/time/posix-cpu-timers.c |  183 ++++++++++++++++++++---------------------
 3 files changed, 150 insertions(+), 108 deletions(-)

--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -5,17 +5,11 @@
 #include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/alarmtimer.h>
+#include <linux/timerqueue.h>
 
 struct kernel_siginfo;
 struct task_struct;
 
-struct cpu_timer_list {
-	struct list_head entry;
-	u64 expires;
-	struct task_struct *task;
-	int firing;
-};
-
 /*
  * Bit fields within a clockid:
  *
@@ -65,13 +59,57 @@ static inline int clockid_to_fd(const cl
 #ifdef CONFIG_POSIX_TIMERS
 
 /**
+ * cpu_timer - Posix CPU timer representation for k_itimer
+ * @node:	timerqueue node to queue in the task/sig
+ * @head:	timerqueue head on which this timer is queued
+ * @task:	Pointer to target task
+ * @elist:	List head for the expiry list
+ * @firing:	Timer is currently firing
+ */
+struct cpu_timer {
+	struct timerqueue_node	node;
+	struct timerqueue_head	*head;
+	struct task_struct	*task;
+	struct list_head	elist;
+	int			firing;
+};
+
+static inline bool cpu_timer_requeue(struct cpu_timer *ctmr)
+{
+	return timerqueue_add(ctmr->head, &ctmr->node);
+}
+
+static inline bool cpu_timer_enqueue(struct timerqueue_head *head,
+				     struct cpu_timer *ctmr)
+{
+	ctmr->head = head;
+	return timerqueue_add(head, &ctmr->node);
+}
+
+static inline void cpu_timer_dequeue(struct cpu_timer *ctmr)
+{
+	if (!RB_EMPTY_NODE(&ctmr->node.node))
+		timerqueue_del(ctmr->head, &ctmr->node);
+}
+
+static inline u64 cpu_timer_getexpires(struct cpu_timer *ctmr)
+{
+	return ctmr->node.expires;
+}
+
+static inline void cpu_timer_setexpires(struct cpu_timer *ctmr, u64 exp)
+{
+	ctmr->node.expires = exp;
+}
+
+/**
  * posix_cputimer_base - Container per posix CPU clock
  * @nextevt:		Earliest-expiration cache
- * @cpu_timers:		List heads to queue posix CPU timers
+ * @tqhead:		timerqueue head for cpu_timers
  */
 struct posix_cputimer_base {
 	u64			nextevt;
-	struct list_head	cpu_timers;
+	struct timerqueue_head	tqhead;
 };
 
 /**
@@ -92,14 +130,10 @@ struct posix_cputimers {
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
 {
-	pct->timers_active = 0;
-	pct->expiry_active = 0;
+	memset(pct->bases, 0, sizeof(pct->bases));
 	pct->bases[0].nextevt = U64_MAX;
 	pct->bases[1].nextevt = U64_MAX;
 	pct->bases[2].nextevt = U64_MAX;
-	INIT_LIST_HEAD(&pct->bases[0].cpu_timers);
-	INIT_LIST_HEAD(&pct->bases[1].cpu_timers);
-	INIT_LIST_HEAD(&pct->bases[2].cpu_timers);
 }
 
 void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit);
@@ -113,7 +147,6 @@ static inline void posix_cputimers_rt_wa
 /* Init task static initializer */
 #define INIT_CPU_TIMERBASE(b) {						\
 	.nextevt	= U64_MAX,					\
-	.cpu_timers	= LIST_HEAD_INIT(b.cpu_timers),			\
 }
 
 #define INIT_CPU_TIMERBASES(b) {					\
@@ -182,7 +215,7 @@ struct k_itimer {
 		struct {
 			struct hrtimer	timer;
 		} real;
-		struct cpu_timer_list	cpu;
+		struct cpu_timer	cpu;
 		struct {
 			struct alarm	alarmtimer;
 		} alarm;
--- a/include/linux/timerqueue.h
+++ b/include/linux/timerqueue.h
@@ -43,6 +43,16 @@ static inline void timerqueue_init(struc
 	RB_CLEAR_NODE(&node->node);
 }
 
+static inline bool timerqueue_node_queued(struct timerqueue_node *node)
+{
+	return !RB_EMPTY_NODE(&node->node);
+}
+
+static inline bool timerqueue_node_expires(struct timerqueue_node *node)
+{
+	return node->expires;
+}
+
 static inline void timerqueue_init_head(struct timerqueue_head *head)
 {
 	head->rb_root = RB_ROOT_CACHED;
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -96,19 +96,19 @@ static inline int validate_clock_permiss
  * Update expiry time from increment, and increase overrun count,
  * given the current clock sample.
  */
-static void bump_cpu_timer(struct k_itimer *timer, u64 now)
+static u64 bump_cpu_timer(struct k_itimer *timer, u64 now)
 {
+	u64 delta, incr, expires = timer->it.cpu.node.expires;
 	int i;
-	u64 delta, incr;
 
 	if (!timer->it_interval)
-		return;
+		return expires;
 
-	if (now < timer->it.cpu.expires)
-		return;
+	if (now < expires)
+		return expires;
 
 	incr = timer->it_interval;
-	delta = now + incr - timer->it.cpu.expires;
+	delta = now + incr - expires;
 
 	/* Don't use (incr*2 < delta), incr*2 might overflow. */
 	for (i = 0; incr < delta - incr; i++)
@@ -118,10 +118,11 @@ static void bump_cpu_timer(struct k_itim
 		if (delta < incr)
 			continue;
 
-		timer->it.cpu.expires += incr;
+		timer->it.cpu.node.expires += incr;
 		timer->it_overrun += 1LL << i;
 		delta -= incr;
 	}
+	return timer->it.cpu.node.expires;
 }
 
 /* Check whether all cache entries contain U64_MAX, i.e. eternal expiry time */
@@ -365,7 +366,7 @@ static int posix_cpu_timer_create(struct
 		return -EINVAL;
 
 	new_timer->kclock = &clock_posix_cpu;
-	INIT_LIST_HEAD(&new_timer->it.cpu.entry);
+	timerqueue_init(&new_timer->it.cpu.node);
 	new_timer->it.cpu.task = p;
 	return 0;
 }
@@ -378,10 +379,11 @@ static int posix_cpu_timer_create(struct
  */
 static int posix_cpu_timer_del(struct k_itimer *timer)
 {
-	int ret = 0;
-	unsigned long flags;
+	struct cpu_timer *ctmr = &timer->it.cpu;
+	struct task_struct *p = ctmr->task;
 	struct sighand_struct *sighand;
-	struct task_struct *p = timer->it.cpu.task;
+	unsigned long flags;
+	int ret = 0;
 
 	if (WARN_ON_ONCE(!p))
 		return -EINVAL;
@@ -393,15 +395,15 @@ static int posix_cpu_timer_del(struct k_
 	sighand = lock_task_sighand(p, &flags);
 	if (unlikely(sighand == NULL)) {
 		/*
-		 * We raced with the reaping of the task.
-		 * The deletion should have cleared us off the list.
+		 * This raced with the reaping of the task. The exit cleanup
+		 * should have removed this timer from the timer queue.
 		 */
-		WARN_ON_ONCE(!list_empty(&timer->it.cpu.entry));
+		WARN_ON_ONCE(ctmr->head || timerqueue_node_queued(&ctmr->node));
 	} else {
 		if (timer->it.cpu.firing)
 			ret = TIMER_RETRY;
 		else
-			list_del(&timer->it.cpu.entry);
+			cpu_timer_dequeue(ctmr);
 
 		unlock_task_sighand(p, &flags);
 	}
@@ -412,12 +414,12 @@ static int posix_cpu_timer_del(struct k_
 	return ret;
 }
 
-static void cleanup_timers_list(struct list_head *head)
+static void cleanup_timerqueue(struct timerqueue_head *head)
 {
-	struct cpu_timer_list *timer, *next;
+	struct timerqueue_node *node;
 
-	list_for_each_entry_safe(timer, next, head, entry)
-		list_del_init(&timer->entry);
+	while ((node = timerqueue_getnext(head)))
+		timerqueue_del(head, node);
 }
 
 /*
@@ -429,9 +431,9 @@ static void cleanup_timers_list(struct l
  */
 static void cleanup_timers(struct posix_cputimers *pct)
 {
-	cleanup_timers_list(&pct->bases[CPUCLOCK_PROF].cpu_timers);
-	cleanup_timers_list(&pct->bases[CPUCLOCK_VIRT].cpu_timers);
-	cleanup_timers_list(&pct->bases[CPUCLOCK_SCHED].cpu_timers);
+	cleanup_timerqueue(&pct->bases[CPUCLOCK_PROF].tqhead);
+	cleanup_timerqueue(&pct->bases[CPUCLOCK_VIRT].tqhead);
+	cleanup_timerqueue(&pct->bases[CPUCLOCK_SCHED].tqhead);
 }
 
 /*
@@ -454,28 +456,18 @@ void posix_cpu_timers_exit_group(struct
  */
 static void arm_timer(struct k_itimer *timer)
 {
-	struct cpu_timer_list *const nt = &timer->it.cpu;
 	int clkidx = CPUCLOCK_WHICH(timer->it_clock);
-	struct task_struct *p = timer->it.cpu.task;
-	u64 newexp = timer->it.cpu.expires;
+	struct cpu_timer *ctmr = &timer->it.cpu;
+	u64 newexp = cpu_timer_getexpires(ctmr);
+	struct task_struct *p = ctmr->task;
 	struct posix_cputimer_base *base;
-	struct list_head *head, *listpos;
-	struct cpu_timer_list *next;
 
 	if (CPUCLOCK_PERTHREAD(timer->it_clock))
 		base = p->posix_cputimers.bases + clkidx;
 	else
 		base = p->signal->posix_cputimers.bases + clkidx;
 
-	listpos = head = &base->cpu_timers;
-	list_for_each_entry(next,head, entry) {
-		if (nt->expires < next->expires)
-			break;
-		listpos = &next->entry;
-	}
-	list_add(&nt->entry, listpos);
-
-	if (listpos != head)
+	if (!cpu_timer_enqueue(&base->tqhead, ctmr))
 		return;
 
 	/*
@@ -498,24 +490,26 @@ static void arm_timer(struct k_itimer *t
  */
 static void cpu_timer_fire(struct k_itimer *timer)
 {
+	struct cpu_timer *ctmr = &timer->it.cpu;
+
 	if ((timer->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) {
 		/*
 		 * User don't want any signal.
 		 */
-		timer->it.cpu.expires = 0;
+		cpu_timer_setexpires(ctmr, 0);
 	} else if (unlikely(timer->sigq == NULL)) {
 		/*
 		 * This a special case for clock_nanosleep,
 		 * not a normal timer from sys_timer_create.
 		 */
 		wake_up_process(timer->it_process);
-		timer->it.cpu.expires = 0;
+		cpu_timer_setexpires(ctmr, 0);
 	} else if (!timer->it_interval) {
 		/*
 		 * One-shot timer.  Clear it as soon as it's fired.
 		 */
 		posix_timer_event(timer, 0);
-		timer->it.cpu.expires = 0;
+		cpu_timer_setexpires(ctmr, 0);
 	} else if (posix_timer_event(timer, ++timer->it_requeue_pending)) {
 		/*
 		 * The signal did not get queued because the signal
@@ -539,10 +533,11 @@ static int posix_cpu_timer_set(struct k_
 {
 	clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
 	u64 old_expires, new_expires, old_incr, val;
-	struct task_struct *p = timer->it.cpu.task;
+	struct cpu_timer *ctmr = &timer->it.cpu;
+	struct task_struct *p = ctmr->task;
 	struct sighand_struct *sighand;
 	unsigned long flags;
-	int ret;
+	int ret = 0;
 
 	if (WARN_ON_ONCE(!p))
 		return -EINVAL;
@@ -562,22 +557,21 @@ static int posix_cpu_timer_set(struct k_
 	 * If p has just been reaped, we can no
 	 * longer get any information about it at all.
 	 */
-	if (unlikely(sighand == NULL)) {
+	if (unlikely(sighand == NULL))
 		return -ESRCH;
-	}
 
 	/*
 	 * Disarm any old timer after extracting its expiry time.
 	 */
-
-	ret = 0;
 	old_incr = timer->it_interval;
-	old_expires = timer->it.cpu.expires;
+	old_expires = cpu_timer_getexpires(ctmr);
+
 	if (unlikely(timer->it.cpu.firing)) {
 		timer->it.cpu.firing = -1;
 		ret = TIMER_RETRY;
-	} else
-		list_del_init(&timer->it.cpu.entry);
+	} else {
+		cpu_timer_dequeue(ctmr);
+	}
 
 	/*
 	 * We need to sample the current value to convert the new
@@ -598,18 +592,16 @@ static int posix_cpu_timer_set(struct k_
 			old->it_value.tv_nsec = 0;
 		} else {
 			/*
-			 * Update the timer in case it has
-			 * overrun already.  If it has,
-			 * we'll report it as having overrun
-			 * and with the next reloaded timer
-			 * already ticking, though we are
-			 * swallowing that pending
-			 * notification here to install the
-			 * new setting.
+			 * Update the timer in case it has overrun already.
+			 * If it has, we'll report it as having overrun and
+			 * with the next reloaded timer already ticking,
+			 * though we are swallowing that pending
+			 * notification here to install the new setting.
 			 */
-			bump_cpu_timer(timer, val);
-			if (val < timer->it.cpu.expires) {
-				old_expires = timer->it.cpu.expires - val;
+			u64 exp = bump_cpu_timer(timer, val);
+
+			if (val < exp) {
+				old_expires = exp - val;
 				old->it_value = ns_to_timespec64(old_expires);
 			} else {
 				old->it_value.tv_nsec = 1;
@@ -638,7 +630,7 @@ static int posix_cpu_timer_set(struct k_
 	 * For a timer with no notification action, we don't actually
 	 * arm the timer (we'll just fake it for timer_gettime).
 	 */
-	timer->it.cpu.expires = new_expires;
+	cpu_timer_setexpires(ctmr, new_expires);
 	if (new_expires != 0 && val < new_expires) {
 		arm_timer(timer);
 	}
@@ -680,8 +672,9 @@ static int posix_cpu_timer_set(struct k_
 static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp)
 {
 	clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
-	struct task_struct *p = timer->it.cpu.task;
-	u64 now;
+	struct cpu_timer *ctmr = &timer->it.cpu;
+	u64 now, expires = cpu_timer_getexpires(ctmr);
+	struct task_struct *p = ctmr->task;
 
 	if (WARN_ON_ONCE(!p))
 		return;
@@ -691,7 +684,7 @@ static void posix_cpu_timer_get(struct k
 	 */
 	itp->it_interval = ktime_to_timespec64(timer->it_interval);
 
-	if (!timer->it.cpu.expires)
+	if (!expires)
 		return;
 
 	/*
@@ -713,9 +706,9 @@ static void posix_cpu_timer_get(struct k
 			/*
 			 * The process has been reaped.
 			 * We can't even collect a sample any more.
-			 * Call the timer disarmed, nothing else to do.
+			 * Disarm the timer, nothing else to do.
 			 */
-			timer->it.cpu.expires = 0;
+			cpu_timer_setexpires(ctmr, 0);
 			return;
 		} else {
 			now = cpu_clock_sample_group(clkid, p, false);
@@ -723,8 +716,8 @@ static void posix_cpu_timer_get(struct k
 		}
 	}
 
-	if (now < timer->it.cpu.expires) {
-		itp->it_value = ns_to_timespec64(timer->it.cpu.expires - now);
+	if (now < expires) {
+		itp->it_value = ns_to_timespec64(expires - now);
 	} else {
 		/*
 		 * The timer should have expired already, but the firing
@@ -735,37 +728,41 @@ static void posix_cpu_timer_get(struct k
 	}
 }
 
-static unsigned long long
-check_timers_list(struct list_head *timers,
-		  struct list_head *firing,
-		  unsigned long long curr)
-{
-	int maxfire = 20;
-
-	while (!list_empty(timers)) {
-		struct cpu_timer_list *t;
+#define MAX_COLLECTED	20
 
-		t = list_first_entry(timers, struct cpu_timer_list, entry);
-
-		if (!--maxfire || curr < t->expires)
-			return t->expires;
+static u64 collect_timerqueue(struct timerqueue_head *head,
+			      struct list_head *firing, u64 now)
+{
+	struct timerqueue_node *next;
+	int i = 0;
 
-		t->firing = 1;
-		list_move_tail(&t->entry, firing);
+	while ((next = timerqueue_getnext(head))) {
+		struct cpu_timer *ctmr;
+		u64 expires;
+
+		ctmr = container_of(next, struct cpu_timer, node);
+		expires = cpu_timer_getexpires(ctmr);
+		/* Limit the number of timers to expire at once */
+		if (++i == MAX_COLLECTED || now < expires)
+			return expires;
+
+		ctmr->firing = 1;
+		cpu_timer_dequeue(ctmr);
+		list_add_tail(&ctmr->elist, firing);
 	}
 
 	return U64_MAX;
 }
 
-static void collect_posix_cputimers(struct posix_cputimers *pct,
-				    u64 *samples, struct list_head *firing)
+static void collect_posix_cputimers(struct posix_cputimers *pct, u64 *samples,
+				    struct list_head *firing)
 {
 	struct posix_cputimer_base *base = pct->bases;
 	int i;
 
 	for (i = 0; i < CPUCLOCK_MAX; i++, base++) {
-		base->nextevt = check_timers_list(&base->cpu_timers, firing,
-						   samples[i]);
+		base->nextevt = collect_timerqueue(&base->tqhead, firing,
+						    samples[i]);
 	}
 }
 
@@ -948,7 +945,8 @@ static void check_process_timers(struct
 static void posix_cpu_timer_rearm(struct k_itimer *timer)
 {
 	clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
-	struct task_struct *p = timer->it.cpu.task;
+	struct cpu_timer *ctmr = &timer->it.cpu;
+	struct task_struct *p = ctmr->task;
 	struct sighand_struct *sighand;
 	unsigned long flags;
 	u64 now;
@@ -980,7 +978,7 @@ static void posix_cpu_timer_rearm(struct
 			 * The process has been reaped.
 			 * We can't even collect a sample any more.
 			 */
-			timer->it.cpu.expires = 0;
+			cpu_timer_setexpires(ctmr, 0);
 			return;
 		} else if (unlikely(p->exit_state) && thread_group_empty(p)) {
 			/* If the process is dying, no need to rearm */
@@ -1124,11 +1122,11 @@ void run_posix_cpu_timers(void)
 	 * each timer's lock before clearing its firing flag, so no
 	 * timer call will interfere.
 	 */
-	list_for_each_entry_safe(timer, next, &firing, it.cpu.entry) {
+	list_for_each_entry_safe(timer, next, &firing, it.cpu.elist) {
 		int cpu_firing;
 
 		spin_lock(&timer->it_lock);
-		list_del_init(&timer->it.cpu.entry);
+		list_del_init(&timer->it.cpu.elist);
 		cpu_firing = timer->it.cpu.firing;
 		timer->it.cpu.firing = 0;
 		/*
@@ -1203,6 +1201,7 @@ static int do_cpu_nanosleep(const clocki
 	timer.it_overrun = -1;
 	error = posix_cpu_timer_create(&timer);
 	timer.it_process = current;
+
 	if (!error) {
 		static struct itimerspec64 zero_it;
 		struct restart_block *restart;
@@ -1218,7 +1217,7 @@ static int do_cpu_nanosleep(const clocki
 		}
 
 		while (!signal_pending(current)) {
-			if (timer.it.cpu.expires == 0) {
+			if (!cpu_timer_getexpires(&timer.it.cpu)) {
 				/*
 				 * Our timer fired and was reset, below
 				 * deletion can not fail.
@@ -1240,7 +1239,7 @@ static int do_cpu_nanosleep(const clocki
 		/*
 		 * We were interrupted by a signal.
 		 */
-		expires = timer.it.cpu.expires;
+		expires = cpu_timer_getexpires(&timer.it.cpu);
 		error = posix_cpu_timer_set(&timer, 0, &zero_it, &it);
 		if (!error) {
 			/*



^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 01/38] posix-cpu-timers: Provide task validation functions
  2019-08-21 19:08 ` [patch V2 01/38] posix-cpu-timers: Provide task validation functions Thomas Gleixner
@ 2019-08-21 22:33   ` Frederic Weisbecker
  2019-08-21 23:03     ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 1 reply; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-21 22:33 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:08:48PM +0200, Thomas Gleixner wrote:
> The code contains three slightly different copies of validating whether a
> given clock resolves to a valid task and whether the current caller has
> permissions to access it.
> 
> Create central functions. Replace check_clock() as a first step and rename
> it to something sensible.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
>  kernel/time/posix-cpu-timers.c |   65 +++++++++++++++++++++++++++--------------
>  1 file changed, 44 insertions(+), 21 deletions(-)
> 
> --- a/kernel/time/posix-cpu-timers.c
> +++ b/kernel/time/posix-cpu-timers.c
> @@ -35,27 +35,52 @@ void update_rlimit_cpu(struct task_struc
>  	spin_unlock_irq(&task->sighand->siglock);
>  }
>  
> -static int check_clock(const clockid_t which_clock)
> +/*
> + * Functions for validating access to tasks.
> + */
> +static struct task_struct *lookup_task(const pid_t pid, bool thread)
>  {
> -	int error = 0;
>  	struct task_struct *p;
> -	const pid_t pid = CPUCLOCK_PID(which_clock);
>  
> -	if (CPUCLOCK_WHICH(which_clock) >= CPUCLOCK_MAX)
> -		return -EINVAL;
> +	if (!pid)
> +		return thread ? current : current->group_leader;
>  
> -	if (pid == 0)
> -		return 0;
> +	p = find_task_by_vpid(pid);
> +	if (!p || p == current)
> +		return p;

What if (p == current && !thread && !has_group_leader_pid(p)) ?

> +	if (thread)
> +		return same_thread_group(p, current) ? p : NULL;
> +	if (p == current)
> +		return p;

You already checked that above.

> +	return has_group_leader_pid(p) ? p : NULL;
> +}

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 01/38] posix-cpu-timers: Provide task validation functions
  2019-08-21 22:33   ` Frederic Weisbecker
@ 2019-08-21 23:03     ` Frederic Weisbecker
  2019-08-23 15:33       ` Thomas Gleixner
  0 siblings, 1 reply; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-21 23:03 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Thu, Aug 22, 2019 at 12:33:56AM +0200, Frederic Weisbecker wrote:
> On Wed, Aug 21, 2019 at 09:08:48PM +0200, Thomas Gleixner wrote:
> > The code contains three slightly different copies of validating whether a
> > given clock resolves to a valid task and whether the current caller has
> > permissions to access it.
> > 
> > Create central functions. Replace check_clock() as a first step and rename
> > it to something sensible.
> > 
> > Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> > ---
> >  kernel/time/posix-cpu-timers.c |   65 +++++++++++++++++++++++++++--------------
> >  1 file changed, 44 insertions(+), 21 deletions(-)
> > 
> > --- a/kernel/time/posix-cpu-timers.c
> > +++ b/kernel/time/posix-cpu-timers.c
> > @@ -35,27 +35,52 @@ void update_rlimit_cpu(struct task_struc
> >  	spin_unlock_irq(&task->sighand->siglock);
> >  }
> >  
> > -static int check_clock(const clockid_t which_clock)
> > +/*
> > + * Functions for validating access to tasks.
> > + */
> > +static struct task_struct *lookup_task(const pid_t pid, bool thread)
> >  {
> > -	int error = 0;
> >  	struct task_struct *p;
> > -	const pid_t pid = CPUCLOCK_PID(which_clock);
> >  
> > -	if (CPUCLOCK_WHICH(which_clock) >= CPUCLOCK_MAX)
> > -		return -EINVAL;
> > +	if (!pid)
> > +		return thread ? current : current->group_leader;
> >  
> > -	if (pid == 0)
> > -		return 0;
> > +	p = find_task_by_vpid(pid);
> > +	if (!p || p == current)
> > +		return p;
> 
> What if (p == current && !thread && !has_group_leader_pid(p)) ?

Ah looking at the next patch, posix_cpu_clock_get_task() and posix_cpu_clock_getres()
had different ad-hoc checks for this specific case.

clock_getres() used to return -EINVAL while clock_get() doesn't care. They certainly should
agree in their behaviour. I'm not sure which one is correct. It probably doesn't matter much.

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 02/38] posix-cpu-timers: Use common permission check in posix_cpu_clock_get()
  2019-08-21 19:08 ` [patch V2 02/38] posix-cpu-timers: Use common permission check in posix_cpu_clock_get() Thomas Gleixner
@ 2019-08-21 23:40   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-21 23:40 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:08:49PM +0200, Thomas Gleixner wrote:
> Replace the next slightly different copy of permission checks. That also
> removes the necessarity to check the return value of the sample functions
> because the clock id is already validated.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
>  kernel/time/posix-cpu-timers.c |   61 ++++++++++-------------------------------
>  1 file changed, 16 insertions(+), 45 deletions(-)
> 
> --- a/kernel/time/posix-cpu-timers.c
> +++ b/kernel/time/posix-cpu-timers.c
> @@ -289,53 +289,24 @@ static int cpu_clock_sample_group(const
>  	return 0;
>  }
>  
> -static int posix_cpu_clock_get_task(struct task_struct *tsk,
> -				    const clockid_t which_clock,
> -				    struct timespec64 *tp)
> +static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)
>  {
> -	int err = -EINVAL;
> -	u64 rtn;
> +	const clockid_t clkid = CPUCLOCK_WHICH(clock);

So I guess you later remove the CPUCLOCK_WHICH() from cpu_clock_sample*()
and turn them to void.

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 03/38] posix-cpu-timers: Use common permission check in posix_cpu_timer_create()
  2019-08-21 19:08 ` [patch V2 03/38] posix-cpu-timers: Use common permission check in posix_cpu_timer_create() Thomas Gleixner
@ 2019-08-21 23:49   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-21 23:49 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:08:50PM +0200, Thomas Gleixner wrote:
> Yet another copy of the same thing gone...
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation
  2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
                   ` (36 preceding siblings ...)
  2019-08-21 19:09 ` [patch V2 38/38] posix-cpu-timers: Utilize timerqueue for storage Thomas Gleixner
@ 2019-08-22  0:54 ` Christoph Hellwig
  2019-08-22  1:02   ` Frederic Weisbecker
       [not found] ` <20190821192920.909530418@linutronix.de>
  38 siblings, 1 reply; 137+ messages in thread
From: Christoph Hellwig @ 2019-08-22  0:54 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Christoph Hellwig

> The series applies on top of:
> 
>    git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
> 
> and is available from git as well:
> 
>    git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git WIP.timers/core

Btw, for some reason git here seems to be very unhappy about that remote:

Fetching tip
error: cannot lock ref 'refs/remotes/tip/WIP.timers/core': 'refs/remotes/tip/WIP.timers' exists; cannot create 'refs/remotes/tip/WIP.timers/core'
From https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
! [new branch]                WIP.timers/core -> tip/WIP.timers/core  (unable to update local ref)
error: Could not fetch tip

which repeats every time I fetch.  I can't of anythign particular on
my side that would cause this.

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation
  2019-08-22  0:54 ` [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Christoph Hellwig
@ 2019-08-22  1:02   ` Frederic Weisbecker
  2019-08-22  1:02     ` Christoph Hellwig
  0 siblings, 1 reply; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22  1:02 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Thomas Gleixner, LKML, Oleg Nesterov, Ingo Molnar,
	Peter Zijlstra, John Stultz, Anna-Maria Behnsen

On Thu, Aug 22, 2019 at 02:54:34AM +0200, Christoph Hellwig wrote:
> > The series applies on top of:
> > 
> >    git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git timers/core
> > 
> > and is available from git as well:
> > 
> >    git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git WIP.timers/core
> 
> Btw, for some reason git here seems to be very unhappy about that remote:
> 
> Fetching tip
> error: cannot lock ref 'refs/remotes/tip/WIP.timers/core': 'refs/remotes/tip/WIP.timers' exists; cannot create 'refs/remotes/tip/WIP.timers/core'
> From https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
> ! [new branch]                WIP.timers/core -> tip/WIP.timers/core  (unable to update local ref)
> error: Could not fetch tip
> 
> which repeats every time I fetch.  I can't of anythign particular on
> my side that would cause this.

Yeah I had to run "git remote prune tip" and fetch again.

Apparently there was an old remote branch tip/WIP.timers and git
seem to refuse to have a new subpath branch.

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation
  2019-08-22  1:02   ` Frederic Weisbecker
@ 2019-08-22  1:02     ` Christoph Hellwig
  0 siblings, 0 replies; 137+ messages in thread
From: Christoph Hellwig @ 2019-08-22  1:02 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: Christoph Hellwig, Thomas Gleixner, LKML, Oleg Nesterov,
	Ingo Molnar, Peter Zijlstra, John Stultz, Anna-Maria Behnsen

On Thu, Aug 22, 2019 at 03:02:04AM +0200, Frederic Weisbecker wrote:
> > which repeats every time I fetch.  I can't of anythign particular on
> > my side that would cause this.
> 
> Yeah I had to run "git remote prune tip" and fetch again.
> 
> Apparently there was an old remote branch tip/WIP.timers and git
> seem to refuse to have a new subpath branch.

Thanks, that seems to have fixed the issue for me.

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 04/38] posix-cpu-timers: Provide quick sample function for itimer
  2019-08-21 19:08 ` [patch V2 04/38] posix-cpu-timers: Provide quick sample function for itimer Thomas Gleixner
@ 2019-08-22 12:13   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 12:13 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:08:51PM +0200, Thomas Gleixner wrote:
> get_itimer() needs a sample of the current thread group cputime. It invokes
> thread_group_cputimer() - which is a misnomer. That function also starts
> eventually the group cputime accouting which is bogus because the
> accounting is already active when a timer is armed.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 05/38] itimers: Use quick sample function
  2019-08-21 19:08 ` [patch V2 05/38] itimers: Use quick sample function Thomas Gleixner
@ 2019-08-22 12:15   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 12:15 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:08:52PM +0200, Thomas Gleixner wrote:
> get_itimer() locks sighand lock and checks whether the timer is already
> expired. If it is not expired then the thread group cputime accounting is
> already enabled. Use the sampling function not the one which is meant for
> starting a timer.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

I've always hated the abuse of thread_group_cputimer().

Thanks!

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 06/38] posix-cpu-timers: Sample directly in timer check
  2019-08-21 19:08 ` [patch V2 06/38] posix-cpu-timers: Sample directly in timer check Thomas Gleixner
@ 2019-08-22 12:30   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 12:30 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:08:53PM +0200, Thomas Gleixner wrote:
> The thread group accounting is active, otherwise the expiry function would
> not be running. Sample the thread group time directly.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 07/38] posix-cpu-timers: Rename thread_group_cputimer() and make it static
  2019-08-21 19:08 ` [patch V2 07/38] posix-cpu-timers: Rename thread_group_cputimer() and make it static Thomas Gleixner
@ 2019-08-22 12:41   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 12:41 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:08:54PM +0200, Thomas Gleixner wrote:
> thread_group_cputimer() is a complete misnomer. The function does two things:
> 
>  - For arming process wide timers it makes sure that the atomic time
>    storage is up to date. If no cpu timer is armed yet, then the atomic
>    time storage is not updated by the scheduler for performance reasons.
> 
>    In that case a full summing up of all threads needs to be done and the
>    update needs to be enabled.
> 
> - Samples the current time into the caller supplied storage.
> 
> Rename it to thread_group_start_cputime(), make it static and fixup the
> callsite.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 08/38] posix-cpu-timers: Consolidate thread group sample code
  2019-08-21 19:08 ` [patch V2 08/38] posix-cpu-timers: Consolidate thread group sample code Thomas Gleixner
@ 2019-08-22 13:49   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 13:49 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:08:55PM +0200, Thomas Gleixner wrote:
> cpu_clock_sample_group() and cpu_timer_sample_group() are almost the
> same. Before the rename one called thread_group_cputimer() and the other
> thread_group_cputime(). Really intuitive function names.
> 
> Consolidate the functions and also avoid the thread traversal when
> the thread group's accounting is already active.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
[snip]
> @@ -755,7 +736,7 @@ static void posix_cpu_timer_get(struct k
>  			timer->it.cpu.expires = 0;
>  			return;
>  		} else {
> -			cpu_timer_sample_group(timer->it_clock, p, &now);
> +			cpu_clock_sample_group(timer->it_clock, p, &now, false);

We might want to warn here if !cputimer->running.

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 09/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_set()
  2019-08-21 19:08 ` [patch V2 09/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_set() Thomas Gleixner
@ 2019-08-22 13:58   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 13:58 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:08:56PM +0200, Thomas Gleixner wrote:
> Extract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it
> as argument to the sample functions. That allows to simplify them once all
> callers are fixed.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 10/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_get()
  2019-08-21 19:08 ` [patch V2 10/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_get() Thomas Gleixner
@ 2019-08-22 14:07   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 14:07 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:08:57PM +0200, Thomas Gleixner wrote:
> Extract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it
> as argument to the sample functions. That allows to simplify them once all
> callers are fixed.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 11/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_rearm()
  2019-08-21 19:08 ` [patch V2 11/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_rearm() Thomas Gleixner
@ 2019-08-22 14:12   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 14:12 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:08:58PM +0200, Thomas Gleixner wrote:
> Extract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it
> as argument to the sample functions. That allows to simplify them once all
> callers are fixed.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 12/38] posix-cpu-timers: Remove pointless return value check
  2019-08-21 19:08 ` [patch V2 12/38] posix-cpu-timers: Remove pointless return value check Thomas Gleixner
@ 2019-08-22 14:15   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 14:15 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:08:59PM +0200, Thomas Gleixner wrote:
> set_process_cpu_timer() checks already whether the clock id is valid. No
> point in checking the return value of the sample function. That allows to
> simplify the sample function later.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 13/38] posix-cpu-timers: Simplify sample functions
  2019-08-21 19:09 ` [patch V2 13/38] posix-cpu-timers: Simplify sample functions Thomas Gleixner
@ 2019-08-22 14:20   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 14:20 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:00PM +0200, Thomas Gleixner wrote:
> All callers hand in a valdiated clock id. Remove the return value which was
> unchecked in most places anyway.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 14/38] posix-cpu-timers: Get rid of pointer indirection
  2019-08-21 19:09 ` [patch V2 14/38] posix-cpu-timers: Get rid of pointer indirection Thomas Gleixner
@ 2019-08-22 14:41   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 14:41 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:01PM +0200, Thomas Gleixner wrote:
> Now that the sample functions have no return value anymore, the result can
> simply be returned instead of using pointer indirection.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 15/38] posix-cpu-timers: Sample task times once in expiry check
  2019-08-21 19:09 ` [patch V2 15/38] posix-cpu-timers: Sample task times once in expiry check Thomas Gleixner
@ 2019-08-22 15:00   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 15:00 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:02PM +0200, Thomas Gleixner wrote:
> Sampling the task times twice does not make sense. Do it once.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>




^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 16/38] posix-cpu-timers: Move prof/virt_ticks into caller
  2019-08-21 19:09 ` [patch V2 16/38] posix-cpu-timers: Move prof/virt_ticks into caller Thomas Gleixner
@ 2019-08-22 15:05   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 15:05 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:03PM +0200, Thomas Gleixner wrote:
> The functions have only one caller left. No point in having them.
> 
> Move the almost duplicated code into the caller and simplify it.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 17/38] posix-cpu-timers: Create a container struct
  2019-08-21 19:09 ` [patch V2 17/38] posix-cpu-timers: Create a container struct Thomas Gleixner
@ 2019-08-22 15:32   ` Frederic Weisbecker
  2019-08-23 15:34     ` Thomas Gleixner
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 1 reply; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 15:32 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:04PM +0200, Thomas Gleixner wrote:
> --- a/include/linux/posix-timers.h
> +++ b/include/linux/posix-timers.h
> @@ -62,6 +62,40 @@ static inline int clockid_to_fd(const cl
>  	return ~(clk >> 3);
>  }

Shouldn't you start the #ifdef CONFIG_POSIX_TIMERS here?
Because you're redefining struct posix_cputimers otherwise.

> +/**
> + * posix_cputimers - Container for posix CPU timer related data
> + * @cpu_timers:		List heads to queue posix CPU timers
> + *
> + * Used in task_struct and signal_struct
> + */
> +struct posix_cputimers {
> +	struct list_head	cpu_timers[CPUCLOCK_MAX];
> +};
> +
> +static inline void posix_cputimers_init(struct posix_cputimers *pct)
> +{
> +	INIT_LIST_HEAD(&pct->cpu_timers[0]);
> +	INIT_LIST_HEAD(&pct->cpu_timers[1]);
> +	INIT_LIST_HEAD(&pct->cpu_timers[2]);
> +}
> +
> +#ifdef CONFIG_POSIX_TIMERS
> +/* Init task static initializer */
> +#define INIT_CPU_TIMERLISTS(c)	{					\
> +	LIST_HEAD_INIT(c.cpu_timers[0]),				\
> +	LIST_HEAD_INIT(c.cpu_timers[1]),				\
> +	LIST_HEAD_INIT(c.cpu_timers[2]),				\
> +}
> +
> +#define INIT_CPU_TIMERS(s)						\
> +	.posix_cputimers = {						\
> +		.cpu_timers = INIT_CPU_TIMERLISTS(s.posix_cputimers),	\
> +	},
> +#else
> +struct posix_cputimers { };
> +#define INIT_CPU_TIMERS(s)
> +#endif
> +

Other than that:

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 18/38] sched: Move struct task_cputime to types.h
       [not found] ` <20190821192920.909530418@linutronix.de>
@ 2019-08-22 16:06   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 16:06 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:05PM +0200, Thomas Gleixner wrote:
> For upcoming posix-timer changes to avoid include recursion hell.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 19/38] posix-cpu-timers: Move expiry cache into struct posix_cputimers
  2019-08-21 19:09 ` [patch V2 19/38] posix-cpu-timers: Move expiry cache into struct posix_cputimers Thomas Gleixner
@ 2019-08-22 16:29   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-22 16:29 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:06PM +0200, Thomas Gleixner wrote:
> The expiry cache belongs into the posix_cputimers container where the other
> cpu timers information is.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 01/38] posix-cpu-timers: Provide task validation functions
  2019-08-21 23:03     ` Frederic Weisbecker
@ 2019-08-23 15:33       ` Thomas Gleixner
  0 siblings, 0 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-23 15:33 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Thu, 22 Aug 2019, Frederic Weisbecker wrote:
> On Thu, Aug 22, 2019 at 12:33:56AM +0200, Frederic Weisbecker wrote:
> > On Wed, Aug 21, 2019 at 09:08:48PM +0200, Thomas Gleixner wrote:
> > > The code contains three slightly different copies of validating whether a
> > > given clock resolves to a valid task and whether the current caller has
> > > permissions to access it.
> > > 
> > > Create central functions. Replace check_clock() as a first step and rename
> > > it to something sensible.
> > > 
> > > Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> > > ---
> > >  kernel/time/posix-cpu-timers.c |   65 +++++++++++++++++++++++++++--------------
> > >  1 file changed, 44 insertions(+), 21 deletions(-)
> > > 
> > > --- a/kernel/time/posix-cpu-timers.c
> > > +++ b/kernel/time/posix-cpu-timers.c
> > > @@ -35,27 +35,52 @@ void update_rlimit_cpu(struct task_struc
> > >  	spin_unlock_irq(&task->sighand->siglock);
> > >  }
> > >  
> > > -static int check_clock(const clockid_t which_clock)
> > > +/*
> > > + * Functions for validating access to tasks.
> > > + */
> > > +static struct task_struct *lookup_task(const pid_t pid, bool thread)
> > >  {
> > > -	int error = 0;
> > >  	struct task_struct *p;
> > > -	const pid_t pid = CPUCLOCK_PID(which_clock);
> > >  
> > > -	if (CPUCLOCK_WHICH(which_clock) >= CPUCLOCK_MAX)
> > > -		return -EINVAL;
> > > +	if (!pid)
> > > +		return thread ? current : current->group_leader;
> > >  
> > > -	if (pid == 0)
> > > -		return 0;
> > > +	p = find_task_by_vpid(pid);
> > > +	if (!p || p == current)
> > > +		return p;
> > 
> > What if (p == current && !thread && !has_group_leader_pid(p)) ?
> 
> Ah looking at the next patch, posix_cpu_clock_get_task() and posix_cpu_clock_getres()
> had different ad-hoc checks for this specific case.
> 
> clock_getres() used to return -EINVAL while clock_get() doesn't
> care. They certainly should agree in their behaviour. I'm not sure which
> one is correct. It probably doesn't matter much.

Let me stare on the different variants again

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 17/38] posix-cpu-timers: Create a container struct
  2019-08-22 15:32   ` Frederic Weisbecker
@ 2019-08-23 15:34     ` Thomas Gleixner
  0 siblings, 0 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-23 15:34 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Thu, 22 Aug 2019, Frederic Weisbecker wrote:

> On Wed, Aug 21, 2019 at 09:09:04PM +0200, Thomas Gleixner wrote:
> > --- a/include/linux/posix-timers.h
> > +++ b/include/linux/posix-timers.h
> > @@ -62,6 +62,40 @@ static inline int clockid_to_fd(const cl
> >  	return ~(clk >> 3);
> >  }
> 
> Shouldn't you start the #ifdef CONFIG_POSIX_TIMERS here?
> Because you're redefining struct posix_cputimers otherwise.

Yeah...


^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 20/38] posix-cpu-timers: Provide array based access to expiry cache
  2019-08-21 19:09 ` [patch V2 20/38] posix-cpu-timers: Provide array based access to expiry cache Thomas Gleixner
@ 2019-08-23 17:33   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-23 17:33 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:07PM +0200, Thomas Gleixner wrote:
> Using struct task_cputime for the expiry cache is a pretty odd choice and
> comes with magic defines to rename the fields for usage in the expiry
> cache.
> 
> struct task_cputime is basically a u64 array with 3 members, but it has
> distinct members.
> 
> The expiry cache content is different than the content of task_cputime
> because
> 
>   expiry[PROF]  = task_cputime.stime + task_cputime.utime
>   expiry[VIRT]  = task_cputime.utime
>   expiry[SCHED] = task_cputime.sum_exec_runtime
> 
> So there is no direct mapping between task_cputime and the expiry cache and
> the #define based remapping is just a horrible hack.
> 
> Having the expiry cache array based allows further simplification of the
> expiry code.
> 
> To avoid an all in one cleanup which is hard to review add a temporary
> anonymous union into struct task_cputime which allows array based access to
> it. That requires to reorder the members. Add a build time sanity check to
> validate that the members are at the same place.
> 
> The union and the build time checks will be removed after conversion.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 21/38] posix-cpu-timers: Simplify timer queueing
  2019-08-21 19:09 ` [patch V2 21/38] posix-cpu-timers: Simplify timer queueing Thomas Gleixner
@ 2019-08-23 17:51   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-23 17:51 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:08PM +0200, Thomas Gleixner wrote:
> Now that the expiry cache can be accessed as an array, the per clock
> checking can be reduced to just comparing the corresponding array elements.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 22/38] posix-cpu-timers: Simplify set_process_cpu_timer()
  2019-08-21 19:09 ` [patch V2 22/38] posix-cpu-timers: Simplify set_process_cpu_timer() Thomas Gleixner
@ 2019-08-23 18:00   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-23 18:00 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:09PM +0200, Thomas Gleixner wrote:
> The expiry cache can now be accessed as an array. Replace the per clock
> checks with a simple comparison of the clock indexed array member.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 23/38] posix-cpu-timers: Switch check_*_timers() to array cache
  2019-08-21 19:09 ` [patch V2 23/38] posix-cpu-timers: Switch check_*_timers() to array cache Thomas Gleixner
@ 2019-08-23 18:13   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-23 18:13 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:10PM +0200, Thomas Gleixner wrote:
> Use the array based expiry cache in check_thread_timers() and convert the
> store in check_process_timers() for consistency.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
>  kernel/time/posix-cpu-timers.c |   26 +++++++++++---------------
>  1 file changed, 11 insertions(+), 15 deletions(-)
> 
> --- a/kernel/time/posix-cpu-timers.c
> +++ b/kernel/time/posix-cpu-timers.c
> @@ -778,8 +778,7 @@ static void check_thread_timers(struct t
>  				struct list_head *firing)
>  {
>  	struct list_head *timers = tsk->posix_cputimers.cpu_timers;
> -	struct task_cputime *tsk_expires = &tsk->posix_cputimers.cputime_expires;
> -	u64 expires, stime, utime;
> +	u64 stime, utime, *expires = tsk->posix_cputimers.expiries;
>  	unsigned long soft;
>  
>  	if (dl_task(tsk))
> @@ -789,19 +788,14 @@ static void check_thread_timers(struct t
>  	 * If cputime_expires is zero, then there are no active
>  	 * per thread CPU timers.
>  	 */
> -	if (task_cputime_zero(tsk_expires))
> +	if (task_cputime_zero(&tsk->posix_cputimers.cputime_expires))
>  		return;
>  
>  	task_cputime(tsk, &utime, &stime);
>  
> -	expires = check_timers_list(timers, firing, utime + stime);
> -	tsk_expires->prof_exp = expires;
> -
> -	expires = check_timers_list(++timers, firing, utime);
> -	tsk_expires->virt_exp = expires;
> -
> -	tsk_expires->sched_exp = check_timers_list(++timers, firing,
> -						   tsk->se.sum_exec_runtime);
> +	*expires++ = check_timers_list(timers, firing, utime + stime);
> +	*expires++ = check_timers_list(++timers, firing, utime);
> +	*expires = check_timers_list(++timers, firing, tsk->se.sum_exec_runtime);

What a nice reading for anyone learning the difference between pointers's
pre and post incrementation :-)

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 24/38] posix-cpu-timers: Remove the odd field rename defines
  2019-08-21 19:09 ` [patch V2 24/38] posix-cpu-timers: Remove the odd field rename defines Thomas Gleixner
@ 2019-08-23 18:36   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-23 18:36 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:11PM +0200, Thomas Gleixner wrote:
> The last users of the odd define based renaming of struct task_cputime
> members are gone. Good riddance.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 25/38] posix-cpu-timers: Provide array based sample functions
  2019-08-21 19:09 ` [patch V2 25/38] posix-cpu-timers: Provide array based sample functions Thomas Gleixner
@ 2019-08-23 22:08   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-23 22:08 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:12PM +0200, Thomas Gleixner wrote:
> Instead of using task_cputime and doing the addition of utime and stime at
> all call sites, it's way simpler to have a sample array which allows
> indexed based checks against the expiry cache array.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 26/38] posix-cpu-timers: Make expiry checks array based
  2019-08-21 19:09 ` [patch V2 26/38] posix-cpu-timers: Make expiry checks array based Thomas Gleixner
@ 2019-08-23 22:44   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-23 22:44 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:13PM +0200, Thomas Gleixner wrote:
> The expiry cache is an array indexed by clock ids. The new sample functions
> allow to retrieve a corresponding array of samples.
> 
> Convert the fastpath expiry checks to make use of the new sample functions
> and do the comparisons on the sample and the expiry array.
> 
> Make the check for the expiry array being zero array based as well.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

Just a few boring neats:

>  /**
> - * task_cputime_expired - Compare two task_cputime entities.
> + * task_cputimers_expired - Compare two task_cputime entities.

s/task_cputime/clock arrays ?

>   *
> - * @sample:	The task_cputime structure to be checked for expiration.
> - * @expires:	Expiration times, against which @sample will be checked.
> + * @samples:	Array of current samples for the CPUCLOCK clocks
> + * @expiries:	Array of expiry values for the CPUCLOCK clocks
>   *
> - * Checks @sample against @expires to see if any field of @sample has expired.
> - * Returns true if any field of the former is greater than the corresponding
> - * field of the latter if the latter field is set.  Otherwise returns false.
> + * Returns true if any mmember of @samples is greater than the corresponding

s/mmember/member

> + * member of @expiries if that member is non zero. False otherwise
>   */
> -static inline int task_cputime_expired(const struct task_cputime *sample,
> -					const struct task_cputime *expires)
> +static inline bool task_cputimers_expired(const u64 *sample, const u64 *expiries)

s/sample/samples to agree with above documented parameters.

Thanks.

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 27/38] posix-cpu-timers: Remove cputime_expires
  2019-08-21 19:09 ` [patch V2 27/38] posix-cpu-timers: Remove cputime_expires Thomas Gleixner
@ 2019-08-23 22:50   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-23 22:50 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:14PM +0200, Thomas Gleixner wrote:
> The last users of the magic struct cputime based expiry cache are
> gone. Remove the leftovers.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 28/38] posix-cpu-timers: Restructure expiry array
  2019-08-21 19:09 ` [patch V2 28/38] posix-cpu-timers: Restructure expiry array Thomas Gleixner
@ 2019-08-26 16:32   ` Frederic Weisbecker
  2019-08-26 18:16     ` Thomas Gleixner
  2019-08-26 21:06   ` [patch V2 28/38] " Frederic Weisbecker
  1 sibling, 1 reply; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-26 16:32 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:15PM +0200, Thomas Gleixner wrote:
>  /**
> - * task_cputimers_expired - Compare two task_cputime entities.
> + * task_cputimers_expired - Check whether posix CPU timers are expired
>   *
>   * @samples:	Array of current samples for the CPUCLOCK clocks
> - * @expiries:	Array of expiry values for the CPUCLOCK clocks
> + * @pct:	Pointer to a posix_cputimers container
>   *
> - * Returns true if any mmember of @samples is greater than the corresponding
> - * member of @expiries if that member is non zero. False otherwise
> + * Returns true if any member of @samples is greater than the corresponding
> + * member of @pct->bases[CLK].nextevt. False otherwise
>   */
> -static inline bool task_cputimers_expired(const u64 *sample, const u64 *expiries)
> +static inline bool
> +task_cputimers_expired(const u64 *sample, struct posix_cputimers *pct)
>  {
>  	int i;
>  
>  	for (i = 0; i < CPUCLOCK_MAX; i++) {
> -		if (expiries[i] && sample[i] >= expiries[i])
> +		if (sample[i] >= pct->bases[i].nextevt)

You may have false positive here if you don't check if pct->bases[i].nextevt
is 0. Probably no big deal by the end of the series since you change that 0
for KTIME_MAX later but right now it might hurt bisection with performance
issues (locking sighand at every tick...).

[...]

> @@ -1176,7 +1182,7 @@ void run_posix_cpu_timers(void)
>  void set_process_cpu_timer(struct task_struct *tsk, unsigned int clkid,
>  			   u64 *newval, u64 *oldval)
>  {
> -	u64 now, *expiry = tsk->signal->posix_cputimers.expiries + clkid;
> +	u64 now, *nextevt = &tsk->signal->posix_cputimers.bases[clkid].nextevt;

You're dereferencing the pointer before checking clkid sanity below.

>  
>  	if (WARN_ON_ONCE(clkid >= CPUCLOCK_SCHED))
>  		return;
> @@ -1207,8 +1213,8 @@ void set_process_cpu_timer(struct task_s
>  	 * Update expiration cache if this is the earliest timer. CPUCLOCK_PROF
>  	 * expiry cache is also used by RLIMIT_CPU!.
>  	 */
> -	if (expires_gt(*expiry, *newval))
> -		*expiry = *newval;
> +	if (expires_gt(*nextevt, *newval))
> +		*nextevt = *newval;
>  
>  	tick_dep_set_signal(tsk->signal, TICK_DEP_BIT_POSIX_TIMER);
>  }
> 
> 

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 28/38] posix-cpu-timers: Restructure expiry array
  2019-08-26 16:32   ` Frederic Weisbecker
@ 2019-08-26 18:16     ` Thomas Gleixner
  2019-08-26 18:22       ` [patch V3 " Thomas Gleixner
  0 siblings, 1 reply; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-26 18:16 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Mon, 26 Aug 2019, Frederic Weisbecker wrote:
> On Wed, Aug 21, 2019 at 09:09:15PM +0200, Thomas Gleixner wrote:
> >  /**
> > - * task_cputimers_expired - Compare two task_cputime entities.
> > + * task_cputimers_expired - Check whether posix CPU timers are expired
> >   *
> >   * @samples:	Array of current samples for the CPUCLOCK clocks
> > - * @expiries:	Array of expiry values for the CPUCLOCK clocks
> > + * @pct:	Pointer to a posix_cputimers container
> >   *
> > - * Returns true if any mmember of @samples is greater than the corresponding
> > - * member of @expiries if that member is non zero. False otherwise
> > + * Returns true if any member of @samples is greater than the corresponding
> > + * member of @pct->bases[CLK].nextevt. False otherwise
> >   */
> > -static inline bool task_cputimers_expired(const u64 *sample, const u64 *expiries)
> > +static inline bool
> > +task_cputimers_expired(const u64 *sample, struct posix_cputimers *pct)
> >  {
> >  	int i;
> >  
> >  	for (i = 0; i < CPUCLOCK_MAX; i++) {
> > -		if (expiries[i] && sample[i] >= expiries[i])
> > +		if (sample[i] >= pct->bases[i].nextevt)
> 
> You may have false positive here if you don't check if pct->bases[i].nextevt
> is 0. Probably no big deal by the end of the series since you change that 0
> for KTIME_MAX later but right now it might hurt bisection with performance
> issues (locking sighand at every tick...).

Hrm. That should have stayed until the patch  which removes that 0 state

> [...]
> 
> > @@ -1176,7 +1182,7 @@ void run_posix_cpu_timers(void)
> >  void set_process_cpu_timer(struct task_struct *tsk, unsigned int clkid,
> >  			   u64 *newval, u64 *oldval)
> >  {
> > -	u64 now, *expiry = tsk->signal->posix_cputimers.expiries + clkid;
> > +	u64 now, *nextevt = &tsk->signal->posix_cputimers.bases[clkid].nextevt;
> 
> You're dereferencing the pointer before checking clkid sanity below.

Urgh. Yes.
 
Thanks,

	tglx

^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V3 28/38] posix-cpu-timers: Restructure expiry array
  2019-08-26 18:16     ` Thomas Gleixner
@ 2019-08-26 18:22       ` Thomas Gleixner
  2019-08-26 19:45         ` Frederic Weisbecker
  2019-08-28 10:16         ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  0 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-26 18:22 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

Now that the abused struct task_cputime is gone, it's more natural to
bundle the expiry cache and the list head of each clock into a struct and
have an array of those structs.

Follow the hrtimer naming convention of 'bases' and rename the expiry cache
to 'nextevt' and adapt all usage sites.

Generates also better code .text size shrinks by 80 bytes.

Suggested-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: New patch
V3: Address review feedback from Frederic
---
 include/linux/posix-timers.h   |   41 ++++++++++------
 kernel/time/posix-cpu-timers.c |  105 +++++++++++++++++++++--------------------
 2 files changed, 83 insertions(+), 63 deletions(-)

--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -63,24 +63,33 @@ static inline int clockid_to_fd(const cl
 }
 
 #ifdef CONFIG_POSIX_TIMERS
+
 /**
- * posix_cputimers - Container for posix CPU timer related data
- * @expiries:		Earliest-expiration cache array based
+ * posix_cputimer_base - Container per posix CPU clock
+ * @nextevt:		Earliest-expiration cache
  * @cpu_timers:		List heads to queue posix CPU timers
+ */
+struct posix_cputimer_base {
+	u64			nextevt;
+	struct list_head	cpu_timers;
+};
+
+/**
+ * posix_cputimers - Container for posix CPU timer related data
+ * @bases:		Base container for posix CPU clocks
  *
  * Used in task_struct and signal_struct
  */
 struct posix_cputimers {
-	u64			expiries[CPUCLOCK_MAX];
-	struct list_head	cpu_timers[CPUCLOCK_MAX];
+	struct posix_cputimer_base	bases[CPUCLOCK_MAX];
 };
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
 {
-	memset(&pct->expiries, 0, sizeof(pct->expiries));
-	INIT_LIST_HEAD(&pct->cpu_timers[0]);
-	INIT_LIST_HEAD(&pct->cpu_timers[1]);
-	INIT_LIST_HEAD(&pct->cpu_timers[2]);
+	memset(pct->bases, 0, sizeof(pct->bases));
+	INIT_LIST_HEAD(&pct->bases[0].cpu_timers);
+	INIT_LIST_HEAD(&pct->bases[1].cpu_timers);
+	INIT_LIST_HEAD(&pct->bases[2].cpu_timers);
 }
 
 void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit);
@@ -88,19 +97,23 @@ void posix_cputimers_group_init(struct p
 static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct,
 					       u64 runtime)
 {
-	pct->expiries[CPUCLOCK_SCHED] = runtime;
+	pct->bases[CPUCLOCK_SCHED].nextevt = runtime;
 }
 
 /* Init task static initializer */
-#define INIT_CPU_TIMERLISTS(c)	{					\
-	LIST_HEAD_INIT(c.cpu_timers[0]),				\
-	LIST_HEAD_INIT(c.cpu_timers[1]),				\
-	LIST_HEAD_INIT(c.cpu_timers[2]),				\
+#define INIT_CPU_TIMERBASE(b) {						\
+	.cpu_timers = LIST_HEAD_INIT(b.cpu_timers),			\
+}
+
+#define INIT_CPU_TIMERBASES(b) {					\
+	INIT_CPU_TIMERBASE(b[0]),					\
+	INIT_CPU_TIMERBASE(b[1]),					\
+	INIT_CPU_TIMERBASE(b[2]),					\
 }
 
 #define INIT_CPU_TIMERS(s)						\
 	.posix_cputimers = {						\
-		.cpu_timers = INIT_CPU_TIMERLISTS(s.posix_cputimers),	\
+		.bases = INIT_CPU_TIMERBASES(s.posix_cputimers.bases),	\
 	},
 #else
 struct posix_cputimers { };
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -24,13 +24,13 @@ void posix_cputimers_group_init(struct p
 {
 	posix_cputimers_init(pct);
 	if (cpu_limit != RLIM_INFINITY)
-		pct->expiries[CPUCLOCK_PROF] = cpu_limit * NSEC_PER_SEC;
+		pct->bases[CPUCLOCK_PROF].nextevt = cpu_limit * NSEC_PER_SEC;
 }
 
 /*
  * Called after updating RLIMIT_CPU to run cpu timer and update
- * tsk->signal->posix_cputimers.expiries expiration cache if
- * necessary. Needs siglock protection since other code may update
+ * tsk->signal->posix_cputimers.bases[clock].nextevt expiration cache if
+ * necessary. Needs siglock protection since other code may update the
  * expiration cache as well.
  */
 void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new)
@@ -122,9 +122,11 @@ static void bump_cpu_timer(struct k_itim
 	}
 }
 
-static inline bool expiry_cache_is_zero(const u64 *ec)
+static inline bool expiry_cache_is_zero(const struct posix_cputimers *pct)
 {
-	return !(ec[CPUCLOCK_PROF] | ec[CPUCLOCK_VIRT] | ec[CPUCLOCK_SCHED]);
+	return !(pct->bases[CPUCLOCK_PROF].nextevt |
+		 pct->bases[CPUCLOCK_VIRT].nextevt |
+		 pct->bases[CPUCLOCK_SCHED].nextevt);
 }
 
 static int
@@ -432,9 +434,9 @@ static void cleanup_timers_list(struct l
  */
 static void cleanup_timers(struct posix_cputimers *pct)
 {
-	cleanup_timers_list(&pct->cpu_timers[CPUCLOCK_PROF]);
-	cleanup_timers_list(&pct->cpu_timers[CPUCLOCK_VIRT]);
-	cleanup_timers_list(&pct->cpu_timers[CPUCLOCK_SCHED]);
+	cleanup_timers_list(&pct->bases[CPUCLOCK_PROF].cpu_timers);
+	cleanup_timers_list(&pct->bases[CPUCLOCK_VIRT].cpu_timers);
+	cleanup_timers_list(&pct->bases[CPUCLOCK_SCHED].cpu_timers);
 }
 
 /*
@@ -464,21 +466,19 @@ static void arm_timer(struct k_itimer *t
 {
 	struct cpu_timer_list *const nt = &timer->it.cpu;
 	int clkidx = CPUCLOCK_WHICH(timer->it_clock);
-	u64 *cpuexp, newexp = timer->it.cpu.expires;
 	struct task_struct *p = timer->it.cpu.task;
+	u64 newexp = timer->it.cpu.expires;
+	struct posix_cputimer_base *base;
 	struct list_head *head, *listpos;
 	struct cpu_timer_list *next;
 
-	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		head = p->posix_cputimers.cpu_timers + clkidx;
-		cpuexp = p->posix_cputimers.expiries + clkidx;
-	} else {
-		head = p->signal->posix_cputimers.cpu_timers + clkidx;
-		cpuexp = p->signal->posix_cputimers.expiries + clkidx;
-	}
+	if (CPUCLOCK_PERTHREAD(timer->it_clock))
+		base = p->posix_cputimers.bases + clkidx;
+	else
+		base = p->signal->posix_cputimers.bases + clkidx;
 
-	listpos = head;
-	list_for_each_entry(next, head, entry) {
+	listpos = head = &base->cpu_timers;
+	list_for_each_entry(next,head, entry) {
 		if (nt->expires < next->expires)
 			break;
 		listpos = &next->entry;
@@ -494,8 +494,8 @@ static void arm_timer(struct k_itimer *t
 	 * for process timers we share expiration cache with itimers
 	 * and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME.
 	 */
-	if (expires_gt(*cpuexp, newexp))
-		*cpuexp = newexp;
+	if (expires_gt(base->nextevt, newexp))
+		base->nextevt = newexp;
 
 	if (CPUCLOCK_PERTHREAD(timer->it_clock))
 		tick_dep_set_task(p, TICK_DEP_BIT_POSIX_TIMER);
@@ -783,9 +783,9 @@ static inline void check_dl_overrun(stru
 static void check_thread_timers(struct task_struct *tsk,
 				struct list_head *firing)
 {
-	struct list_head *timers = tsk->posix_cputimers.cpu_timers;
-	u64 stime, utime, *expires = tsk->posix_cputimers.expiries;
+	struct posix_cputimer_base *base = tsk->posix_cputimers.bases;
 	unsigned long soft;
+	u64 stime, utime;
 
 	if (dl_task(tsk))
 		check_dl_overrun(tsk);
@@ -794,14 +794,18 @@ static void check_thread_timers(struct t
 	 * If the expiry cache is zero, then there are no active per thread
 	 * CPU timers.
 	 */
-	if (expiry_cache_is_zero(tsk->posix_cputimers.expiries))
+	if (expiry_cache_is_zero(&tsk->posix_cputimers))
 		return;
 
 	task_cputime(tsk, &utime, &stime);
 
-	*expires++ = check_timers_list(timers, firing, utime + stime);
-	*expires++ = check_timers_list(++timers, firing, utime);
-	*expires = check_timers_list(++timers, firing, tsk->se.sum_exec_runtime);
+	base->nextevt = check_timers_list(&base->cpu_timers, firing,
+					  utime + stime);
+	base++;
+	base->nextevt = check_timers_list(&base->cpu_timers, firing, utime);
+	base++;
+	base->nextevt = check_timers_list(&base->cpu_timers, firing,
+					  tsk->se.sum_exec_runtime);
 
 	/*
 	 * Check for the special case thread timers.
@@ -840,7 +844,7 @@ static void check_thread_timers(struct t
 		}
 	}
 
-	if (expiry_cache_is_zero(tsk->posix_cputimers.expiries))
+	if (expiry_cache_is_zero(&tsk->posix_cputimers))
 		tick_dep_clear_task(tsk, TICK_DEP_BIT_POSIX_TIMER);
 }
 
@@ -884,7 +888,7 @@ static void check_process_timers(struct
 				 struct list_head *firing)
 {
 	struct signal_struct *const sig = tsk->signal;
-	struct list_head *timers = sig->posix_cputimers.cpu_timers;
+	struct posix_cputimer_base *base = sig->posix_cputimers.bases;
 	u64 utime, ptime, virt_expires, prof_expires;
 	u64 sum_sched_runtime, sched_expires;
 	struct task_cputime cputime;
@@ -912,9 +916,12 @@ static void check_process_timers(struct
 	ptime = utime + cputime.stime;
 	sum_sched_runtime = cputime.sum_exec_runtime;
 
-	prof_expires = check_timers_list(timers, firing, ptime);
-	virt_expires = check_timers_list(++timers, firing, utime);
-	sched_expires = check_timers_list(++timers, firing, sum_sched_runtime);
+	prof_expires = check_timers_list(&base[CPUCLOCK_PROF].cpu_timers,
+					 firing, ptime);
+	virt_expires = check_timers_list(&base[CPUCLOCK_VIRT].cpu_timers,
+					 firing, utime);
+	sched_expires = check_timers_list(&base[CPUCLOCK_SCHED].cpu_timers,
+					  firing, sum_sched_runtime);
 
 	/*
 	 * Check for the special case process timers.
@@ -959,11 +966,11 @@ static void check_process_timers(struct
 			prof_expires = x;
 	}
 
-	sig->posix_cputimers.expiries[CPUCLOCK_PROF] = prof_expires;
-	sig->posix_cputimers.expiries[CPUCLOCK_VIRT] = virt_expires;
-	sig->posix_cputimers.expiries[CPUCLOCK_SCHED] = sched_expires;
+	base[CPUCLOCK_PROF].nextevt = prof_expires;
+	base[CPUCLOCK_VIRT].nextevt = virt_expires;
+	base[CPUCLOCK_SCHED].nextevt = sched_expires;
 
-	if (expiry_cache_is_zero(sig->posix_cputimers.expiries))
+	if (expiry_cache_is_zero(&sig->posix_cputimers))
 		stop_process_timers(sig);
 
 	sig->cputimer.checking_timer = false;
@@ -1028,20 +1035,21 @@ static void posix_cpu_timer_rearm(struct
 }
 
 /**
- * task_cputimers_expired - Compare two task_cputime entities.
+ * task_cputimers_expired - Check whether posix CPU timers are expired
  *
  * @samples:	Array of current samples for the CPUCLOCK clocks
- * @expiries:	Array of expiry values for the CPUCLOCK clocks
+ * @pct:	Pointer to a posix_cputimers container
  *
- * Returns true if any mmember of @samples is greater than the corresponding
- * member of @expiries if that member is non zero. False otherwise
+ * Returns true if any member of @samples is greater than the corresponding
+ * member of @pct->bases[CLK].nextevt. False otherwise
  */
-static inline bool task_cputimers_expired(const u64 *sample, const u64 *expiries)
+static inline bool
+task_cputimers_expired(const u64 *sample, struct posix_cputimers *pct)
 {
 	int i;
 
 	for (i = 0; i < CPUCLOCK_MAX; i++) {
-		if (expiries[i] && sample[i] >= expiries[i])
+		if (pct->bases[i].nextevt && sample[i] >= pct->bases[i].nextevt)
 			return true;
 	}
 	return false;
@@ -1059,14 +1067,13 @@ static inline bool task_cputimers_expire
  */
 static inline bool fastpath_timer_check(struct task_struct *tsk)
 {
-	u64 *expiries = tsk->posix_cputimers.expiries;
 	struct signal_struct *sig;
 
-	if (!expiry_cache_is_zero(expiries)) {
+	if (!expiry_cache_is_zero(&tsk->posix_cputimers)) {
 		u64 samples[CPUCLOCK_MAX];
 
 		task_sample_cputime(tsk, samples);
-		if (task_cputimers_expired(samples, expiries))
+		if (task_cputimers_expired(samples, &tsk->posix_cputimers))
 			return true;
 	}
 
@@ -1092,8 +1099,7 @@ static inline bool fastpath_timer_check(
 		proc_sample_cputime_atomic(&sig->cputimer.cputime_atomic,
 					   samples);
 
-		if (task_cputimers_expired(samples,
-					   sig->posix_cputimers.expiries))
+		if (task_cputimers_expired(samples, &sig->posix_cputimers))
 			return true;
 	}
 
@@ -1176,11 +1182,12 @@ void run_posix_cpu_timers(void)
 void set_process_cpu_timer(struct task_struct *tsk, unsigned int clkid,
 			   u64 *newval, u64 *oldval)
 {
-	u64 now, *expiry = tsk->signal->posix_cputimers.expiries + clkid;
+	u64 now, *nextevt;
 
 	if (WARN_ON_ONCE(clkid >= CPUCLOCK_SCHED))
 		return;
 
+	nextevt = &tsk->signal->posix_cputimers.bases[clkid].nextevt;
 	now = cpu_clock_sample_group(clkid, tsk, true);
 
 	if (oldval) {
@@ -1207,8 +1214,8 @@ void set_process_cpu_timer(struct task_s
 	 * Update expiration cache if this is the earliest timer. CPUCLOCK_PROF
 	 * expiry cache is also used by RLIMIT_CPU!.
 	 */
-	if (expires_gt(*expiry, *newval))
-		*expiry = *newval;
+	if (expires_gt(*nextevt, *newval))
+		*nextevt = *newval;
 
 	tick_dep_set_signal(tsk->signal, TICK_DEP_BIT_POSIX_TIMER);
 }

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V3 28/38] posix-cpu-timers: Restructure expiry array
  2019-08-26 18:22       ` [patch V3 " Thomas Gleixner
@ 2019-08-26 19:45         ` Frederic Weisbecker
  2019-08-28 10:16         ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-26 19:45 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Mon, Aug 26, 2019 at 08:22:24PM +0200, Thomas Gleixner wrote:
> Now that the abused struct task_cputime is gone, it's more natural to
> bundle the expiry cache and the list head of each clock into a struct and
> have an array of those structs.
> 
> Follow the hrtimer naming convention of 'bases' and rename the expiry cache
> to 'nextevt' and adapt all usage sites.
> 
> Generates also better code .text size shrinks by 80 bytes.
> 
> Suggested-by: Ingo Molnar <mingo@kernel.org>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
> V2: New patch
> V3: Address review feedback from Frederic

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 28/38] posix-cpu-timers: Restructure expiry array
  2019-08-21 19:09 ` [patch V2 28/38] posix-cpu-timers: Restructure expiry array Thomas Gleixner
  2019-08-26 16:32   ` Frederic Weisbecker
@ 2019-08-26 21:06   ` Frederic Weisbecker
  2019-08-26 21:46     ` Thomas Gleixner
  1 sibling, 1 reply; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-26 21:06 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:15PM +0200, Thomas Gleixner wrote:
> @@ -884,7 +888,7 @@ static void check_process_timers(struct
>  				 struct list_head *firing)
>  {
>  	struct signal_struct *const sig = tsk->signal;
> -	struct list_head *timers = sig->posix_cputimers.cpu_timers;
> +	struct posix_cputimer_base *base = sig->posix_cputimers.bases;
>  	u64 utime, ptime, virt_expires, prof_expires;
>  	u64 sum_sched_runtime, sched_expires;
>  	struct task_cputime cputime;
> @@ -912,9 +916,12 @@ static void check_process_timers(struct
>  	ptime = utime + cputime.stime;
>  	sum_sched_runtime = cputime.sum_exec_runtime;
>  
> -	prof_expires = check_timers_list(timers, firing, ptime);
> -	virt_expires = check_timers_list(++timers, firing, utime);
> -	sched_expires = check_timers_list(++timers, firing, sum_sched_runtime);
> +	prof_expires = check_timers_list(&base[CPUCLOCK_PROF].cpu_timers,
> +					 firing, ptime);
> +	virt_expires = check_timers_list(&base[CPUCLOCK_VIRT].cpu_timers,
> +					 firing, utime);
> +	sched_expires = check_timers_list(&base[CLPCLOCK_SCHED].cpu_timers,

                                                ^^
0-day bot should have warned by now.

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 29/38] posix-cpu-timers: Switch thread group sampling to array
  2019-08-21 19:09 ` [patch V2 29/38] posix-cpu-timers: Switch thread group sampling to array Thomas Gleixner
@ 2019-08-26 21:12   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-26 21:12 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:16PM +0200, Thomas Gleixner wrote:
> That allows more simplifications in various places.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 30/38] posix-cpu-timers: Respect INFINITY for hard RTTIME limit
  2019-08-21 19:09 ` [patch V2 30/38] posix-cpu-timers: Respect INFINITY for hard RTTIME limit Thomas Gleixner
@ 2019-08-26 21:19   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-26 21:19 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:17PM +0200, Thomas Gleixner wrote:
> The RTIME limit expiry code does not check the hard RTTIME limit for
> INFINITY, i.e. being disabled.  Add it.
> 
> While this could be considered an ABI breakage if something would depend on
> this behaviour. Though it's highly unlikely to have an effect because
> RLIM_INFINITY is at minimum INT_MAX and the RTTIME limit is in seconds, so
> the timer would fire after ~68 years.
> 
> Adding this obvious correct limit check also allows further consolidation
> of that code and is a prerequisite for cleaning up the 0 based checks and
> the rlimit setter code.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 31/38] rlimit: Rewrite non-sensical RLIMIT_CPU comment
  2019-08-21 19:09 ` [patch V2 31/38] rlimit: Rewrite non-sensical RLIMIT_CPU comment Thomas Gleixner
@ 2019-08-26 21:41   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-26 21:41 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig, Andrew Morton, Jiri Slaby

On Wed, Aug 21, 2019 at 09:09:18PM +0200, Thomas Gleixner wrote:
> The comment above the function which arms RLIMIT_CPU in the posix CPU timer
> code makes no sense at all. It claims that the kernel does not return an
> error code when it rejected the attempt to set RLIMIT_CPU. That's clearly
> bogus as the code does an error check and the rlimit is only set and
> activated when the permission checks are ok. In case of a rejection an
> appropriate error code is returned.
> 
> This is a historical and outdated comment which got dragged along even when
> the rlimit handling code was rewritten.
> 
> Replace it with an explanation why the setup function is not called when
> the rlimit value is RLIM_INFINITY and how the 'disarming' is handled.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Jiri Slaby <jslaby@suse.com>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 28/38] posix-cpu-timers: Restructure expiry array
  2019-08-26 21:06   ` [patch V2 28/38] " Frederic Weisbecker
@ 2019-08-26 21:46     ` Thomas Gleixner
  0 siblings, 0 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-26 21:46 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Mon, 26 Aug 2019, Frederic Weisbecker wrote:
> On Wed, Aug 21, 2019 at 09:09:15PM +0200, Thomas Gleixner wrote:
> > @@ -884,7 +888,7 @@ static void check_process_timers(struct
> >  				 struct list_head *firing)
> >  {
> >  	struct signal_struct *const sig = tsk->signal;
> > -	struct list_head *timers = sig->posix_cputimers.cpu_timers;
> > +	struct posix_cputimer_base *base = sig->posix_cputimers.bases;
> >  	u64 utime, ptime, virt_expires, prof_expires;
> >  	u64 sum_sched_runtime, sched_expires;
> >  	struct task_cputime cputime;
> > @@ -912,9 +916,12 @@ static void check_process_timers(struct
> >  	ptime = utime + cputime.stime;
> >  	sum_sched_runtime = cputime.sum_exec_runtime;
> >  
> > -	prof_expires = check_timers_list(timers, firing, ptime);
> > -	virt_expires = check_timers_list(++timers, firing, utime);
> > -	sched_expires = check_timers_list(++timers, firing, sum_sched_runtime);
> > +	prof_expires = check_timers_list(&base[CPUCLOCK_PROF].cpu_timers,
> > +					 firing, ptime);
> > +	virt_expires = check_timers_list(&base[CPUCLOCK_VIRT].cpu_timers,
> > +					 firing, utime);
> > +	sched_expires = check_timers_list(&base[CLPCLOCK_SCHED].cpu_timers,
> 
>                                                 ^^
> 0-day bot should have warned by now.

It didn't but my own testing found it and I fixed it locally already


^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 32/38] posix-cpu-timers: Get rid of zero checks
  2019-08-21 19:09 ` [patch V2 32/38] posix-cpu-timers: Get rid of zero checks Thomas Gleixner
@ 2019-08-26 21:57   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-26 21:57 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:19PM +0200, Thomas Gleixner wrote:
> Deactivation of the expiry cache is done by setting all clock caches to
> 0. That requires to have a check for zero in all places which update the
> expiry cache:
> 
> 	if (cache == 0 || new < cache)
> 		cache = new;
> 
> Use U64_MAX as the deactivated value, which allows to remove the zero
> checks when updating the cache and reduces it to the obvious check:
> 
> 	if (new < cache)
> 		cache = new;
> 
> This also removes the weird workaround in do_prlimit() which was required
> to convert a RLIMIT_CPU value of 0 (immediate expiry) to 1 because handing
> in 0 to the posix CPU timer code would have effectively disarmed it.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 33/38] posix-cpu-timers: Consolidate timer expiry further
  2019-08-21 19:09 ` [patch V2 33/38] posix-cpu-timers: Consolidate timer expiry further Thomas Gleixner
@ 2019-08-26 22:29   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-26 22:29 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:20PM +0200, Thomas Gleixner wrote:
> With the array based samples and expiry cache, the expiry function can use
> a loop to collect timers from the clock specific lists.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 34/38] posix-cpu-timers: Get rid of 64bit divisions
  2019-08-21 19:09 ` [patch V2 34/38] posix-cpu-timers: Get rid of 64bit divisions Thomas Gleixner
@ 2019-08-26 22:51   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-26 22:51 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:21PM +0200, Thomas Gleixner wrote:
> Instead of dividing A to match the units of B it's more efficient to
> multiply B to match the units of A.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
> V2: Fix the dropped update of the expiry cache when the soft limit increased
> ---
>  kernel/time/posix-cpu-timers.c |   24 ++++++++++++++----------
>  1 file changed, 14 insertions(+), 10 deletions(-)
> 
> --- a/kernel/time/posix-cpu-timers.c
> +++ b/kernel/time/posix-cpu-timers.c
> @@ -798,10 +798,11 @@ static void check_thread_timers(struct t
>  	 */
>  	soft = task_rlimit(tsk, RLIMIT_RTTIME);
>  	if (soft != RLIM_INFINITY) {
> +		/* Task RT timeout is accounted in jiffies. RTTIME is usec */
> +		unsigned long rtim = tsk->rt.timeout * (USEC_PER_SEC / HZ);

jiffies_to_usecs() ?

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 35/38] posix-cpu-timers: Remove pointless comparisons
  2019-08-21 19:09 ` [patch V2 35/38] posix-cpu-timers: Remove pointless comparisons Thomas Gleixner
@ 2019-08-26 22:59   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-26 22:59 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:22PM +0200, Thomas Gleixner wrote:
> The soft RLIMIT expiry code checks whether the soft limit is greater than
> the hard limit. That's pointless because if the soft RLIMIT is greater than
> the hard RLIMIT then that code cannot be reached as the hard RLIMIT check
> is before that and already killed the process.
> 
> Remove it.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 36/38] posix-cpu-timers: Deduplicate rlimit handling
  2019-08-21 19:09 ` [patch V2 36/38] posix-cpu-timers: Deduplicate rlimit handling Thomas Gleixner
@ 2019-08-26 23:13   ` Frederic Weisbecker
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-26 23:13 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:23PM +0200, Thomas Gleixner wrote:
> Both thread and process expiry functions have the same functionality for
> sending signals for soft and hard RLIMITs duplicated in 4 different
> ways.
> 
> Split it out into a common function and cleanup the callsites.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 37/38] posix-cpu-timers: Move state tracking to struct posix_cputimers
  2019-08-21 19:09 ` [patch V2 37/38] posix-cpu-timers: Move state tracking to struct posix_cputimers Thomas Gleixner
@ 2019-08-26 23:28   ` Frederic Weisbecker
  2019-08-26 23:33     ` Thomas Gleixner
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 1 reply; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-26 23:28 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:24PM +0200, Thomas Gleixner wrote:
> Put it where it belongs and clean up the ifdeffery in fork completely.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
> V2: Adopt to the per clock base struct
> ---
>  include/linux/posix-timers.h   |    8 ++++
>  include/linux/sched/cputime.h  |    9 +++--
>  include/linux/sched/signal.h   |    6 ---
>  init/init_task.c               |    2 -
>  kernel/fork.c                  |    6 ---
>  kernel/time/posix-cpu-timers.c |   73 ++++++++++++++++++++++-------------------
>  6 files changed, 54 insertions(+), 50 deletions(-)
> 
> --- a/include/linux/posix-timers.h
> +++ b/include/linux/posix-timers.h
> @@ -77,15 +77,23 @@ struct posix_cputimer_base {
>  /**
>   * posix_cputimers - Container for posix CPU timer related data
>   * @bases:		Base container for posix CPU clocks
> + * @timers_active:	Timers are queued.
> + * @expiry_active:	Timer expiry is active. Used for
> + *			process wide timers to avoid multiple
> + *			task trying to handle expiry concurrently

So those two fields are also added to struct task_struct but unused there,
right?


>   *
>   * Used in task_struct and signal_struct
>   */
>  struct posix_cputimers {
>  	struct posix_cputimer_base	bases[CPUCLOCK_MAX];
> +	unsigned int			timers_active;
> +	unsigned int			expiry_active;
>  };

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 37/38] posix-cpu-timers: Move state tracking to struct posix_cputimers
  2019-08-26 23:28   ` Frederic Weisbecker
@ 2019-08-26 23:33     ` Thomas Gleixner
  0 siblings, 0 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-26 23:33 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Tue, 27 Aug 2019, Frederic Weisbecker wrote:
> On Wed, Aug 21, 2019 at 09:09:24PM +0200, Thomas Gleixner wrote:
> > Put it where it belongs and clean up the ifdeffery in fork completely.
> > 
> > Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> > ---
> > V2: Adopt to the per clock base struct
> > ---
> >  include/linux/posix-timers.h   |    8 ++++
> >  include/linux/sched/cputime.h  |    9 +++--
> >  include/linux/sched/signal.h   |    6 ---
> >  init/init_task.c               |    2 -
> >  kernel/fork.c                  |    6 ---
> >  kernel/time/posix-cpu-timers.c |   73 ++++++++++++++++++++++-------------------
> >  6 files changed, 54 insertions(+), 50 deletions(-)
> > 
> > --- a/include/linux/posix-timers.h
> > +++ b/include/linux/posix-timers.h
> > @@ -77,15 +77,23 @@ struct posix_cputimer_base {
> >  /**
> >   * posix_cputimers - Container for posix CPU timer related data
> >   * @bases:		Base container for posix CPU clocks
> > + * @timers_active:	Timers are queued.
> > + * @expiry_active:	Timer expiry is active. Used for
> > + *			process wide timers to avoid multiple
> > + *			task trying to handle expiry concurrently
> 
> So those two fields are also added to struct task_struct but unused there,
> right?

Yes. I did not come up with a smart way to avoid that, but lemme think
about it some more.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 38/38] posix-cpu-timers: Utilize timerqueue for storage
  2019-08-21 19:09 ` [patch V2 38/38] posix-cpu-timers: Utilize timerqueue for storage Thomas Gleixner
@ 2019-08-27  0:48   ` Frederic Weisbecker
  2019-08-27  6:08     ` Thomas Gleixner
  0 siblings, 1 reply; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-27  0:48 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Wed, Aug 21, 2019 at 09:09:25PM +0200, Thomas Gleixner wrote:
>  /**
> @@ -92,14 +130,10 @@ struct posix_cputimers {
>  
>  static inline void posix_cputimers_init(struct posix_cputimers *pct)
>  {
> -	pct->timers_active = 0;
> -	pct->expiry_active = 0;

No more need to initialize these?

> +	memset(pct->bases, 0, sizeof(pct->bases));
>  	pct->bases[0].nextevt = U64_MAX;
>  	pct->bases[1].nextevt = U64_MAX;
>  	pct->bases[2].nextevt = U64_MAX;
> -	INIT_LIST_HEAD(&pct->bases[0].cpu_timers);
> -	INIT_LIST_HEAD(&pct->bases[1].cpu_timers);
> -	INIT_LIST_HEAD(&pct->bases[2].cpu_timers);
>  }

[...]

> @@ -393,15 +395,15 @@ static int posix_cpu_timer_del(struct k_
>  	sighand = lock_task_sighand(p, &flags);
>  	if (unlikely(sighand == NULL)) {
>  		/*
> -		 * We raced with the reaping of the task.
> -		 * The deletion should have cleared us off the list.
> +		 * This raced with the reaping of the task. The exit cleanup
> +		 * should have removed this timer from the timer queue.
>  		 */
> -		WARN_ON_ONCE(!list_empty(&timer->it.cpu.entry));
> +		WARN_ON_ONCE(ctmr->head || timerqueue_node_queued(&ctmr->node));

Should we clear ctmr->head upon cleanup_timerqueue() ?

Thanks.


>  	} else {
>  		if (timer->it.cpu.firing)
>  			ret = TIMER_RETRY;
>  		else
> -			list_del(&timer->it.cpu.entry);
> +			cpu_timer_dequeue(ctmr);
>  
>  		unlock_task_sighand(p, &flags);
>  	}
> @@ -412,12 +414,12 @@ static int posix_cpu_timer_del(struct k_
>  	return ret;
>  }
>  
> -static void cleanup_timers_list(struct list_head *head)
> +static void cleanup_timerqueue(struct timerqueue_head *head)
>  {
> -	struct cpu_timer_list *timer, *next;
> +	struct timerqueue_node *node;
>  
> -	list_for_each_entry_safe(timer, next, head, entry)
> -		list_del_init(&timer->entry);
> +	while ((node = timerqueue_getnext(head)))
> +		timerqueue_del(head, node);
>  }


^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 38/38] posix-cpu-timers: Utilize timerqueue for storage
  2019-08-27  0:48   ` Frederic Weisbecker
@ 2019-08-27  6:08     ` Thomas Gleixner
  2019-08-27 13:17       ` Frederic Weisbecker
  0 siblings, 1 reply; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-27  6:08 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Tue, 27 Aug 2019, Frederic Weisbecker wrote:

> On Wed, Aug 21, 2019 at 09:09:25PM +0200, Thomas Gleixner wrote:
> >  /**
> > @@ -92,14 +130,10 @@ struct posix_cputimers {
> >  
> >  static inline void posix_cputimers_init(struct posix_cputimers *pct)
> >  {
> > -	pct->timers_active = 0;
> > -	pct->expiry_active = 0;
> 
> No more need to initialize these?
> 
> > +	memset(pct->bases, 0, sizeof(pct->bases));

memset() does that IIRC :)

> >  	pct->bases[0].nextevt = U64_MAX;
> >  	pct->bases[1].nextevt = U64_MAX;
> >  	pct->bases[2].nextevt = U64_MAX;
> > -	INIT_LIST_HEAD(&pct->bases[0].cpu_timers);
> > -	INIT_LIST_HEAD(&pct->bases[1].cpu_timers);
> > -	INIT_LIST_HEAD(&pct->bases[2].cpu_timers);
> >  }
> 
> [...]
> 
> > @@ -393,15 +395,15 @@ static int posix_cpu_timer_del(struct k_
> >  	sighand = lock_task_sighand(p, &flags);
> >  	if (unlikely(sighand == NULL)) {
> >  		/*
> > -		 * We raced with the reaping of the task.
> > -		 * The deletion should have cleared us off the list.
> > +		 * This raced with the reaping of the task. The exit cleanup
> > +		 * should have removed this timer from the timer queue.
> >  		 */
> > -		WARN_ON_ONCE(!list_empty(&timer->it.cpu.entry));
> > +		WARN_ON_ONCE(ctmr->head || timerqueue_node_queued(&ctmr->node));
> 
> Should we clear ctmr->head upon cleanup_timerqueue() ?

Probably.
 

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 38/38] posix-cpu-timers: Utilize timerqueue for storage
  2019-08-27  6:08     ` Thomas Gleixner
@ 2019-08-27 13:17       ` Frederic Weisbecker
  2019-08-27 13:46         ` Thomas Gleixner
  0 siblings, 1 reply; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-27 13:17 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Tue, Aug 27, 2019 at 08:08:06AM +0200, Thomas Gleixner wrote:
> On Tue, 27 Aug 2019, Frederic Weisbecker wrote:
> 
> > On Wed, Aug 21, 2019 at 09:09:25PM +0200, Thomas Gleixner wrote:
> > >  /**
> > > @@ -92,14 +130,10 @@ struct posix_cputimers {
> > >  
> > >  static inline void posix_cputimers_init(struct posix_cputimers *pct)
> > >  {
> > > -	pct->timers_active = 0;
> > > -	pct->expiry_active = 0;
> > 
> > No more need to initialize these?
> > 
> > > +	memset(pct->bases, 0, sizeof(pct->bases));
> 
> memset() does that IIRC :)

But those two fields aren't part of pct->bases, are they? :)

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V2 38/38] posix-cpu-timers: Utilize timerqueue for storage
  2019-08-27 13:17       ` Frederic Weisbecker
@ 2019-08-27 13:46         ` Thomas Gleixner
  2019-08-27 19:31           ` [patch V3 " Thomas Gleixner
  0 siblings, 1 reply; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-27 13:46 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Tue, 27 Aug 2019, Frederic Weisbecker wrote:
> On Tue, Aug 27, 2019 at 08:08:06AM +0200, Thomas Gleixner wrote:
> > On Tue, 27 Aug 2019, Frederic Weisbecker wrote:
> > 
> > > On Wed, Aug 21, 2019 at 09:09:25PM +0200, Thomas Gleixner wrote:
> > > >  /**
> > > > @@ -92,14 +130,10 @@ struct posix_cputimers {
> > > >  
> > > >  static inline void posix_cputimers_init(struct posix_cputimers *pct)
> > > >  {
> > > > -	pct->timers_active = 0;
> > > > -	pct->expiry_active = 0;
> > > 
> > > No more need to initialize these?
> > > 
> > > > +	memset(pct->bases, 0, sizeof(pct->bases));
> > 
> > memset() does that IIRC :)
> 
> But those two fields aren't part of pct->bases, are they? :)

Duh. I wanted to memset() the full pile obviously.


^ permalink raw reply	[flat|nested] 137+ messages in thread

* [patch V3 38/38] posix-cpu-timers: Utilize timerqueue for storage
  2019-08-27 13:46         ` Thomas Gleixner
@ 2019-08-27 19:31           ` Thomas Gleixner
  2019-08-27 22:23             ` Frederic Weisbecker
  2019-08-28 10:16             ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  0 siblings, 2 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-27 19:31 UTC (permalink / raw)
  To: Frederic Weisbecker
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

Using a linear O(N) search for timer insertion affects execution time and
D-cache footprint badly with a larger number of timers.

Switch the storage to a timerqueue which is already used for hrtimers and
alarmtimers. It does not affect the size of struct k_itimer as it.alarm is
still larger.

The extra list head for the expiry list will go away later once the expiry
is moved into task work context.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V2: Adopt to the per clock base struct
V3: Fixup memset() and clear cputtimer::head in cleanup_timerqueue()
---
 include/linux/posix-timers.h   |   65 ++++++++++----
 include/linux/timerqueue.h     |   10 ++
 kernel/time/posix-cpu-timers.c |  187 ++++++++++++++++++++---------------------
 3 files changed, 154 insertions(+), 108 deletions(-)

--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -5,17 +5,11 @@
 #include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/alarmtimer.h>
+#include <linux/timerqueue.h>
 
 struct kernel_siginfo;
 struct task_struct;
 
-struct cpu_timer_list {
-	struct list_head entry;
-	u64 expires;
-	struct task_struct *task;
-	int firing;
-};
-
 /*
  * Bit fields within a clockid:
  *
@@ -65,13 +59,57 @@ static inline int clockid_to_fd(const cl
 #ifdef CONFIG_POSIX_TIMERS
 
 /**
+ * cpu_timer - Posix CPU timer representation for k_itimer
+ * @node:	timerqueue node to queue in the task/sig
+ * @head:	timerqueue head on which this timer is queued
+ * @task:	Pointer to target task
+ * @elist:	List head for the expiry list
+ * @firing:	Timer is currently firing
+ */
+struct cpu_timer {
+	struct timerqueue_node	node;
+	struct timerqueue_head	*head;
+	struct task_struct	*task;
+	struct list_head	elist;
+	int			firing;
+};
+
+static inline bool cpu_timer_requeue(struct cpu_timer *ctmr)
+{
+	return timerqueue_add(ctmr->head, &ctmr->node);
+}
+
+static inline bool cpu_timer_enqueue(struct timerqueue_head *head,
+				     struct cpu_timer *ctmr)
+{
+	ctmr->head = head;
+	return timerqueue_add(head, &ctmr->node);
+}
+
+static inline void cpu_timer_dequeue(struct cpu_timer *ctmr)
+{
+	if (!RB_EMPTY_NODE(&ctmr->node.node))
+		timerqueue_del(ctmr->head, &ctmr->node);
+}
+
+static inline u64 cpu_timer_getexpires(struct cpu_timer *ctmr)
+{
+	return ctmr->node.expires;
+}
+
+static inline void cpu_timer_setexpires(struct cpu_timer *ctmr, u64 exp)
+{
+	ctmr->node.expires = exp;
+}
+
+/**
  * posix_cputimer_base - Container per posix CPU clock
  * @nextevt:		Earliest-expiration cache
- * @cpu_timers:		List heads to queue posix CPU timers
+ * @tqhead:		timerqueue head for cpu_timers
  */
 struct posix_cputimer_base {
 	u64			nextevt;
-	struct list_head	cpu_timers;
+	struct timerqueue_head	tqhead;
 };
 
 /**
@@ -92,14 +130,10 @@ struct posix_cputimers {
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
 {
-	pct->timers_active = 0;
-	pct->expiry_active = 0;
+	memset(pct, 0, sizeof(*pct));
 	pct->bases[0].nextevt = U64_MAX;
 	pct->bases[1].nextevt = U64_MAX;
 	pct->bases[2].nextevt = U64_MAX;
-	INIT_LIST_HEAD(&pct->bases[0].cpu_timers);
-	INIT_LIST_HEAD(&pct->bases[1].cpu_timers);
-	INIT_LIST_HEAD(&pct->bases[2].cpu_timers);
 }
 
 void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit);
@@ -113,7 +147,6 @@ static inline void posix_cputimers_rt_wa
 /* Init task static initializer */
 #define INIT_CPU_TIMERBASE(b) {						\
 	.nextevt	= U64_MAX,					\
-	.cpu_timers	= LIST_HEAD_INIT(b.cpu_timers),			\
 }
 
 #define INIT_CPU_TIMERBASES(b) {					\
@@ -182,7 +215,7 @@ struct k_itimer {
 		struct {
 			struct hrtimer	timer;
 		} real;
-		struct cpu_timer_list	cpu;
+		struct cpu_timer	cpu;
 		struct {
 			struct alarm	alarmtimer;
 		} alarm;
--- a/include/linux/timerqueue.h
+++ b/include/linux/timerqueue.h
@@ -43,6 +43,16 @@ static inline void timerqueue_init(struc
 	RB_CLEAR_NODE(&node->node);
 }
 
+static inline bool timerqueue_node_queued(struct timerqueue_node *node)
+{
+	return !RB_EMPTY_NODE(&node->node);
+}
+
+static inline bool timerqueue_node_expires(struct timerqueue_node *node)
+{
+	return node->expires;
+}
+
 static inline void timerqueue_init_head(struct timerqueue_head *head)
 {
 	head->rb_root = RB_ROOT_CACHED;
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -96,19 +96,19 @@ static inline int validate_clock_permiss
  * Update expiry time from increment, and increase overrun count,
  * given the current clock sample.
  */
-static void bump_cpu_timer(struct k_itimer *timer, u64 now)
+static u64 bump_cpu_timer(struct k_itimer *timer, u64 now)
 {
+	u64 delta, incr, expires = timer->it.cpu.node.expires;
 	int i;
-	u64 delta, incr;
 
 	if (!timer->it_interval)
-		return;
+		return expires;
 
-	if (now < timer->it.cpu.expires)
-		return;
+	if (now < expires)
+		return expires;
 
 	incr = timer->it_interval;
-	delta = now + incr - timer->it.cpu.expires;
+	delta = now + incr - expires;
 
 	/* Don't use (incr*2 < delta), incr*2 might overflow. */
 	for (i = 0; incr < delta - incr; i++)
@@ -118,10 +118,11 @@ static void bump_cpu_timer(struct k_itim
 		if (delta < incr)
 			continue;
 
-		timer->it.cpu.expires += incr;
+		timer->it.cpu.node.expires += incr;
 		timer->it_overrun += 1LL << i;
 		delta -= incr;
 	}
+	return timer->it.cpu.node.expires;
 }
 
 /* Check whether all cache entries contain U64_MAX, i.e. eternal expiry time */
@@ -365,7 +366,7 @@ static int posix_cpu_timer_create(struct
 		return -EINVAL;
 
 	new_timer->kclock = &clock_posix_cpu;
-	INIT_LIST_HEAD(&new_timer->it.cpu.entry);
+	timerqueue_init(&new_timer->it.cpu.node);
 	new_timer->it.cpu.task = p;
 	return 0;
 }
@@ -378,10 +379,11 @@ static int posix_cpu_timer_create(struct
  */
 static int posix_cpu_timer_del(struct k_itimer *timer)
 {
-	int ret = 0;
-	unsigned long flags;
+	struct cpu_timer *ctmr = &timer->it.cpu;
+	struct task_struct *p = ctmr->task;
 	struct sighand_struct *sighand;
-	struct task_struct *p = timer->it.cpu.task;
+	unsigned long flags;
+	int ret = 0;
 
 	if (WARN_ON_ONCE(!p))
 		return -EINVAL;
@@ -393,15 +395,15 @@ static int posix_cpu_timer_del(struct k_
 	sighand = lock_task_sighand(p, &flags);
 	if (unlikely(sighand == NULL)) {
 		/*
-		 * We raced with the reaping of the task.
-		 * The deletion should have cleared us off the list.
+		 * This raced with the reaping of the task. The exit cleanup
+		 * should have removed this timer from the timer queue.
 		 */
-		WARN_ON_ONCE(!list_empty(&timer->it.cpu.entry));
+		WARN_ON_ONCE(ctmr->head || timerqueue_node_queued(&ctmr->node));
 	} else {
 		if (timer->it.cpu.firing)
 			ret = TIMER_RETRY;
 		else
-			list_del(&timer->it.cpu.entry);
+			cpu_timer_dequeue(ctmr);
 
 		unlock_task_sighand(p, &flags);
 	}
@@ -412,12 +414,16 @@ static int posix_cpu_timer_del(struct k_
 	return ret;
 }
 
-static void cleanup_timers_list(struct list_head *head)
+static void cleanup_timerqueue(struct timerqueue_head *head)
 {
-	struct cpu_timer_list *timer, *next;
+	struct timerqueue_node *node;
+	struct cpu_timer *ctmr;
 
-	list_for_each_entry_safe(timer, next, head, entry)
-		list_del_init(&timer->entry);
+	while ((node = timerqueue_getnext(head))) {
+		timerqueue_del(head, node);
+		ctmr = container_of(next, struct cpu_timer, node);
+		ctmr->head = NULL;
+	}
 }
 
 /*
@@ -429,9 +435,9 @@ static void cleanup_timers_list(struct l
  */
 static void cleanup_timers(struct posix_cputimers *pct)
 {
-	cleanup_timers_list(&pct->bases[CPUCLOCK_PROF].cpu_timers);
-	cleanup_timers_list(&pct->bases[CPUCLOCK_VIRT].cpu_timers);
-	cleanup_timers_list(&pct->bases[CPUCLOCK_SCHED].cpu_timers);
+	cleanup_timerqueue(&pct->bases[CPUCLOCK_PROF].tqhead);
+	cleanup_timerqueue(&pct->bases[CPUCLOCK_VIRT].tqhead);
+	cleanup_timerqueue(&pct->bases[CPUCLOCK_SCHED].tqhead);
 }
 
 /*
@@ -454,28 +460,18 @@ void posix_cpu_timers_exit_group(struct
  */
 static void arm_timer(struct k_itimer *timer)
 {
-	struct cpu_timer_list *const nt = &timer->it.cpu;
 	int clkidx = CPUCLOCK_WHICH(timer->it_clock);
-	struct task_struct *p = timer->it.cpu.task;
-	u64 newexp = timer->it.cpu.expires;
+	struct cpu_timer *ctmr = &timer->it.cpu;
+	u64 newexp = cpu_timer_getexpires(ctmr);
+	struct task_struct *p = ctmr->task;
 	struct posix_cputimer_base *base;
-	struct list_head *head, *listpos;
-	struct cpu_timer_list *next;
 
 	if (CPUCLOCK_PERTHREAD(timer->it_clock))
 		base = p->posix_cputimers.bases + clkidx;
 	else
 		base = p->signal->posix_cputimers.bases + clkidx;
 
-	listpos = head = &base->cpu_timers;
-	list_for_each_entry(next,head, entry) {
-		if (nt->expires < next->expires)
-			break;
-		listpos = &next->entry;
-	}
-	list_add(&nt->entry, listpos);
-
-	if (listpos != head)
+	if (!cpu_timer_enqueue(&base->tqhead, ctmr))
 		return;
 
 	/*
@@ -498,24 +494,26 @@ static void arm_timer(struct k_itimer *t
  */
 static void cpu_timer_fire(struct k_itimer *timer)
 {
+	struct cpu_timer *ctmr = &timer->it.cpu;
+
 	if ((timer->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) {
 		/*
 		 * User don't want any signal.
 		 */
-		timer->it.cpu.expires = 0;
+		cpu_timer_setexpires(ctmr, 0);
 	} else if (unlikely(timer->sigq == NULL)) {
 		/*
 		 * This a special case for clock_nanosleep,
 		 * not a normal timer from sys_timer_create.
 		 */
 		wake_up_process(timer->it_process);
-		timer->it.cpu.expires = 0;
+		cpu_timer_setexpires(ctmr, 0);
 	} else if (!timer->it_interval) {
 		/*
 		 * One-shot timer.  Clear it as soon as it's fired.
 		 */
 		posix_timer_event(timer, 0);
-		timer->it.cpu.expires = 0;
+		cpu_timer_setexpires(ctmr, 0);
 	} else if (posix_timer_event(timer, ++timer->it_requeue_pending)) {
 		/*
 		 * The signal did not get queued because the signal
@@ -539,10 +537,11 @@ static int posix_cpu_timer_set(struct k_
 {
 	clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
 	u64 old_expires, new_expires, old_incr, val;
-	struct task_struct *p = timer->it.cpu.task;
+	struct cpu_timer *ctmr = &timer->it.cpu;
+	struct task_struct *p = ctmr->task;
 	struct sighand_struct *sighand;
 	unsigned long flags;
-	int ret;
+	int ret = 0;
 
 	if (WARN_ON_ONCE(!p))
 		return -EINVAL;
@@ -562,22 +561,21 @@ static int posix_cpu_timer_set(struct k_
 	 * If p has just been reaped, we can no
 	 * longer get any information about it at all.
 	 */
-	if (unlikely(sighand == NULL)) {
+	if (unlikely(sighand == NULL))
 		return -ESRCH;
-	}
 
 	/*
 	 * Disarm any old timer after extracting its expiry time.
 	 */
-
-	ret = 0;
 	old_incr = timer->it_interval;
-	old_expires = timer->it.cpu.expires;
+	old_expires = cpu_timer_getexpires(ctmr);
+
 	if (unlikely(timer->it.cpu.firing)) {
 		timer->it.cpu.firing = -1;
 		ret = TIMER_RETRY;
-	} else
-		list_del_init(&timer->it.cpu.entry);
+	} else {
+		cpu_timer_dequeue(ctmr);
+	}
 
 	/*
 	 * We need to sample the current value to convert the new
@@ -598,18 +596,16 @@ static int posix_cpu_timer_set(struct k_
 			old->it_value.tv_nsec = 0;
 		} else {
 			/*
-			 * Update the timer in case it has
-			 * overrun already.  If it has,
-			 * we'll report it as having overrun
-			 * and with the next reloaded timer
-			 * already ticking, though we are
-			 * swallowing that pending
-			 * notification here to install the
-			 * new setting.
+			 * Update the timer in case it has overrun already.
+			 * If it has, we'll report it as having overrun and
+			 * with the next reloaded timer already ticking,
+			 * though we are swallowing that pending
+			 * notification here to install the new setting.
 			 */
-			bump_cpu_timer(timer, val);
-			if (val < timer->it.cpu.expires) {
-				old_expires = timer->it.cpu.expires - val;
+			u64 exp = bump_cpu_timer(timer, val);
+
+			if (val < exp) {
+				old_expires = exp - val;
 				old->it_value = ns_to_timespec64(old_expires);
 			} else {
 				old->it_value.tv_nsec = 1;
@@ -638,7 +634,7 @@ static int posix_cpu_timer_set(struct k_
 	 * For a timer with no notification action, we don't actually
 	 * arm the timer (we'll just fake it for timer_gettime).
 	 */
-	timer->it.cpu.expires = new_expires;
+	cpu_timer_setexpires(ctmr, new_expires);
 	if (new_expires != 0 && val < new_expires) {
 		arm_timer(timer);
 	}
@@ -680,8 +676,9 @@ static int posix_cpu_timer_set(struct k_
 static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp)
 {
 	clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
-	struct task_struct *p = timer->it.cpu.task;
-	u64 now;
+	struct cpu_timer *ctmr = &timer->it.cpu;
+	u64 now, expires = cpu_timer_getexpires(ctmr);
+	struct task_struct *p = ctmr->task;
 
 	if (WARN_ON_ONCE(!p))
 		return;
@@ -691,7 +688,7 @@ static void posix_cpu_timer_get(struct k
 	 */
 	itp->it_interval = ktime_to_timespec64(timer->it_interval);
 
-	if (!timer->it.cpu.expires)
+	if (!expires)
 		return;
 
 	/*
@@ -713,9 +710,9 @@ static void posix_cpu_timer_get(struct k
 			/*
 			 * The process has been reaped.
 			 * We can't even collect a sample any more.
-			 * Call the timer disarmed, nothing else to do.
+			 * Disarm the timer, nothing else to do.
 			 */
-			timer->it.cpu.expires = 0;
+			cpu_timer_setexpires(ctmr, 0);
 			return;
 		} else {
 			now = cpu_clock_sample_group(clkid, p, false);
@@ -723,8 +720,8 @@ static void posix_cpu_timer_get(struct k
 		}
 	}
 
-	if (now < timer->it.cpu.expires) {
-		itp->it_value = ns_to_timespec64(timer->it.cpu.expires - now);
+	if (now < expires) {
+		itp->it_value = ns_to_timespec64(expires - now);
 	} else {
 		/*
 		 * The timer should have expired already, but the firing
@@ -735,37 +732,41 @@ static void posix_cpu_timer_get(struct k
 	}
 }
 
-static unsigned long long
-check_timers_list(struct list_head *timers,
-		  struct list_head *firing,
-		  unsigned long long curr)
-{
-	int maxfire = 20;
-
-	while (!list_empty(timers)) {
-		struct cpu_timer_list *t;
+#define MAX_COLLECTED	20
 
-		t = list_first_entry(timers, struct cpu_timer_list, entry);
-
-		if (!--maxfire || curr < t->expires)
-			return t->expires;
+static u64 collect_timerqueue(struct timerqueue_head *head,
+			      struct list_head *firing, u64 now)
+{
+	struct timerqueue_node *next;
+	int i = 0;
 
-		t->firing = 1;
-		list_move_tail(&t->entry, firing);
+	while ((next = timerqueue_getnext(head))) {
+		struct cpu_timer *ctmr;
+		u64 expires;
+
+		ctmr = container_of(next, struct cpu_timer, node);
+		expires = cpu_timer_getexpires(ctmr);
+		/* Limit the number of timers to expire at once */
+		if (++i == MAX_COLLECTED || now < expires)
+			return expires;
+
+		ctmr->firing = 1;
+		cpu_timer_dequeue(ctmr);
+		list_add_tail(&ctmr->elist, firing);
 	}
 
 	return U64_MAX;
 }
 
-static void collect_posix_cputimers(struct posix_cputimers *pct,
-				    u64 *samples, struct list_head *firing)
+static void collect_posix_cputimers(struct posix_cputimers *pct, u64 *samples,
+				    struct list_head *firing)
 {
 	struct posix_cputimer_base *base = pct->bases;
 	int i;
 
 	for (i = 0; i < CPUCLOCK_MAX; i++, base++) {
-		base->nextevt = check_timers_list(&base->cpu_timers, firing,
-						   samples[i]);
+		base->nextevt = collect_timerqueue(&base->tqhead, firing,
+						    samples[i]);
 	}
 }
 
@@ -948,7 +949,8 @@ static void check_process_timers(struct
 static void posix_cpu_timer_rearm(struct k_itimer *timer)
 {
 	clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
-	struct task_struct *p = timer->it.cpu.task;
+	struct cpu_timer *ctmr = &timer->it.cpu;
+	struct task_struct *p = ctmr->task;
 	struct sighand_struct *sighand;
 	unsigned long flags;
 	u64 now;
@@ -980,7 +982,7 @@ static void posix_cpu_timer_rearm(struct
 			 * The process has been reaped.
 			 * We can't even collect a sample any more.
 			 */
-			timer->it.cpu.expires = 0;
+			cpu_timer_setexpires(ctmr, 0);
 			return;
 		} else if (unlikely(p->exit_state) && thread_group_empty(p)) {
 			/* If the process is dying, no need to rearm */
@@ -1124,11 +1126,11 @@ void run_posix_cpu_timers(void)
 	 * each timer's lock before clearing its firing flag, so no
 	 * timer call will interfere.
 	 */
-	list_for_each_entry_safe(timer, next, &firing, it.cpu.entry) {
+	list_for_each_entry_safe(timer, next, &firing, it.cpu.elist) {
 		int cpu_firing;
 
 		spin_lock(&timer->it_lock);
-		list_del_init(&timer->it.cpu.entry);
+		list_del_init(&timer->it.cpu.elist);
 		cpu_firing = timer->it.cpu.firing;
 		timer->it.cpu.firing = 0;
 		/*
@@ -1204,6 +1206,7 @@ static int do_cpu_nanosleep(const clocki
 	timer.it_overrun = -1;
 	error = posix_cpu_timer_create(&timer);
 	timer.it_process = current;
+
 	if (!error) {
 		static struct itimerspec64 zero_it;
 		struct restart_block *restart;
@@ -1219,7 +1222,7 @@ static int do_cpu_nanosleep(const clocki
 		}
 
 		while (!signal_pending(current)) {
-			if (timer.it.cpu.expires == 0) {
+			if (!cpu_timer_getexpires(&timer.it.cpu)) {
 				/*
 				 * Our timer fired and was reset, below
 				 * deletion can not fail.
@@ -1241,7 +1244,7 @@ static int do_cpu_nanosleep(const clocki
 		/*
 		 * We were interrupted by a signal.
 		 */
-		expires = timer.it.cpu.expires;
+		expires = cpu_timer_getexpires(&timer.it.cpu);
 		error = posix_cpu_timer_set(&timer, 0, &zero_it, &it);
 		if (!error) {
 			/*

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [patch V3 38/38] posix-cpu-timers: Utilize timerqueue for storage
  2019-08-27 19:31           ` [patch V3 " Thomas Gleixner
@ 2019-08-27 22:23             ` Frederic Weisbecker
  2019-08-28 10:16             ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: Frederic Weisbecker @ 2019-08-27 22:23 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, Oleg Nesterov, Ingo Molnar, Peter Zijlstra, John Stultz,
	Anna-Maria Behnsen, Christoph Hellwig

On Tue, Aug 27, 2019 at 09:31:02PM +0200, Thomas Gleixner wrote:
> Using a linear O(N) search for timer insertion affects execution time and
> D-cache footprint badly with a larger number of timers.
> 
> Switch the storage to a timerqueue which is already used for hrtimers and
> alarmtimers. It does not affect the size of struct k_itimer as it.alarm is
> still larger.
> 
> The extra list head for the expiry list will go away later once the expiry
> is moved into task work context.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
> V2: Adopt to the per clock base struct
> V3: Fixup memset() and clear cputtimer::head in cleanup_timerqueue()

Reviewed-by: Frederic Weisbecker <frederic@kernel.org>

^ permalink raw reply	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Provide task validation functions
  2019-08-21 19:08 ` [patch V2 01/38] posix-cpu-timers: Provide task validation functions Thomas Gleixner
  2019-08-21 22:33   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     6ae40e3fdcd33a6ff3c490b9302d6a1861093f65
Gitweb:        https://git.kernel.org/tip/6ae40e3fdcd33a6ff3c490b9302d6a1861093f65
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:08:48 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:24 +02:00

posix-cpu-timers: Provide task validation functions

The code contains three slightly different copies of validating whether a
given clock resolves to a valid task and whether the current caller has
permissions to access it.

Create central functions. Replace check_clock() as a first step and rename
it to something sensible.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190821192919.326097175@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 65 ++++++++++++++++++++++-----------
 1 file changed, 44 insertions(+), 21 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 387e0e8..b06ed8b 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -35,27 +35,52 @@ void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new)
 	spin_unlock_irq(&task->sighand->siglock);
 }
 
-static int check_clock(const clockid_t which_clock)
+/*
+ * Functions for validating access to tasks.
+ */
+static struct task_struct *lookup_task(const pid_t pid, bool thread)
 {
-	int error = 0;
 	struct task_struct *p;
-	const pid_t pid = CPUCLOCK_PID(which_clock);
 
-	if (CPUCLOCK_WHICH(which_clock) >= CPUCLOCK_MAX)
-		return -EINVAL;
+	if (!pid)
+		return thread ? current : current->group_leader;
+
+	p = find_task_by_vpid(pid);
+	if (!p || p == current)
+		return p;
+	if (thread)
+		return same_thread_group(p, current) ? p : NULL;
+	if (p == current)
+		return p;
+	return has_group_leader_pid(p) ? p : NULL;
+}
+
+static struct task_struct *__get_task_for_clock(const clockid_t clock,
+						bool getref)
+{
+	const bool thread = !!CPUCLOCK_PERTHREAD(clock);
+	const pid_t pid = CPUCLOCK_PID(clock);
+	struct task_struct *p;
 
-	if (pid == 0)
-		return 0;
+	if (CPUCLOCK_WHICH(clock) >= CPUCLOCK_MAX)
+		return NULL;
 
 	rcu_read_lock();
-	p = find_task_by_vpid(pid);
-	if (!p || !(CPUCLOCK_PERTHREAD(which_clock) ?
-		   same_thread_group(p, current) : has_group_leader_pid(p))) {
-		error = -EINVAL;
-	}
+	p = lookup_task(pid, thread);
+	if (p && getref)
+		get_task_struct(p);
 	rcu_read_unlock();
+	return p;
+}
 
-	return error;
+static inline struct task_struct *get_task_for_clock(const clockid_t clock)
+{
+	return __get_task_for_clock(clock, true);
+}
+
+static inline int validate_clock_permissions(const clockid_t clock)
+{
+	return __get_task_for_clock(clock, false) ? 0 : -EINVAL;
 }
 
 /*
@@ -125,7 +150,8 @@ static inline u64 virt_ticks(struct task_struct *p)
 static int
 posix_cpu_clock_getres(const clockid_t which_clock, struct timespec64 *tp)
 {
-	int error = check_clock(which_clock);
+	int error = validate_clock_permissions(which_clock);
+
 	if (!error) {
 		tp->tv_sec = 0;
 		tp->tv_nsec = ((NSEC_PER_SEC + HZ - 1) / HZ);
@@ -142,20 +168,17 @@ posix_cpu_clock_getres(const clockid_t which_clock, struct timespec64 *tp)
 }
 
 static int
-posix_cpu_clock_set(const clockid_t which_clock, const struct timespec64 *tp)
+posix_cpu_clock_set(const clockid_t clock, const struct timespec64 *tp)
 {
+	int error = validate_clock_permissions(clock);
+
 	/*
 	 * You can never reset a CPU clock, but we check for other errors
 	 * in the call before failing with EPERM.
 	 */
-	int error = check_clock(which_clock);
-	if (error == 0) {
-		error = -EPERM;
-	}
-	return error;
+	return error ? : -EPERM;
 }
 
-
 /*
  * Sample a per-thread clock for the given task.
  */

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Use common permission check in posix_cpu_clock_get()
  2019-08-21 19:08 ` [patch V2 02/38] posix-cpu-timers: Use common permission check in posix_cpu_clock_get() Thomas Gleixner
  2019-08-21 23:40   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  2019-08-29 11:00     ` kbuild test robot
  2019-08-29 11:23     ` kbuild test robot
  1 sibling, 2 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     bfcf3e92c6c07cd1084624bad5622f3dad96328c
Gitweb:        https://git.kernel.org/tip/bfcf3e92c6c07cd1084624bad5622f3dad96328c
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:08:49 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:25 +02:00

posix-cpu-timers: Use common permission check in posix_cpu_clock_get()

Replace the next slightly different copy of permission checks. That also
removes the necessarity to check the return value of the sample functions
because the clock id is already validated.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192919.414813172@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 57 ++++++++-------------------------
 1 file changed, 14 insertions(+), 43 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index b06ed8b..eb11117 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -289,53 +289,24 @@ static int cpu_clock_sample_group(const clockid_t which_clock,
 	return 0;
 }
 
-static int posix_cpu_clock_get_task(struct task_struct *tsk,
-				    const clockid_t which_clock,
-				    struct timespec64 *tp)
+static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)
 {
-	int err = -EINVAL;
-	u64 rtn;
-
-	if (CPUCLOCK_PERTHREAD(which_clock)) {
-		if (same_thread_group(tsk, current))
-			err = cpu_clock_sample(which_clock, tsk, &rtn);
-	} else {
-		if (tsk == current || thread_group_leader(tsk))
-			err = cpu_clock_sample_group(which_clock, tsk, &rtn);
-	}
-
-	if (!err)
-		*tp = ns_to_timespec64(rtn);
+	const clockid_t clkid = CPUCLOCK_WHICH(clock);
+	struct task_struct *tsk;
+	u64 t;
 
-	return err;
-}
-
-
-static int posix_cpu_clock_get(const clockid_t which_clock, struct timespec64 *tp)
-{
-	const pid_t pid = CPUCLOCK_PID(which_clock);
-	int err = -EINVAL;
+	tsk = get_task_for_clock(clock);
+	if (!tsk)
+		return -EINVAL;
 
-	if (pid == 0) {
-		/*
-		 * Special case constant value for our own clocks.
-		 * We don't have to do any lookup to find ourselves.
-		 */
-		err = posix_cpu_clock_get_task(current, which_clock, tp);
-	} else {
-		/*
-		 * Find the given PID, and validate that the caller
-		 * should be able to see it.
-		 */
-		struct task_struct *p;
-		rcu_read_lock();
-		p = find_task_by_vpid(pid);
-		if (p)
-			err = posix_cpu_clock_get_task(p, which_clock, tp);
-		rcu_read_unlock();
-	}
+	if (CPUCLOCK_PERTHREAD(clock))
+		cpu_clock_sample(clkid, tsk, &t);
+	else
+		cpu_clock_sample_group(clkid, tsk, &t);
+	put_task_struct(tsk);
 
-	return err;
+	*tp = ns_to_timespec64(t);
+	return 0;
 }
 
 /*

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Use common permission check in posix_cpu_timer_create()
  2019-08-21 19:08 ` [patch V2 03/38] posix-cpu-timers: Use common permission check in posix_cpu_timer_create() Thomas Gleixner
  2019-08-21 23:49   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     e5a8b65b4cb2fe024b83bdec0424269949cc0a27
Gitweb:        https://git.kernel.org/tip/e5a8b65b4cb2fe024b83bdec0424269949cc0a27
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:08:50 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:25 +02:00

posix-cpu-timers: Use common permission check in posix_cpu_timer_create()

Yet another copy of the same thing gone...

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192919.505833418@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 35 ++-------------------------------
 1 file changed, 3 insertions(+), 32 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index eb11117..4426a0f 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -316,44 +316,15 @@ static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)
  */
 static int posix_cpu_timer_create(struct k_itimer *new_timer)
 {
-	int ret = 0;
-	const pid_t pid = CPUCLOCK_PID(new_timer->it_clock);
-	struct task_struct *p;
+	struct task_struct *p = get_task_for_clock(new_timer->it_clock);
 
-	if (CPUCLOCK_WHICH(new_timer->it_clock) >= CPUCLOCK_MAX)
+	if (!p)
 		return -EINVAL;
 
 	new_timer->kclock = &clock_posix_cpu;
-
 	INIT_LIST_HEAD(&new_timer->it.cpu.entry);
-
-	rcu_read_lock();
-	if (CPUCLOCK_PERTHREAD(new_timer->it_clock)) {
-		if (pid == 0) {
-			p = current;
-		} else {
-			p = find_task_by_vpid(pid);
-			if (p && !same_thread_group(p, current))
-				p = NULL;
-		}
-	} else {
-		if (pid == 0) {
-			p = current->group_leader;
-		} else {
-			p = find_task_by_vpid(pid);
-			if (p && !has_group_leader_pid(p))
-				p = NULL;
-		}
-	}
 	new_timer->it.cpu.task = p;
-	if (p) {
-		get_task_struct(p);
-	} else {
-		ret = -EINVAL;
-	}
-	rcu_read_unlock();
-
-	return ret;
+	return 0;
 }
 
 /*

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Provide quick sample function for itimer
  2019-08-21 19:08 ` [patch V2 04/38] posix-cpu-timers: Provide quick sample function for itimer Thomas Gleixner
  2019-08-22 12:13   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     19298fbf453c90a6cf72288155f80c6f55e9139d
Gitweb:        https://git.kernel.org/tip/19298fbf453c90a6cf72288155f80c6f55e9139d
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:08:51 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:26 +02:00

posix-cpu-timers: Provide quick sample function for itimer

get_itimer() needs a sample of the current thread group cputime. It invokes
thread_group_cputimer() - which is a misnomer. That function also starts
eventually the group cputime accouting which is bogus because the
accounting is already active when a timer is armed.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192919.599658199@linutronix.de

---
 include/linux/sched/cputime.h  |  2 +-
 kernel/time/posix-cpu-timers.c | 21 +++++++++++++++++++++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/include/linux/sched/cputime.h b/include/linux/sched/cputime.h
index 53f883f..6de7b38 100644
--- a/include/linux/sched/cputime.h
+++ b/include/linux/sched/cputime.h
@@ -62,7 +62,7 @@ extern void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev,
  */
 void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times);
 void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times);
-
+void thread_group_sample_cputime(struct task_struct *tsk, struct task_cputime *times);
 
 /*
  * The following are functions that support scheduler-internal time accounting.
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 4426a0f..c22b6b6 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -232,6 +232,27 @@ static inline void sample_cputime_atomic(struct task_cputime *times,
 	times->sum_exec_runtime = atomic64_read(&atomic_times->sum_exec_runtime);
 }
 
+/**
+ * thread_group_sample_cputime - Sample cputime for a given task
+ * @tsk:	Task for which cputime needs to be started
+ * @iimes:	Storage for time samples
+ *
+ * Called from sys_getitimer() to calculate the expiry time of an active
+ * timer. That means group cputime accounting is already active. Called
+ * with task sighand lock held.
+ *
+ * Updates @times with an uptodate sample of the thread group cputimes.
+ */
+void thread_group_sample_cputime(struct task_struct *tsk,
+				struct task_cputime *times)
+{
+	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
+
+	WARN_ON_ONCE(!cputimer->running);
+
+	sample_cputime_atomic(times, &cputimer->cputime_atomic);
+}
+
 void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
 {
 	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] itimers: Use quick sample function
  2019-08-21 19:08 ` [patch V2 05/38] itimers: Use quick sample function Thomas Gleixner
  2019-08-22 12:15   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  2019-08-29 23:47     ` kbuild test robot
  1 sibling, 1 reply; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     a34360d42434bbf28c0f375444c52c154ae3e6cf
Gitweb:        https://git.kernel.org/tip/a34360d42434bbf28c0f375444c52c154ae3e6cf
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:08:52 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:26 +02:00

itimers: Use quick sample function

get_itimer() locks sighand lock and checks whether the timer is already
expired. If it is not expired then the thread group cputime accounting is
already enabled. Use the sampling function not the one which is meant for
starting a timer.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192919.689713638@linutronix.de

---
 kernel/time/itimer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/time/itimer.c b/kernel/time/itimer.c
index 9d26fd4..ae04bc2 100644
--- a/kernel/time/itimer.c
+++ b/kernel/time/itimer.c
@@ -58,7 +58,7 @@ static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
 		struct task_cputime cputime;
 		u64 t;
 
-		thread_group_cputimer(tsk, &cputime);
+		thread_group_sample_cputime(tsk, &cputime);
 		if (clock_id == CPUCLOCK_PROF)
 			t = cputime.utime + cputime.stime;
 		else

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Sample directly in timer check
  2019-08-21 19:08 ` [patch V2 06/38] posix-cpu-timers: Sample directly in timer check Thomas Gleixner
  2019-08-22 12:30   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     a324956fae05d863386c682830e917f6685f1d4f
Gitweb:        https://git.kernel.org/tip/a324956fae05d863386c682830e917f6685f1d4f
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:08:53 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:27 +02:00

posix-cpu-timers: Sample directly in timer check

The thread group accounting is active, otherwise the expiry function would
not be running. Sample the thread group time directly.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192919.780348088@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index c22b6b6..cb73678 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -914,16 +914,17 @@ static void check_process_timers(struct task_struct *tsk,
 	if (!READ_ONCE(tsk->signal->cputimer.running))
 		return;
 
-        /*
+       /*
 	 * Signify that a thread is checking for process timers.
 	 * Write access to this field is protected by the sighand lock.
 	 */
 	sig->cputimer.checking_timer = true;
 
 	/*
-	 * Collect the current process totals.
+	 * Collect the current process totals. Group accounting is active
+	 * so the sample can be taken directly.
 	 */
-	thread_group_cputimer(tsk, &cputime);
+	sample_cputime_atomic(&cputime, &sig->cputimer.cputime_atomic);
 	utime = cputime.utime;
 	ptime = utime + cputime.stime;
 	sum_sched_runtime = cputime.sum_exec_runtime;

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Rename thread_group_cputimer() and make it static
  2019-08-21 19:08 ` [patch V2 07/38] posix-cpu-timers: Rename thread_group_cputimer() and make it static Thomas Gleixner
  2019-08-22 12:41   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     c506bef424ca282f2ad357e86fee940c69018974
Gitweb:        https://git.kernel.org/tip/c506bef424ca282f2ad357e86fee940c69018974
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:08:54 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:27 +02:00

posix-cpu-timers: Rename thread_group_cputimer() and make it static

thread_group_cputimer() is a complete misnomer. The function does two things:

 - For arming process wide timers it makes sure that the atomic time
   storage is up to date. If no cpu timer is armed yet, then the atomic
   time storage is not updated by the scheduler for performance reasons.

   In that case a full summing up of all threads needs to be done and the
   update needs to be enabled.

- Samples the current time into the caller supplied storage.

Rename it to thread_group_start_cputime(), make it static and fixup the
callsite.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192919.869350319@linutronix.de

---
 include/linux/sched/cputime.h  |  1 -
 kernel/time/posix-cpu-timers.c | 17 +++++++++++++++--
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/include/linux/sched/cputime.h b/include/linux/sched/cputime.h
index 6de7b38..2638fd0 100644
--- a/include/linux/sched/cputime.h
+++ b/include/linux/sched/cputime.h
@@ -61,7 +61,6 @@ extern void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev,
  * Thread group CPU time accounting.
  */
 void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times);
-void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times);
 void thread_group_sample_cputime(struct task_struct *tsk, struct task_cputime *times);
 
 /*
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index cb73678..def225a 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -253,7 +253,20 @@ void thread_group_sample_cputime(struct task_struct *tsk,
 	sample_cputime_atomic(times, &cputimer->cputime_atomic);
 }
 
-void thread_group_cputimer(struct task_struct *tsk, struct task_cputime *times)
+/**
+ * thread_group_start_cputime - Start cputime and return a sample
+ * @tsk:	Task for which cputime needs to be started
+ * @iimes:	Storage for time samples
+ *
+ * The thread group cputime accouting is avoided when there are no posix
+ * CPU timers armed. Before starting a timer it's required to check whether
+ * the time accounting is active. If not, a full update of the atomic
+ * accounting store needs to be done and the accounting enabled.
+ *
+ * Updates @times with an uptodate sample of the thread group cputimes.
+ */
+static void
+thread_group_start_cputime(struct task_struct *tsk, struct task_cputime *times)
 {
 	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
 	struct task_cputime sum;
@@ -536,7 +549,7 @@ static int cpu_timer_sample_group(const clockid_t which_clock,
 {
 	struct task_cputime cputime;
 
-	thread_group_cputimer(p, &cputime);
+	thread_group_start_cputime(p, &cputime);
 	switch (CPUCLOCK_WHICH(which_clock)) {
 	default:
 		return -EINVAL;

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Consolidate thread group sample code
  2019-08-21 19:08 ` [patch V2 08/38] posix-cpu-timers: Consolidate thread group sample code Thomas Gleixner
  2019-08-22 13:49   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     24ab7f5a7b2c917e89fc6a87252f18faff91d6ce
Gitweb:        https://git.kernel.org/tip/24ab7f5a7b2c917e89fc6a87252f18faff91d6ce
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:08:55 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:28 +02:00

posix-cpu-timers: Consolidate thread group sample code

cpu_clock_sample_group() and cpu_timer_sample_group() are almost the
same. Before the rename one called thread_group_cputimer() and the other
thread_group_cputime(). Really intuitive function names.

Consolidate the functions and also avoid the thread traversal when
the thread group's accounting is already active.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192919.960966884@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 59 +++++++++++----------------------
 1 file changed, 20 insertions(+), 39 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index def225a..a9003b2 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -294,29 +294,37 @@ thread_group_start_cputime(struct task_struct *tsk, struct task_cputime *times)
 }
 
 /*
- * Sample a process (thread group) clock for the given group_leader task.
- * Must be called with task sighand lock held for safe while_each_thread()
- * traversal.
+ * Sample a process (thread group) clock for the given task clkid. If the
+ * group's cputime accounting is already enabled, read the atomic
+ * store. Otherwise a full update is required.  Task's sighand lock must be
+ * held to protect the task traversal on a full update.
  */
 static int cpu_clock_sample_group(const clockid_t which_clock,
 				  struct task_struct *p,
-				  u64 *sample)
+				  u64 *sample, bool start)
 {
+	struct thread_group_cputimer *cputimer = &p->signal->cputimer;
 	struct task_cputime cputime;
 
+	if (!READ_ONCE(cputimer->running)) {
+		if (start)
+			thread_group_start_cputime(p, &cputime);
+		else
+			thread_group_cputime(p, &cputime);
+	} else {
+		sample_cputime_atomic(&cputime, &cputimer->cputime_atomic);
+	}
+
 	switch (CPUCLOCK_WHICH(which_clock)) {
 	default:
 		return -EINVAL;
 	case CPUCLOCK_PROF:
-		thread_group_cputime(p, &cputime);
 		*sample = cputime.utime + cputime.stime;
 		break;
 	case CPUCLOCK_VIRT:
-		thread_group_cputime(p, &cputime);
 		*sample = cputime.utime;
 		break;
 	case CPUCLOCK_SCHED:
-		thread_group_cputime(p, &cputime);
 		*sample = cputime.sum_exec_runtime;
 		break;
 	}
@@ -336,7 +344,7 @@ static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)
 	if (CPUCLOCK_PERTHREAD(clock))
 		cpu_clock_sample(clkid, tsk, &t);
 	else
-		cpu_clock_sample_group(clkid, tsk, &t);
+		cpu_clock_sample_group(clkid, tsk, &t, false);
 	put_task_struct(tsk);
 
 	*tp = ns_to_timespec64(t);
@@ -540,33 +548,6 @@ static void cpu_timer_fire(struct k_itimer *timer)
 }
 
 /*
- * Sample a process (thread group) timer for the given group_leader task.
- * Must be called with task sighand lock held for safe while_each_thread()
- * traversal.
- */
-static int cpu_timer_sample_group(const clockid_t which_clock,
-				  struct task_struct *p, u64 *sample)
-{
-	struct task_cputime cputime;
-
-	thread_group_start_cputime(p, &cputime);
-	switch (CPUCLOCK_WHICH(which_clock)) {
-	default:
-		return -EINVAL;
-	case CPUCLOCK_PROF:
-		*sample = cputime.utime + cputime.stime;
-		break;
-	case CPUCLOCK_VIRT:
-		*sample = cputime.utime;
-		break;
-	case CPUCLOCK_SCHED:
-		*sample = cputime.sum_exec_runtime;
-		break;
-	}
-	return 0;
-}
-
-/*
  * Guts of sys_timer_settime for CPU timers.
  * This is called with the timer locked and interrupts disabled.
  * If we return TIMER_RETRY, it's necessary to release the timer's lock
@@ -627,7 +608,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
 		cpu_clock_sample(timer->it_clock, p, &val);
 	} else {
-		cpu_timer_sample_group(timer->it_clock, p, &val);
+		cpu_clock_sample_group(timer->it_clock, p, &val, true);
 	}
 
 	if (old) {
@@ -755,7 +736,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
 			timer->it.cpu.expires = 0;
 			return;
 		} else {
-			cpu_timer_sample_group(timer->it_clock, p, &now);
+			cpu_clock_sample_group(timer->it_clock, p, &now, false);
 			unlock_task_sighand(p, &flags);
 		}
 	}
@@ -1042,7 +1023,7 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
 			/* If the process is dying, no need to rearm */
 			goto unlock;
 		}
-		cpu_timer_sample_group(timer->it_clock, p, &now);
+		cpu_clock_sample_group(timer->it_clock, p, &now, true);
 		bump_cpu_timer(timer, now);
 		/* Leave the sighand locked for the call below.  */
 	}
@@ -1211,7 +1192,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
 	if (WARN_ON_ONCE(clock_idx >= CPUCLOCK_SCHED))
 		return;
 
-	ret = cpu_timer_sample_group(clock_idx, tsk, &now);
+	ret = cpu_clock_sample_group(clock_idx, tsk, &now, true);
 
 	if (oldval && ret != -EINVAL) {
 		/*

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Use clock ID in posix_cpu_timer_set()
  2019-08-21 19:08 ` [patch V2 09/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_set() Thomas Gleixner
  2019-08-22 13:58   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     c7a37c6f4c651a531101c5721814333bae2804ec
Gitweb:        https://git.kernel.org/tip/c7a37c6f4c651a531101c5721814333bae2804ec
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:08:56 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:28 +02:00

posix-cpu-timers: Use clock ID in posix_cpu_timer_set()

Extract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it
as argument to the sample functions. That allows to simplify them once all
callers are fixed.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192920.050770464@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index a9003b2..12561f8 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -556,10 +556,11 @@ static void cpu_timer_fire(struct k_itimer *timer)
 static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
 			       struct itimerspec64 *new, struct itimerspec64 *old)
 {
-	unsigned long flags;
-	struct sighand_struct *sighand;
-	struct task_struct *p = timer->it.cpu.task;
+	clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
 	u64 old_expires, new_expires, old_incr, val;
+	struct task_struct *p = timer->it.cpu.task;
+	struct sighand_struct *sighand;
+	unsigned long flags;
 	int ret;
 
 	if (WARN_ON_ONCE(!p))
@@ -606,9 +607,9 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
 	 * check if it's already passed.  In short, we need a sample.
 	 */
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		cpu_clock_sample(timer->it_clock, p, &val);
+		cpu_clock_sample(clkid, p, &val);
 	} else {
-		cpu_clock_sample_group(timer->it_clock, p, &val, true);
+		cpu_clock_sample_group(clkid, p, &val, true);
 	}
 
 	if (old) {

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Remove pointless return value check
  2019-08-21 19:08 ` [patch V2 12/38] posix-cpu-timers: Remove pointless return value check Thomas Gleixner
  2019-08-22 14:15   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     5405d0051f7ca820d1781d87baf4d730ff58f208
Gitweb:        https://git.kernel.org/tip/5405d0051f7ca820d1781d87baf4d730ff58f208
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:08:59 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:30 +02:00

posix-cpu-timers: Remove pointless return value check

set_process_cpu_timer() checks already whether the clock id is valid. No
point in checking the return value of the sample function. That allows to
simplify the sample function later.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192920.339725769@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index aff7e3b..5944b74 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1190,14 +1190,13 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
 			   u64 *newval, u64 *oldval)
 {
 	u64 now;
-	int ret;
 
 	if (WARN_ON_ONCE(clock_idx >= CPUCLOCK_SCHED))
 		return;
 
-	ret = cpu_clock_sample_group(clock_idx, tsk, &now, true);
+	cpu_clock_sample_group(clock_idx, tsk, &now, true);
 
-	if (oldval && ret != -EINVAL) {
+	if (oldval) {
 		/*
 		 * We are setting itimer. The *oldval is absolute and we update
 		 * it to be relative, *newval argument is relative and we update

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Use clock ID in posix_cpu_timer_rearm()
  2019-08-21 19:08 ` [patch V2 11/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_rearm() Thomas Gleixner
  2019-08-22 14:12   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     da020ce406b2a9b714b82de9123a4c5a4848647b
Gitweb:        https://git.kernel.org/tip/da020ce406b2a9b714b82de9123a4c5a4848647b
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:08:58 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:29 +02:00

posix-cpu-timers: Use clock ID in posix_cpu_timer_rearm()

Extract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it
as argument to the sample functions. That allows to simplify them once all
callers are fixed.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192920.245357769@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 8e4ce8a..aff7e3b 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -987,6 +987,7 @@ static void check_process_timers(struct task_struct *tsk,
  */
 static void posix_cpu_timer_rearm(struct k_itimer *timer)
 {
+	clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
 	struct task_struct *p = timer->it.cpu.task;
 	struct sighand_struct *sighand;
 	unsigned long flags;
@@ -999,7 +1000,7 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
 	 * Fetch the current sample and update the timer's expiry time.
 	 */
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		cpu_clock_sample(timer->it_clock, p, &now);
+		cpu_clock_sample(clkid, p, &now);
 		bump_cpu_timer(timer, now);
 		if (unlikely(p->exit_state))
 			return;
@@ -1025,7 +1026,7 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
 			/* If the process is dying, no need to rearm */
 			goto unlock;
 		}
-		cpu_clock_sample_group(timer->it_clock, p, &now, true);
+		cpu_clock_sample_group(clkid, p, &now, true);
 		bump_cpu_timer(timer, now);
 		/* Leave the sighand locked for the call below.  */
 	}

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Use clock ID in posix_cpu_timer_get()
  2019-08-21 19:08 ` [patch V2 10/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_get() Thomas Gleixner
  2019-08-22 14:07   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     99093c5b81f58815fbfc1fe301c87206c6f5f730
Gitweb:        https://git.kernel.org/tip/99093c5b81f58815fbfc1fe301c87206c6f5f730
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:08:57 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:29 +02:00

posix-cpu-timers: Use clock ID in posix_cpu_timer_get()

Extract the clock ID (PROF/VIRT/SCHED) from the clock selector and use it
as argument to the sample functions. That allows to simplify them once all
callers are fixed.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192920.155487201@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 12561f8..8e4ce8a 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -699,6 +699,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
 
 static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp)
 {
+	clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
 	struct task_struct *p = timer->it.cpu.task;
 	u64 now;
 
@@ -717,7 +718,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
 	 * Sample the clock to take the difference with the expiry time.
 	 */
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		cpu_clock_sample(timer->it_clock, p, &now);
+		cpu_clock_sample(clkid, p, &now);
 	} else {
 		struct sighand_struct *sighand;
 		unsigned long flags;
@@ -737,7 +738,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
 			timer->it.cpu.expires = 0;
 			return;
 		} else {
-			cpu_clock_sample_group(timer->it_clock, p, &now, false);
+			cpu_clock_sample_group(clkid, p, &now, false);
 			unlock_task_sighand(p, &flags);
 		}
 	}

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Simplify sample functions
  2019-08-21 19:09 ` [patch V2 13/38] posix-cpu-timers: Simplify sample functions Thomas Gleixner
  2019-08-22 14:20   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     2092c1d4fed9f279d10600b4c1b5167dd8486a2a
Gitweb:        https://git.kernel.org/tip/2092c1d4fed9f279d10600b4c1b5167dd8486a2a
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:00 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:31 +02:00

posix-cpu-timers: Simplify sample functions

All callers hand in a valdiated clock id. Remove the return value which was
unchecked in most places anyway.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192920.430475832@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 28 +++++++++++++---------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 5944b74..cc3d148 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -180,14 +180,12 @@ posix_cpu_clock_set(const clockid_t clock, const struct timespec64 *tp)
 }
 
 /*
- * Sample a per-thread clock for the given task.
+ * Sample a per-thread clock for the given task. clkid is validated.
  */
-static int cpu_clock_sample(const clockid_t which_clock,
-			    struct task_struct *p, u64 *sample)
+static void cpu_clock_sample(const clockid_t clkid, struct task_struct *p,
+			     u64 *sample)
 {
-	switch (CPUCLOCK_WHICH(which_clock)) {
-	default:
-		return -EINVAL;
+	switch (clkid) {
 	case CPUCLOCK_PROF:
 		*sample = prof_ticks(p);
 		break;
@@ -197,8 +195,9 @@ static int cpu_clock_sample(const clockid_t which_clock,
 	case CPUCLOCK_SCHED:
 		*sample = task_sched_runtime(p);
 		break;
+	default:
+		WARN_ON_ONCE(1);
 	}
-	return 0;
 }
 
 /*
@@ -297,11 +296,11 @@ thread_group_start_cputime(struct task_struct *tsk, struct task_cputime *times)
  * Sample a process (thread group) clock for the given task clkid. If the
  * group's cputime accounting is already enabled, read the atomic
  * store. Otherwise a full update is required.  Task's sighand lock must be
- * held to protect the task traversal on a full update.
+ * held to protect the task traversal on a full update. clkid is already
+ * validated.
  */
-static int cpu_clock_sample_group(const clockid_t which_clock,
-				  struct task_struct *p,
-				  u64 *sample, bool start)
+static void cpu_clock_sample_group(const clockid_t clkid, struct task_struct *p,
+				   u64 *sample, bool start)
 {
 	struct thread_group_cputimer *cputimer = &p->signal->cputimer;
 	struct task_cputime cputime;
@@ -315,9 +314,7 @@ static int cpu_clock_sample_group(const clockid_t which_clock,
 		sample_cputime_atomic(&cputime, &cputimer->cputime_atomic);
 	}
 
-	switch (CPUCLOCK_WHICH(which_clock)) {
-	default:
-		return -EINVAL;
+	switch (clkid) {
 	case CPUCLOCK_PROF:
 		*sample = cputime.utime + cputime.stime;
 		break;
@@ -327,8 +324,9 @@ static int cpu_clock_sample_group(const clockid_t which_clock,
 	case CPUCLOCK_SCHED:
 		*sample = cputime.sum_exec_runtime;
 		break;
+	default:
+		WARN_ON_ONCE(1);
 	}
-	return 0;
 }
 
 static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Get rid of pointer indirection
  2019-08-21 19:09 ` [patch V2 14/38] posix-cpu-timers: Get rid of pointer indirection Thomas Gleixner
  2019-08-22 14:41   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     8c2d74f03705c2c993a57673bae8fd535eabede6
Gitweb:        https://git.kernel.org/tip/8c2d74f03705c2c993a57673bae8fd535eabede6
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:01 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:32 +02:00

posix-cpu-timers: Get rid of pointer indirection

Now that the sample functions have no return value anymore, the result can
simply be returned instead of using pointer indirection.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192920.535079278@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 50 ++++++++++++++-------------------
 1 file changed, 22 insertions(+), 28 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index cc3d148..a2007ce 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -182,22 +182,19 @@ posix_cpu_clock_set(const clockid_t clock, const struct timespec64 *tp)
 /*
  * Sample a per-thread clock for the given task. clkid is validated.
  */
-static void cpu_clock_sample(const clockid_t clkid, struct task_struct *p,
-			     u64 *sample)
+static u64 cpu_clock_sample(const clockid_t clkid, struct task_struct *p)
 {
 	switch (clkid) {
 	case CPUCLOCK_PROF:
-		*sample = prof_ticks(p);
-		break;
+		return prof_ticks(p);
 	case CPUCLOCK_VIRT:
-		*sample = virt_ticks(p);
-		break;
+		return virt_ticks(p);
 	case CPUCLOCK_SCHED:
-		*sample = task_sched_runtime(p);
-		break;
+		return task_sched_runtime(p);
 	default:
 		WARN_ON_ONCE(1);
 	}
+	return 0;
 }
 
 /*
@@ -299,8 +296,8 @@ thread_group_start_cputime(struct task_struct *tsk, struct task_cputime *times)
  * held to protect the task traversal on a full update. clkid is already
  * validated.
  */
-static void cpu_clock_sample_group(const clockid_t clkid, struct task_struct *p,
-				   u64 *sample, bool start)
+static u64 cpu_clock_sample_group(const clockid_t clkid, struct task_struct *p,
+				  bool start)
 {
 	struct thread_group_cputimer *cputimer = &p->signal->cputimer;
 	struct task_cputime cputime;
@@ -316,17 +313,15 @@ static void cpu_clock_sample_group(const clockid_t clkid, struct task_struct *p,
 
 	switch (clkid) {
 	case CPUCLOCK_PROF:
-		*sample = cputime.utime + cputime.stime;
-		break;
+		return cputime.utime + cputime.stime;
 	case CPUCLOCK_VIRT:
-		*sample = cputime.utime;
-		break;
+		return cputime.utime;
 	case CPUCLOCK_SCHED:
-		*sample = cputime.sum_exec_runtime;
-		break;
+		return cputime.sum_exec_runtime;
 	default:
 		WARN_ON_ONCE(1);
 	}
+	return 0;
 }
 
 static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)
@@ -340,9 +335,9 @@ static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)
 		return -EINVAL;
 
 	if (CPUCLOCK_PERTHREAD(clock))
-		cpu_clock_sample(clkid, tsk, &t);
+		t = cpu_clock_sample(clkid, tsk);
 	else
-		cpu_clock_sample_group(clkid, tsk, &t, false);
+		t = cpu_clock_sample_group(clkid, tsk, false);
 	put_task_struct(tsk);
 
 	*tp = ns_to_timespec64(t);
@@ -604,11 +599,10 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
 	 * times (in arm_timer).  With an absolute time, we must
 	 * check if it's already passed.  In short, we need a sample.
 	 */
-	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		cpu_clock_sample(clkid, p, &val);
-	} else {
-		cpu_clock_sample_group(clkid, p, &val, true);
-	}
+	if (CPUCLOCK_PERTHREAD(timer->it_clock))
+		val = cpu_clock_sample(clkid, p);
+	else
+		val = cpu_clock_sample_group(clkid, p, true);
 
 	if (old) {
 		if (old_expires == 0) {
@@ -716,7 +710,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
 	 * Sample the clock to take the difference with the expiry time.
 	 */
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		cpu_clock_sample(clkid, p, &now);
+		now = cpu_clock_sample(clkid, p);
 	} else {
 		struct sighand_struct *sighand;
 		unsigned long flags;
@@ -736,7 +730,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
 			timer->it.cpu.expires = 0;
 			return;
 		} else {
-			cpu_clock_sample_group(clkid, p, &now, false);
+			now = cpu_clock_sample_group(clkid, p, false);
 			unlock_task_sighand(p, &flags);
 		}
 	}
@@ -998,7 +992,7 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
 	 * Fetch the current sample and update the timer's expiry time.
 	 */
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		cpu_clock_sample(clkid, p, &now);
+		now = cpu_clock_sample(clkid, p);
 		bump_cpu_timer(timer, now);
 		if (unlikely(p->exit_state))
 			return;
@@ -1024,7 +1018,7 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
 			/* If the process is dying, no need to rearm */
 			goto unlock;
 		}
-		cpu_clock_sample_group(clkid, p, &now, true);
+		now = cpu_clock_sample_group(clkid, p, true);
 		bump_cpu_timer(timer, now);
 		/* Leave the sighand locked for the call below.  */
 	}
@@ -1192,7 +1186,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
 	if (WARN_ON_ONCE(clock_idx >= CPUCLOCK_SCHED))
 		return;
 
-	cpu_clock_sample_group(clock_idx, tsk, &now, true);
+	now = cpu_clock_sample_group(clock_idx, tsk, true);
 
 	if (oldval) {
 		/*

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Move prof/virt_ticks into caller
  2019-08-21 19:09 ` [patch V2 16/38] posix-cpu-timers: Move prof/virt_ticks into caller Thomas Gleixner
  2019-08-22 15:05   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     ab693c5a5e3107f035d5162e6ada9aaf7dd76a1d
Gitweb:        https://git.kernel.org/tip/ab693c5a5e3107f035d5162e6ada9aaf7dd76a1d
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:03 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:33 +02:00

posix-cpu-timers: Move prof/virt_ticks into caller

The functions have only one caller left. No point in having them.

Move the almost duplicated code into the caller and simplify it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192920.729298382@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 30 +++++++++---------------------
 1 file changed, 9 insertions(+), 21 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 98dab3e..b1c9766 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -130,23 +130,6 @@ static inline int task_cputime_zero(const struct task_cputime *cputime)
 	return 0;
 }
 
-static inline u64 prof_ticks(struct task_struct *p)
-{
-	u64 utime, stime;
-
-	task_cputime(p, &utime, &stime);
-
-	return utime + stime;
-}
-static inline u64 virt_ticks(struct task_struct *p)
-{
-	u64 utime, stime;
-
-	task_cputime(p, &utime, &stime);
-
-	return utime;
-}
-
 static int
 posix_cpu_clock_getres(const clockid_t which_clock, struct timespec64 *tp)
 {
@@ -184,13 +167,18 @@ posix_cpu_clock_set(const clockid_t clock, const struct timespec64 *tp)
  */
 static u64 cpu_clock_sample(const clockid_t clkid, struct task_struct *p)
 {
+	u64 utime, stime;
+
+	if (clkid == CPUCLOCK_SCHED)
+		return task_sched_runtime(p);
+
+	task_cputime(p, &utime, &stime);
+
 	switch (clkid) {
 	case CPUCLOCK_PROF:
-		return prof_ticks(p);
+		return utime + stime;
 	case CPUCLOCK_VIRT:
-		return virt_ticks(p);
-	case CPUCLOCK_SCHED:
-		return task_sched_runtime(p);
+		return utime;
 	default:
 		WARN_ON_ONCE(1);
 	}

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Sample task times once in expiry check
  2019-08-21 19:09 ` [patch V2 15/38] posix-cpu-timers: Sample task times once in expiry check Thomas Gleixner
  2019-08-22 15:00   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     0476ff2c151ee35bda2f938e8828b6f6113ebf55
Gitweb:        https://git.kernel.org/tip/0476ff2c151ee35bda2f938e8828b6f6113ebf55
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:02 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:32 +02:00

posix-cpu-timers: Sample task times once in expiry check

Sampling the task times twice does not make sense. Do it once.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192920.639878168@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index a2007ce..98dab3e 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -785,9 +785,9 @@ static inline void check_dl_overrun(struct task_struct *tsk)
 static void check_thread_timers(struct task_struct *tsk,
 				struct list_head *firing)
 {
-	struct list_head *timers = tsk->cpu_timers;
 	struct task_cputime *tsk_expires = &tsk->cputime_expires;
-	u64 expires;
+	struct list_head *timers = tsk->cpu_timers;
+	u64 expires, stime, utime;
 	unsigned long soft;
 
 	if (dl_task(tsk))
@@ -800,10 +800,12 @@ static void check_thread_timers(struct task_struct *tsk,
 	if (task_cputime_zero(&tsk->cputime_expires))
 		return;
 
-	expires = check_timers_list(timers, firing, prof_ticks(tsk));
+	task_cputime(tsk, &utime, &stime);
+
+	expires = check_timers_list(timers, firing, utime + stime);
 	tsk_expires->prof_exp = expires;
 
-	expires = check_timers_list(++timers, firing, virt_ticks(tsk));
+	expires = check_timers_list(++timers, firing, utime);
 	tsk_expires->virt_exp = expires;
 
 	tsk_expires->sched_exp = check_timers_list(++timers, firing,

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Create a container struct
  2019-08-21 19:09 ` [patch V2 17/38] posix-cpu-timers: Create a container struct Thomas Gleixner
  2019-08-22 15:32   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     2b69942f9021bf75bd1b001f53bd2578361fadf3
Gitweb:        https://git.kernel.org/tip/2b69942f9021bf75bd1b001f53bd2578361fadf3
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:04 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:33 +02:00

posix-cpu-timers: Create a container struct

Per task/process data of posix CPU timers is all over the place which
makes the code hard to follow and requires ifdeffery.

Create a container to hold all this information in one place, so data is
consolidated and the ifdeffery can be confined to the posix timer header
file and removed from places like fork.

As a first step, move the cpu_timers list head array into the new struct
and clean up the initializers and simplify fork. The remaining #ifdef in
fork will be removed later.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192920.819418976@linutronix.de

---
 include/linux/init_task.h      | 11 +-----------
 include/linux/posix-timers.h   | 34 +++++++++++++++++++++++++++++++++-
 include/linux/sched.h          |  4 +++-
 include/linux/sched/signal.h   |  5 +++--
 kernel/fork.c                  | 11 ++++-------
 kernel/time/posix-cpu-timers.c | 20 +++++++++----------
 6 files changed, 54 insertions(+), 31 deletions(-)

diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 6049baa..2c620d7 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -36,17 +36,6 @@ extern struct cred init_cred;
 #define INIT_PREV_CPUTIME(x)
 #endif
 
-#ifdef CONFIG_POSIX_TIMERS
-#define INIT_CPU_TIMERS(s)						\
-	.cpu_timers = {							\
-		LIST_HEAD_INIT(s.cpu_timers[0]),			\
-		LIST_HEAD_INIT(s.cpu_timers[1]),			\
-		LIST_HEAD_INIT(s.cpu_timers[2]),			\
-	},
-#else
-#define INIT_CPU_TIMERS(s)
-#endif
-
 #define INIT_TASK_COMM "swapper"
 
 /* Attach to the init_task data structure for proper alignment */
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 033374b..cdef897 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -62,6 +62,40 @@ static inline int clockid_to_fd(const clockid_t clk)
 	return ~(clk >> 3);
 }
 
+#ifdef CONFIG_POSIX_TIMERS
+/**
+ * posix_cputimers - Container for posix CPU timer related data
+ * @cpu_timers:		List heads to queue posix CPU timers
+ *
+ * Used in task_struct and signal_struct
+ */
+struct posix_cputimers {
+	struct list_head	cpu_timers[CPUCLOCK_MAX];
+};
+
+static inline void posix_cputimers_init(struct posix_cputimers *pct)
+{
+	INIT_LIST_HEAD(&pct->cpu_timers[0]);
+	INIT_LIST_HEAD(&pct->cpu_timers[1]);
+	INIT_LIST_HEAD(&pct->cpu_timers[2]);
+}
+
+/* Init task static initializer */
+#define INIT_CPU_TIMERLISTS(c)	{					\
+	LIST_HEAD_INIT(c.cpu_timers[0]),				\
+	LIST_HEAD_INIT(c.cpu_timers[1]),				\
+	LIST_HEAD_INIT(c.cpu_timers[2]),				\
+}
+
+#define INIT_CPU_TIMERS(s)						\
+	.posix_cputimers = {						\
+		.cpu_timers = INIT_CPU_TIMERLISTS(s.posix_cputimers),	\
+	},
+#else
+struct posix_cputimers { };
+#define INIT_CPU_TIMERS(s)
+#endif
+
 #define REQUEUE_PENDING 1
 
 /**
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 8dc1811..fde844a 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -28,6 +28,7 @@
 #include <linux/signal_types.h>
 #include <linux/mm_types_task.h>
 #include <linux/task_io_accounting.h>
+#include <linux/posix-timers.h>
 #include <linux/rseq.h>
 
 /* task_struct member predeclarations (sorted alphabetically): */
@@ -878,8 +879,9 @@ struct task_struct {
 
 #ifdef CONFIG_POSIX_TIMERS
 	struct task_cputime		cputime_expires;
-	struct list_head		cpu_timers[3];
 #endif
+	/* Empty if CONFIG_POSIX_CPUTIMERS=n */
+	struct posix_cputimers		posix_cputimers;
 
 	/* Process credentials: */
 
diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index efd8ce7..88fbb3f 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -9,6 +9,7 @@
 #include <linux/sched/task.h>
 #include <linux/cred.h>
 #include <linux/refcount.h>
+#include <linux/posix-timers.h>
 
 /*
  * Types defining task->signal and task->sighand and APIs using them:
@@ -151,9 +152,9 @@ struct signal_struct {
 	/* Earliest-expiration cache. */
 	struct task_cputime cputime_expires;
 
-	struct list_head cpu_timers[3];
-
 #endif
+	/* Empty if CONFIG_POSIX_TIMERS=n */
+	struct posix_cputimers posix_cputimers;
 
 	/* PID/PID hash table linkage. */
 	struct pid *pids[PIDTYPE_MAX];
diff --git a/kernel/fork.c b/kernel/fork.c
index d8ae0f1..b6a135e 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1523,6 +1523,7 @@ void __cleanup_sighand(struct sighand_struct *sighand)
  */
 static void posix_cpu_timers_init_group(struct signal_struct *sig)
 {
+	struct posix_cputimers *pct = &sig->posix_cputimers;
 	unsigned long cpu_limit;
 
 	cpu_limit = READ_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur);
@@ -1531,10 +1532,7 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig)
 		sig->cputimer.running = true;
 	}
 
-	/* The timer lists. */
-	INIT_LIST_HEAD(&sig->cpu_timers[0]);
-	INIT_LIST_HEAD(&sig->cpu_timers[1]);
-	INIT_LIST_HEAD(&sig->cpu_timers[2]);
+	posix_cputimers_init(pct);
 }
 #else
 static inline void posix_cpu_timers_init_group(struct signal_struct *sig) { }
@@ -1649,9 +1647,8 @@ static void posix_cpu_timers_init(struct task_struct *tsk)
 	tsk->cputime_expires.prof_exp = 0;
 	tsk->cputime_expires.virt_exp = 0;
 	tsk->cputime_expires.sched_exp = 0;
-	INIT_LIST_HEAD(&tsk->cpu_timers[0]);
-	INIT_LIST_HEAD(&tsk->cpu_timers[1]);
-	INIT_LIST_HEAD(&tsk->cpu_timers[2]);
+
+	posix_cputimers_init(&tsk->posix_cputimers);
 }
 #else
 static inline void posix_cpu_timers_init(struct task_struct *tsk) { }
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index b1c9766..849e204 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -407,11 +407,11 @@ static void cleanup_timers_list(struct list_head *head)
  *
  * This must be called with the siglock held.
  */
-static void cleanup_timers(struct list_head *head)
+static void cleanup_timers(struct posix_cputimers *pct)
 {
-	cleanup_timers_list(head);
-	cleanup_timers_list(++head);
-	cleanup_timers_list(++head);
+	cleanup_timers_list(&pct->cpu_timers[CPUCLOCK_PROF]);
+	cleanup_timers_list(&pct->cpu_timers[CPUCLOCK_VIRT]);
+	cleanup_timers_list(&pct->cpu_timers[CPUCLOCK_SCHED]);
 }
 
 /*
@@ -421,11 +421,11 @@ static void cleanup_timers(struct list_head *head)
  */
 void posix_cpu_timers_exit(struct task_struct *tsk)
 {
-	cleanup_timers(tsk->cpu_timers);
+	cleanup_timers(&tsk->posix_cputimers);
 }
 void posix_cpu_timers_exit_group(struct task_struct *tsk)
 {
-	cleanup_timers(tsk->signal->cpu_timers);
+	cleanup_timers(&tsk->signal->posix_cputimers);
 }
 
 static inline int expires_gt(u64 expires, u64 new_exp)
@@ -446,10 +446,10 @@ static void arm_timer(struct k_itimer *timer)
 	struct cpu_timer_list *next;
 
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		head = p->cpu_timers;
+		head = p->posix_cputimers.cpu_timers;
 		cputime_expires = &p->cputime_expires;
 	} else {
-		head = p->signal->cpu_timers;
+		head = p->signal->posix_cputimers.cpu_timers;
 		cputime_expires = &p->signal->cputime_expires;
 	}
 	head += CPUCLOCK_WHICH(timer->it_clock);
@@ -773,8 +773,8 @@ static inline void check_dl_overrun(struct task_struct *tsk)
 static void check_thread_timers(struct task_struct *tsk,
 				struct list_head *firing)
 {
+	struct list_head *timers = tsk->posix_cputimers.cpu_timers;
 	struct task_cputime *tsk_expires = &tsk->cputime_expires;
-	struct list_head *timers = tsk->cpu_timers;
 	u64 expires, stime, utime;
 	unsigned long soft;
 
@@ -879,9 +879,9 @@ static void check_process_timers(struct task_struct *tsk,
 				 struct list_head *firing)
 {
 	struct signal_struct *const sig = tsk->signal;
+	struct list_head *timers = sig->posix_cputimers.cpu_timers;
 	u64 utime, ptime, virt_expires, prof_expires;
 	u64 sum_sched_runtime, sched_expires;
-	struct list_head *timers = sig->cpu_timers;
 	struct task_cputime cputime;
 	unsigned long soft;
 

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] sched: Move struct task_cputime to types.h
       [not found] ` <20190821192920.909530418@linutronix.de>
  2019-08-22 16:06   ` [patch V2 18/38] sched: Move struct task_cputime to types.h Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     9eacb5c7e6607aba00a7322b21cad83fc8b101c8
Gitweb:        https://git.kernel.org/tip/9eacb5c7e6607aba00a7322b21cad83fc8b101c8
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:05 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:34 +02:00

sched: Move struct task_cputime to types.h

For upcoming posix-timer changes to avoid include recursion hell.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190821192920.909530418@linutronix.de

---
 include/linux/sched.h       | 17 +----------------
 include/linux/sched/types.h | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+), 16 deletions(-)
 create mode 100644 include/linux/sched/types.h

diff --git a/include/linux/sched.h b/include/linux/sched.h
index fde844a..37c39df 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -25,6 +25,7 @@
 #include <linux/resource.h>
 #include <linux/latencytop.h>
 #include <linux/sched/prio.h>
+#include <linux/sched/types.h>
 #include <linux/signal_types.h>
 #include <linux/mm_types_task.h>
 #include <linux/task_io_accounting.h>
@@ -245,22 +246,6 @@ struct prev_cputime {
 #endif
 };
 
-/**
- * struct task_cputime - collected CPU time counts
- * @utime:		time spent in user mode, in nanoseconds
- * @stime:		time spent in kernel mode, in nanoseconds
- * @sum_exec_runtime:	total time spent on the CPU, in nanoseconds
- *
- * This structure groups together three kinds of CPU time that are tracked for
- * threads and thread groups.  Most things considering CPU time want to group
- * these counts together and treat all three of them in parallel.
- */
-struct task_cputime {
-	u64				utime;
-	u64				stime;
-	unsigned long long		sum_exec_runtime;
-};
-
 /* Alternate field names when used on cache expirations: */
 #define virt_exp			utime
 #define prof_exp			stime
diff --git a/include/linux/sched/types.h b/include/linux/sched/types.h
new file mode 100644
index 0000000..2c5c28d
--- /dev/null
+++ b/include/linux/sched/types.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_SCHED_TYPES_H
+#define _LINUX_SCHED_TYPES_H
+
+#include <linux/types.h>
+
+/**
+ * struct task_cputime - collected CPU time counts
+ * @utime:		time spent in user mode, in nanoseconds
+ * @stime:		time spent in kernel mode, in nanoseconds
+ * @sum_exec_runtime:	total time spent on the CPU, in nanoseconds
+ *
+ * This structure groups together three kinds of CPU time that are tracked for
+ * threads and thread groups.  Most things considering CPU time want to group
+ * these counts together and treat all three of them in parallel.
+ */
+struct task_cputime {
+	u64				utime;
+	u64				stime;
+	unsigned long long		sum_exec_runtime;
+};
+
+#endif

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Provide array based access to expiry cache
  2019-08-21 19:09 ` [patch V2 20/38] posix-cpu-timers: Provide array based access to expiry cache Thomas Gleixner
  2019-08-23 17:33   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     11b8462f7e1d25f639c88949a2746a9c2667a766
Gitweb:        https://git.kernel.org/tip/11b8462f7e1d25f639c88949a2746a9c2667a766
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:07 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:35 +02:00

posix-cpu-timers: Provide array based access to expiry cache

Using struct task_cputime for the expiry cache is a pretty odd choice and
comes with magic defines to rename the fields for usage in the expiry
cache.

struct task_cputime is basically a u64 array with 3 members, but it has
distinct members.

The expiry cache content is different than the content of task_cputime
because

  expiry[PROF]  = task_cputime.stime + task_cputime.utime
  expiry[VIRT]  = task_cputime.utime
  expiry[SCHED] = task_cputime.sum_exec_runtime

So there is no direct mapping between task_cputime and the expiry cache and
the #define based remapping is just a horrible hack.

Having the expiry cache array based allows further simplification of the
expiry code.

To avoid an all in one cleanup which is hard to review add a temporary
anonymous union into struct task_cputime which allows array based access to
it. That requires to reorder the members. Add a build time sanity check to
validate that the members are at the same place.

The union and the build time checks will be removed after conversion.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192921.105793824@linutronix.de

---
 include/linux/posix-timers.h   | 24 ++++++++++++++++++------
 include/linux/sched/types.h    |  4 ++--
 kernel/time/posix-cpu-timers.c | 12 +++++++++++-
 3 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index a3731ba..ed0f6ec 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -65,27 +65,39 @@ static inline int clockid_to_fd(const clockid_t clk)
 /*
  * Alternate field names for struct task_cputime when used on cache
  * expirations. Will go away soon.
+ *
+ * stime corresponds to CLOCKCPU_PROF
+ * utime corresponds to CLOCKCPU_VIRT
+ * sum_exex_runtime corresponds to CLOCKCPU_SCHED
+ *
+ * The ordering is currently enforced so struct task_cputime and the
+ * expiries array in struct posix_cputimers are equivalent.
  */
-#define virt_exp			utime
 #define prof_exp			stime
+#define virt_exp			utime
 #define sched_exp			sum_exec_runtime
 
 #ifdef CONFIG_POSIX_TIMERS
 /**
  * posix_cputimers - Container for posix CPU timer related data
- * @cputime_expires:	Earliest-expiration cache
+ * @cputime_expires:	Earliest-expiration cache task_cputime based
+ * @expiries:		Earliest-expiration cache array based
  * @cpu_timers:		List heads to queue posix CPU timers
  *
  * Used in task_struct and signal_struct
  */
 struct posix_cputimers {
-	struct task_cputime	cputime_expires;
-	struct list_head	cpu_timers[CPUCLOCK_MAX];
+	/* Temporary union until all users are cleaned up */
+	union {
+		struct task_cputime	cputime_expires;
+		u64			expiries[CPUCLOCK_MAX];
+	};
+	struct list_head		cpu_timers[CPUCLOCK_MAX];
 };
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
 {
-	memset(&pct->cputime_expires, 0, sizeof(pct->cputime_expires));
+	memset(&pct->expiries, 0, sizeof(pct->expiries));
 	INIT_LIST_HEAD(&pct->cpu_timers[0]);
 	INIT_LIST_HEAD(&pct->cpu_timers[1]);
 	INIT_LIST_HEAD(&pct->cpu_timers[2]);
@@ -96,7 +108,7 @@ void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit);
 static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct,
 					       u64 runtime)
 {
-	pct->cputime_expires.sched_exp = runtime;
+	pct->expiries[CPUCLOCK_SCHED] = runtime;
 }
 
 /* Init task static initializer */
diff --git a/include/linux/sched/types.h b/include/linux/sched/types.h
index 2c5c28d..3c3e049 100644
--- a/include/linux/sched/types.h
+++ b/include/linux/sched/types.h
@@ -6,8 +6,8 @@
 
 /**
  * struct task_cputime - collected CPU time counts
- * @utime:		time spent in user mode, in nanoseconds
  * @stime:		time spent in kernel mode, in nanoseconds
+ * @utime:		time spent in user mode, in nanoseconds
  * @sum_exec_runtime:	total time spent on the CPU, in nanoseconds
  *
  * This structure groups together three kinds of CPU time that are tracked for
@@ -15,8 +15,8 @@
  * these counts together and treat all three of them in parallel.
  */
 struct task_cputime {
-	u64				utime;
 	u64				stime;
+	u64				utime;
 	unsigned long long		sum_exec_runtime;
 };
 
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 3e29d16..a38b6d0 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -18,13 +18,23 @@
 
 #include "posix-timers.h"
 
+static inline void temporary_check(void)
+{
+	BUILD_BUG_ON(offsetof(struct task_cputime, stime) !=
+		     CPUCLOCK_PROF * sizeof(u64));
+	BUILD_BUG_ON(offsetof(struct task_cputime, utime) !=
+		     CPUCLOCK_VIRT * sizeof(u64));
+	BUILD_BUG_ON(offsetof(struct task_cputime, sum_exec_runtime) !=
+		     CPUCLOCK_SCHED * sizeof(u64));
+}
+
 static void posix_cpu_timer_rearm(struct k_itimer *timer);
 
 void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit)
 {
 	posix_cputimers_init(pct);
 	if (cpu_limit != RLIM_INFINITY)
-		pct->cputime_expires.prof_exp = cpu_limit * NSEC_PER_SEC;
+		pct->expiries[CPUCLOCK_PROF] = cpu_limit * NSEC_PER_SEC;
 }
 
 /*

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Move expiry cache into struct posix_cputimers
  2019-08-21 19:09 ` [patch V2 19/38] posix-cpu-timers: Move expiry cache into struct posix_cputimers Thomas Gleixner
  2019-08-22 16:29   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     3a245c0f110e2bfcf7f2cd2248a29005c78999e3
Gitweb:        https://git.kernel.org/tip/3a245c0f110e2bfcf7f2cd2248a29005c78999e3
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:06 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:35 +02:00

posix-cpu-timers: Move expiry cache into struct posix_cputimers

The expiry cache belongs into the posix_cputimers container where the other
cpu timers information is.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192921.014444012@linutronix.de

---
 include/linux/posix-timers.h   | 22 ++++++++++++++++-
 include/linux/sched.h          |  8 +------
 include/linux/sched/signal.h   |  3 +--
 kernel/fork.c                  | 25 ++----------------
 kernel/sched/rt.c              |  6 ++--
 kernel/time/posix-cpu-timers.c | 45 +++++++++++++++++++--------------
 6 files changed, 56 insertions(+), 53 deletions(-)

diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index cdef897..a3731ba 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -62,24 +62,43 @@ static inline int clockid_to_fd(const clockid_t clk)
 	return ~(clk >> 3);
 }
 
+/*
+ * Alternate field names for struct task_cputime when used on cache
+ * expirations. Will go away soon.
+ */
+#define virt_exp			utime
+#define prof_exp			stime
+#define sched_exp			sum_exec_runtime
+
 #ifdef CONFIG_POSIX_TIMERS
 /**
  * posix_cputimers - Container for posix CPU timer related data
+ * @cputime_expires:	Earliest-expiration cache
  * @cpu_timers:		List heads to queue posix CPU timers
  *
  * Used in task_struct and signal_struct
  */
 struct posix_cputimers {
+	struct task_cputime	cputime_expires;
 	struct list_head	cpu_timers[CPUCLOCK_MAX];
 };
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
 {
+	memset(&pct->cputime_expires, 0, sizeof(pct->cputime_expires));
 	INIT_LIST_HEAD(&pct->cpu_timers[0]);
 	INIT_LIST_HEAD(&pct->cpu_timers[1]);
 	INIT_LIST_HEAD(&pct->cpu_timers[2]);
 }
 
+void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit);
+
+static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct,
+					       u64 runtime)
+{
+	pct->cputime_expires.sched_exp = runtime;
+}
+
 /* Init task static initializer */
 #define INIT_CPU_TIMERLISTS(c)	{					\
 	LIST_HEAD_INIT(c.cpu_timers[0]),				\
@@ -94,6 +113,9 @@ static inline void posix_cputimers_init(struct posix_cputimers *pct)
 #else
 struct posix_cputimers { };
 #define INIT_CPU_TIMERS(s)
+static inline void posix_cputimers_init(struct posix_cputimers *pct) { }
+static inline void posix_cputimers_group_init(struct posix_cputimers *pct,
+					      u64 cpu_limit) { }
 #endif
 
 #define REQUEUE_PENDING 1
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 37c39df..8cc8e32 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -246,11 +246,6 @@ struct prev_cputime {
 #endif
 };
 
-/* Alternate field names when used on cache expirations: */
-#define virt_exp			utime
-#define prof_exp			stime
-#define sched_exp			sum_exec_runtime
-
 enum vtime_state {
 	/* Task is sleeping or running in a CPU with VTIME inactive: */
 	VTIME_INACTIVE = 0,
@@ -862,9 +857,6 @@ struct task_struct {
 	unsigned long			min_flt;
 	unsigned long			maj_flt;
 
-#ifdef CONFIG_POSIX_TIMERS
-	struct task_cputime		cputime_expires;
-#endif
 	/* Empty if CONFIG_POSIX_CPUTIMERS=n */
 	struct posix_cputimers		posix_cputimers;
 
diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index 88fbb3f..729bd89 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -149,9 +149,6 @@ struct signal_struct {
 	 */
 	struct thread_group_cputimer cputimer;
 
-	/* Earliest-expiration cache. */
-	struct task_cputime cputime_expires;
-
 #endif
 	/* Empty if CONFIG_POSIX_TIMERS=n */
 	struct posix_cputimers posix_cputimers;
diff --git a/kernel/fork.c b/kernel/fork.c
index b6a135e..52bfe7c 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1527,12 +1527,9 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig)
 	unsigned long cpu_limit;
 
 	cpu_limit = READ_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur);
-	if (cpu_limit != RLIM_INFINITY) {
-		sig->cputime_expires.prof_exp = cpu_limit * NSEC_PER_SEC;
+	posix_cputimers_group_init(pct, cpu_limit);
+	if (cpu_limit != RLIM_INFINITY)
 		sig->cputimer.running = true;
-	}
-
-	posix_cputimers_init(pct);
 }
 #else
 static inline void posix_cpu_timers_init_group(struct signal_struct *sig) { }
@@ -1638,22 +1635,6 @@ static void rt_mutex_init_task(struct task_struct *p)
 #endif
 }
 
-#ifdef CONFIG_POSIX_TIMERS
-/*
- * Initialize POSIX timer handling for a single task.
- */
-static void posix_cpu_timers_init(struct task_struct *tsk)
-{
-	tsk->cputime_expires.prof_exp = 0;
-	tsk->cputime_expires.virt_exp = 0;
-	tsk->cputime_expires.sched_exp = 0;
-
-	posix_cputimers_init(&tsk->posix_cputimers);
-}
-#else
-static inline void posix_cpu_timers_init(struct task_struct *tsk) { }
-#endif
-
 static inline void init_task_pid_links(struct task_struct *task)
 {
 	enum pid_type type;
@@ -1932,7 +1913,7 @@ static __latent_entropy struct task_struct *copy_process(
 	task_io_accounting_init(&p->ioac);
 	acct_clear_integrals(p);
 
-	posix_cpu_timers_init(p);
+	posix_cputimers_init(&p->posix_cputimers);
 
 	p->io_context = NULL;
 	audit_set_context(p, NULL);
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index da3e85e..d6678f7 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -2305,8 +2305,10 @@ static void watchdog(struct rq *rq, struct task_struct *p)
 		}
 
 		next = DIV_ROUND_UP(min(soft, hard), USEC_PER_SEC/HZ);
-		if (p->rt.timeout > next)
-			p->cputime_expires.sched_exp = p->se.sum_exec_runtime;
+		if (p->rt.timeout > next) {
+			posix_cputimers_rt_watchdog(&p->posix_cputimers,
+						    p->se.sum_exec_runtime);
+		}
 	}
 }
 #else
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 849e204..3e29d16 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -20,11 +20,18 @@
 
 static void posix_cpu_timer_rearm(struct k_itimer *timer);
 
+void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit)
+{
+	posix_cputimers_init(pct);
+	if (cpu_limit != RLIM_INFINITY)
+		pct->cputime_expires.prof_exp = cpu_limit * NSEC_PER_SEC;
+}
+
 /*
  * Called after updating RLIMIT_CPU to run cpu timer and update
- * tsk->signal->cputime_expires expiration cache if necessary. Needs
- * siglock protection since other code may update expiration cache as
- * well.
+ * tsk->signal->posix_cputimers.cputime_expires expiration cache if
+ * necessary. Needs siglock protection since other code may update
+ * expiration cache as well.
  */
 void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new)
 {
@@ -447,10 +454,10 @@ static void arm_timer(struct k_itimer *timer)
 
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
 		head = p->posix_cputimers.cpu_timers;
-		cputime_expires = &p->cputime_expires;
+		cputime_expires = &p->posix_cputimers.cputime_expires;
 	} else {
 		head = p->signal->posix_cputimers.cpu_timers;
-		cputime_expires = &p->signal->cputime_expires;
+		cputime_expires = &p->signal->posix_cputimers.cputime_expires;
 	}
 	head += CPUCLOCK_WHICH(timer->it_clock);
 
@@ -774,7 +781,7 @@ static void check_thread_timers(struct task_struct *tsk,
 				struct list_head *firing)
 {
 	struct list_head *timers = tsk->posix_cputimers.cpu_timers;
-	struct task_cputime *tsk_expires = &tsk->cputime_expires;
+	struct task_cputime *tsk_expires = &tsk->posix_cputimers.cputime_expires;
 	u64 expires, stime, utime;
 	unsigned long soft;
 
@@ -785,7 +792,7 @@ static void check_thread_timers(struct task_struct *tsk,
 	 * If cputime_expires is zero, then there are no active
 	 * per thread CPU timers.
 	 */
-	if (task_cputime_zero(&tsk->cputime_expires))
+	if (task_cputime_zero(tsk_expires))
 		return;
 
 	task_cputime(tsk, &utime, &stime);
@@ -954,10 +961,10 @@ static void check_process_timers(struct task_struct *tsk,
 			prof_expires = x;
 	}
 
-	sig->cputime_expires.prof_exp = prof_expires;
-	sig->cputime_expires.virt_exp = virt_expires;
-	sig->cputime_expires.sched_exp = sched_expires;
-	if (task_cputime_zero(&sig->cputime_expires))
+	sig->posix_cputimers.cputime_expires.prof_exp = prof_expires;
+	sig->posix_cputimers.cputime_expires.virt_exp = virt_expires;
+	sig->posix_cputimers.cputime_expires.sched_exp = sched_expires;
+	if (task_cputime_zero(&sig->posix_cputimers.cputime_expires))
 		stop_process_timers(sig);
 
 	sig->cputimer.checking_timer = false;
@@ -1058,12 +1065,13 @@ static inline int fastpath_timer_check(struct task_struct *tsk)
 {
 	struct signal_struct *sig;
 
-	if (!task_cputime_zero(&tsk->cputime_expires)) {
+	if (!task_cputime_zero(&tsk->posix_cputimers.cputime_expires)) {
 		struct task_cputime task_sample;
 
 		task_cputime(tsk, &task_sample.utime, &task_sample.stime);
 		task_sample.sum_exec_runtime = tsk->se.sum_exec_runtime;
-		if (task_cputime_expired(&task_sample, &tsk->cputime_expires))
+		if (task_cputime_expired(&task_sample,
+					 &tsk->posix_cputimers.cputime_expires))
 			return 1;
 	}
 
@@ -1088,7 +1096,8 @@ static inline int fastpath_timer_check(struct task_struct *tsk)
 
 		sample_cputime_atomic(&group_sample, &sig->cputimer.cputime_atomic);
 
-		if (task_cputime_expired(&group_sample, &sig->cputime_expires))
+		if (task_cputime_expired(&group_sample,
+					 &sig->posix_cputimers.cputime_expires))
 			return 1;
 	}
 
@@ -1204,12 +1213,12 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
 	 */
 	switch (clock_idx) {
 	case CPUCLOCK_PROF:
-		if (expires_gt(tsk->signal->cputime_expires.prof_exp, *newval))
-			tsk->signal->cputime_expires.prof_exp = *newval;
+		if (expires_gt(tsk->signal->posix_cputimers.cputime_expires.prof_exp, *newval))
+			tsk->signal->posix_cputimers.cputime_expires.prof_exp = *newval;
 		break;
 	case CPUCLOCK_VIRT:
-		if (expires_gt(tsk->signal->cputime_expires.virt_exp, *newval))
-			tsk->signal->cputime_expires.virt_exp = *newval;
+		if (expires_gt(tsk->signal->posix_cputimers.cputime_expires.virt_exp, *newval))
+			tsk->signal->posix_cputimers.cputime_expires.virt_exp = *newval;
 		break;
 	}
 

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Simplify timer queueing
  2019-08-21 19:09 ` [patch V2 21/38] posix-cpu-timers: Simplify timer queueing Thomas Gleixner
  2019-08-23 17:51   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     3b495b22d04df3220ccae829bf7c5cadb3059ccf
Gitweb:        https://git.kernel.org/tip/3b495b22d04df3220ccae829bf7c5cadb3059ccf
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:08 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:36 +02:00

posix-cpu-timers: Simplify timer queueing

Now that the expiry cache can be accessed as an array, the per clock
checking can be reduced to just comparing the corresponding array elements.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192921.212129449@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 55 ++++++++++++---------------------
 1 file changed, 21 insertions(+), 34 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index a38b6d0..b132417 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -456,20 +456,20 @@ static inline int expires_gt(u64 expires, u64 new_exp)
  */
 static void arm_timer(struct k_itimer *timer)
 {
+	struct cpu_timer_list *const nt = &timer->it.cpu;
+	int clkidx = CPUCLOCK_WHICH(timer->it_clock);
+	u64 *cpuexp, newexp = timer->it.cpu.expires;
 	struct task_struct *p = timer->it.cpu.task;
 	struct list_head *head, *listpos;
-	struct task_cputime *cputime_expires;
-	struct cpu_timer_list *const nt = &timer->it.cpu;
 	struct cpu_timer_list *next;
 
 	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		head = p->posix_cputimers.cpu_timers;
-		cputime_expires = &p->posix_cputimers.cputime_expires;
+		head = p->posix_cputimers.cpu_timers + clkidx;
+		cpuexp = p->posix_cputimers.expiries + clkidx;
 	} else {
-		head = p->signal->posix_cputimers.cpu_timers;
-		cputime_expires = &p->signal->posix_cputimers.cputime_expires;
+		head = p->signal->posix_cputimers.cpu_timers + clkidx;
+		cpuexp = p->signal->posix_cputimers.expiries + clkidx;
 	}
-	head += CPUCLOCK_WHICH(timer->it_clock);
 
 	listpos = head;
 	list_for_each_entry(next, head, entry) {
@@ -479,35 +479,22 @@ static void arm_timer(struct k_itimer *timer)
 	}
 	list_add(&nt->entry, listpos);
 
-	if (listpos == head) {
-		u64 exp = nt->expires;
+	if (listpos != head)
+		return;
 
-		/*
-		 * We are the new earliest-expiring POSIX 1.b timer, hence
-		 * need to update expiration cache. Take into account that
-		 * for process timers we share expiration cache with itimers
-		 * and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME.
-		 */
+	/*
+	 * We are the new earliest-expiring POSIX 1.b timer, hence
+	 * need to update expiration cache. Take into account that
+	 * for process timers we share expiration cache with itimers
+	 * and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME.
+	 */
+	if (expires_gt(*cpuexp, newexp))
+		*cpuexp = newexp;
 
-		switch (CPUCLOCK_WHICH(timer->it_clock)) {
-		case CPUCLOCK_PROF:
-			if (expires_gt(cputime_expires->prof_exp, exp))
-				cputime_expires->prof_exp = exp;
-			break;
-		case CPUCLOCK_VIRT:
-			if (expires_gt(cputime_expires->virt_exp, exp))
-				cputime_expires->virt_exp = exp;
-			break;
-		case CPUCLOCK_SCHED:
-			if (expires_gt(cputime_expires->sched_exp, exp))
-				cputime_expires->sched_exp = exp;
-			break;
-		}
-		if (CPUCLOCK_PERTHREAD(timer->it_clock))
-			tick_dep_set_task(p, TICK_DEP_BIT_POSIX_TIMER);
-		else
-			tick_dep_set_signal(p->signal, TICK_DEP_BIT_POSIX_TIMER);
-	}
+	if (CPUCLOCK_PERTHREAD(timer->it_clock))
+		tick_dep_set_task(p, TICK_DEP_BIT_POSIX_TIMER);
+	else
+		tick_dep_set_signal(p->signal, TICK_DEP_BIT_POSIX_TIMER);
 }
 
 /*

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Simplify set_process_cpu_timer()
  2019-08-21 19:09 ` [patch V2 22/38] posix-cpu-timers: Simplify set_process_cpu_timer() Thomas Gleixner
  2019-08-23 18:00   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     1b0dd96d0f07c482bf1d04987cc1b35e376a7518
Gitweb:        https://git.kernel.org/tip/1b0dd96d0f07c482bf1d04987cc1b35e376a7518
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:09 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:36 +02:00

posix-cpu-timers: Simplify set_process_cpu_timer()

The expiry cache can now be accessed as an array. Replace the per clock
checks with a simple comparison of the clock indexed array member.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192921.303316423@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 24 ++++++++----------------
 1 file changed, 8 insertions(+), 16 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index b132417..2c47ce6 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -1174,15 +1174,15 @@ void run_posix_cpu_timers(void)
  * Set one of the process-wide special case CPU timers or RLIMIT_CPU.
  * The tsk->sighand->siglock must be held by the caller.
  */
-void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
+void set_process_cpu_timer(struct task_struct *tsk, unsigned int clkid,
 			   u64 *newval, u64 *oldval)
 {
-	u64 now;
+	u64 now, *expiry = tsk->signal->posix_cputimers.expiries + clkid;
 
-	if (WARN_ON_ONCE(clock_idx >= CPUCLOCK_SCHED))
+	if (WARN_ON_ONCE(clkid >= CPUCLOCK_SCHED))
 		return;
 
-	now = cpu_clock_sample_group(clock_idx, tsk, true);
+	now = cpu_clock_sample_group(clkid, tsk, true);
 
 	if (oldval) {
 		/*
@@ -1205,19 +1205,11 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
 	}
 
 	/*
-	 * Update expiration cache if we are the earliest timer, or eventually
-	 * RLIMIT_CPU limit is earlier than prof_exp cpu timer expire.
+	 * Update expiration cache if this is the earliest timer. CPUCLOCK_PROF
+	 * expiry cache is also used by RLIMIT_CPU!.
 	 */
-	switch (clock_idx) {
-	case CPUCLOCK_PROF:
-		if (expires_gt(tsk->signal->posix_cputimers.cputime_expires.prof_exp, *newval))
-			tsk->signal->posix_cputimers.cputime_expires.prof_exp = *newval;
-		break;
-	case CPUCLOCK_VIRT:
-		if (expires_gt(tsk->signal->posix_cputimers.cputime_expires.virt_exp, *newval))
-			tsk->signal->posix_cputimers.cputime_expires.virt_exp = *newval;
-		break;
-	}
+	if (expires_gt(*expiry, *newval))
+		*expiry = *newval;
 
 	tick_dep_set_signal(tsk->signal, TICK_DEP_BIT_POSIX_TIMER);
 }

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Remove the odd field rename defines
  2019-08-21 19:09 ` [patch V2 24/38] posix-cpu-timers: Remove the odd field rename defines Thomas Gleixner
  2019-08-23 18:36   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     bbc9bae1e49bee9862c7f24101a728e73cd9f589
Gitweb:        https://git.kernel.org/tip/bbc9bae1e49bee9862c7f24101a728e73cd9f589
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:11 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:37 +02:00

posix-cpu-timers: Remove the odd field rename defines

The last users of the odd define based renaming of struct task_cputime
members are gone. Good riddance.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192921.499058279@linutronix.de

---
 include/linux/posix-timers.h | 15 ---------------
 1 file changed, 15 deletions(-)

diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index ed0f6ec..e36c6fd 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -62,21 +62,6 @@ static inline int clockid_to_fd(const clockid_t clk)
 	return ~(clk >> 3);
 }
 
-/*
- * Alternate field names for struct task_cputime when used on cache
- * expirations. Will go away soon.
- *
- * stime corresponds to CLOCKCPU_PROF
- * utime corresponds to CLOCKCPU_VIRT
- * sum_exex_runtime corresponds to CLOCKCPU_SCHED
- *
- * The ordering is currently enforced so struct task_cputime and the
- * expiries array in struct posix_cputimers are equivalent.
- */
-#define prof_exp			stime
-#define virt_exp			utime
-#define sched_exp			sum_exec_runtime
-
 #ifdef CONFIG_POSIX_TIMERS
 /**
  * posix_cputimers - Container for posix CPU timer related data

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Switch check_*_timers() to array cache
  2019-08-21 19:09 ` [patch V2 23/38] posix-cpu-timers: Switch check_*_timers() to array cache Thomas Gleixner
  2019-08-23 18:13   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     c02b078e63a6f42029cb655d0aa3c991271637ac
Gitweb:        https://git.kernel.org/tip/c02b078e63a6f42029cb655d0aa3c991271637ac
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:10 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:36 +02:00

posix-cpu-timers: Switch check_*_timers() to array cache

Use the array based expiry cache in check_thread_timers() and convert the
store in check_process_timers() for consistency.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192921.408222378@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 26 +++++++++++---------------
 1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 2c47ce6..220e3c7 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -778,8 +778,7 @@ static void check_thread_timers(struct task_struct *tsk,
 				struct list_head *firing)
 {
 	struct list_head *timers = tsk->posix_cputimers.cpu_timers;
-	struct task_cputime *tsk_expires = &tsk->posix_cputimers.cputime_expires;
-	u64 expires, stime, utime;
+	u64 stime, utime, *expires = tsk->posix_cputimers.expiries;
 	unsigned long soft;
 
 	if (dl_task(tsk))
@@ -789,19 +788,14 @@ static void check_thread_timers(struct task_struct *tsk,
 	 * If cputime_expires is zero, then there are no active
 	 * per thread CPU timers.
 	 */
-	if (task_cputime_zero(tsk_expires))
+	if (task_cputime_zero(&tsk->posix_cputimers.cputime_expires))
 		return;
 
 	task_cputime(tsk, &utime, &stime);
 
-	expires = check_timers_list(timers, firing, utime + stime);
-	tsk_expires->prof_exp = expires;
-
-	expires = check_timers_list(++timers, firing, utime);
-	tsk_expires->virt_exp = expires;
-
-	tsk_expires->sched_exp = check_timers_list(++timers, firing,
-						   tsk->se.sum_exec_runtime);
+	*expires++ = check_timers_list(timers, firing, utime + stime);
+	*expires++ = check_timers_list(++timers, firing, utime);
+	*expires = check_timers_list(++timers, firing, tsk->se.sum_exec_runtime);
 
 	/*
 	 * Check for the special case thread timers.
@@ -839,7 +833,8 @@ static void check_thread_timers(struct task_struct *tsk,
 			__group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
 		}
 	}
-	if (task_cputime_zero(tsk_expires))
+
+	if (task_cputime_zero(&tsk->posix_cputimers.cputime_expires))
 		tick_dep_clear_task(tsk, TICK_DEP_BIT_POSIX_TIMER);
 }
 
@@ -958,9 +953,10 @@ static void check_process_timers(struct task_struct *tsk,
 			prof_expires = x;
 	}
 
-	sig->posix_cputimers.cputime_expires.prof_exp = prof_expires;
-	sig->posix_cputimers.cputime_expires.virt_exp = virt_expires;
-	sig->posix_cputimers.cputime_expires.sched_exp = sched_expires;
+	sig->posix_cputimers.expiries[CPUCLOCK_PROF] = prof_expires;
+	sig->posix_cputimers.expiries[CPUCLOCK_VIRT] = virt_expires;
+	sig->posix_cputimers.expiries[CPUCLOCK_SCHED] = sched_expires;
+
 	if (task_cputime_zero(&sig->posix_cputimers.cputime_expires))
 		stop_process_timers(sig);
 

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Make expiry checks array based
  2019-08-21 19:09 ` [patch V2 26/38] posix-cpu-timers: Make expiry checks array based Thomas Gleixner
  2019-08-23 22:44   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     001f7971433a53bb76443cd8f5827ca27b0bc8ca
Gitweb:        https://git.kernel.org/tip/001f7971433a53bb76443cd8f5827ca27b0bc8ca
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:13 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:38 +02:00

posix-cpu-timers: Make expiry checks array based

The expiry cache is an array indexed by clock ids. The new sample functions
allow to retrieve a corresponding array of samples.

Convert the fastpath expiry checks to make use of the new sample functions
and do the comparisons on the sample and the expiry array.

Make the check for the expiry array being zero array based as well.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192921.695481430@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 85 +++++++++++++--------------------
 1 file changed, 36 insertions(+), 49 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 11c841c..e159b03 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -39,7 +39,7 @@ void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit)
 
 /*
  * Called after updating RLIMIT_CPU to run cpu timer and update
- * tsk->signal->posix_cputimers.cputime_expires expiration cache if
+ * tsk->signal->posix_cputimers.expiries expiration cache if
  * necessary. Needs siglock protection since other code may update
  * expiration cache as well.
  */
@@ -132,19 +132,9 @@ static void bump_cpu_timer(struct k_itimer *timer, u64 now)
 	}
 }
 
-/**
- * task_cputime_zero - Check a task_cputime struct for all zero fields.
- *
- * @cputime:	The struct to compare.
- *
- * Checks @cputime to see if all fields are zero.  Returns true if all fields
- * are zero, false if any field is nonzero.
- */
-static inline int task_cputime_zero(const struct task_cputime *cputime)
+static inline bool expiry_cache_is_zero(const u64 *ec)
 {
-	if (!cputime->utime && !cputime->stime && !cputime->sum_exec_runtime)
-		return 1;
-	return 0;
+	return !(ec[CPUCLOCK_PROF] | ec[CPUCLOCK_VIRT] | ec[CPUCLOCK_SCHED]);
 }
 
 static int
@@ -811,10 +801,10 @@ static void check_thread_timers(struct task_struct *tsk,
 		check_dl_overrun(tsk);
 
 	/*
-	 * If cputime_expires is zero, then there are no active
-	 * per thread CPU timers.
+	 * If the expiry cache is zero, then there are no active per thread
+	 * CPU timers.
 	 */
-	if (task_cputime_zero(&tsk->posix_cputimers.cputime_expires))
+	if (expiry_cache_is_zero(tsk->posix_cputimers.expiries))
 		return;
 
 	task_cputime(tsk, &utime, &stime);
@@ -860,7 +850,7 @@ static void check_thread_timers(struct task_struct *tsk,
 		}
 	}
 
-	if (task_cputime_zero(&tsk->posix_cputimers.cputime_expires))
+	if (expiry_cache_is_zero(tsk->posix_cputimers.expiries))
 		tick_dep_clear_task(tsk, TICK_DEP_BIT_POSIX_TIMER);
 }
 
@@ -983,7 +973,7 @@ static void check_process_timers(struct task_struct *tsk,
 	sig->posix_cputimers.expiries[CPUCLOCK_VIRT] = virt_expires;
 	sig->posix_cputimers.expiries[CPUCLOCK_SCHED] = sched_expires;
 
-	if (task_cputime_zero(&sig->posix_cputimers.cputime_expires))
+	if (expiry_cache_is_zero(sig->posix_cputimers.expiries))
 		stop_process_timers(sig);
 
 	sig->cputimer.checking_timer = false;
@@ -1048,26 +1038,23 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
 }
 
 /**
- * task_cputime_expired - Compare two task_cputime entities.
+ * task_cputimers_expired - Compare two task_cputime entities.
  *
- * @sample:	The task_cputime structure to be checked for expiration.
- * @expires:	Expiration times, against which @sample will be checked.
+ * @samples:	Array of current samples for the CPUCLOCK clocks
+ * @expiries:	Array of expiry values for the CPUCLOCK clocks
  *
- * Checks @sample against @expires to see if any field of @sample has expired.
- * Returns true if any field of the former is greater than the corresponding
- * field of the latter if the latter field is set.  Otherwise returns false.
+ * Returns true if any mmember of @samples is greater than the corresponding
+ * member of @expiries if that member is non zero. False otherwise
  */
-static inline int task_cputime_expired(const struct task_cputime *sample,
-					const struct task_cputime *expires)
+static inline bool task_cputimers_expired(const u64 *sample, const u64 *expiries)
 {
-	if (expires->utime && sample->utime >= expires->utime)
-		return 1;
-	if (expires->stime && sample->utime + sample->stime >= expires->stime)
-		return 1;
-	if (expires->sum_exec_runtime != 0 &&
-	    sample->sum_exec_runtime >= expires->sum_exec_runtime)
-		return 1;
-	return 0;
+	int i;
+
+	for (i = 0; i < CPUCLOCK_MAX; i++) {
+		if (expiries[i] && sample[i] >= expiries[i])
+			return true;
+	}
+	return false;
 }
 
 /**
@@ -1080,18 +1067,17 @@ static inline int task_cputime_expired(const struct task_cputime *sample,
  * timers and compare them with the corresponding expiration times.  Return
  * true if a timer has expired, else return false.
  */
-static inline int fastpath_timer_check(struct task_struct *tsk)
+static inline bool fastpath_timer_check(struct task_struct *tsk)
 {
+	u64 *expiries = tsk->posix_cputimers.expiries;
 	struct signal_struct *sig;
 
-	if (!task_cputime_zero(&tsk->posix_cputimers.cputime_expires)) {
-		struct task_cputime task_sample;
+	if (!expiry_cache_is_zero(expiries)) {
+		u64 samples[CPUCLOCK_MAX];
 
-		task_cputime(tsk, &task_sample.utime, &task_sample.stime);
-		task_sample.sum_exec_runtime = tsk->se.sum_exec_runtime;
-		if (task_cputime_expired(&task_sample,
-					 &tsk->posix_cputimers.cputime_expires))
-			return 1;
+		task_sample_cputime(tsk, samples);
+		if (task_cputimers_expired(samples, expiries))
+			return true;
 	}
 
 	sig = tsk->signal;
@@ -1111,19 +1097,20 @@ static inline int fastpath_timer_check(struct task_struct *tsk)
 	 */
 	if (READ_ONCE(sig->cputimer.running) &&
 	    !READ_ONCE(sig->cputimer.checking_timer)) {
-		struct task_cputime group_sample;
+		u64 samples[CPUCLOCK_MAX];
 
-		sample_cputime_atomic(&group_sample, &sig->cputimer.cputime_atomic);
+		proc_sample_cputime_atomic(&sig->cputimer.cputime_atomic,
+					   samples);
 
-		if (task_cputime_expired(&group_sample,
-					 &sig->posix_cputimers.cputime_expires))
-			return 1;
+		if (task_cputimers_expired(samples,
+					   sig->posix_cputimers.expiries))
+			return true;
 	}
 
 	if (dl_task(tsk) && tsk->dl.dl_overrun)
-		return 1;
+		return true;
 
-	return 0;
+	return false;
 }
 
 /*

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Provide array based sample functions
  2019-08-21 19:09 ` [patch V2 25/38] posix-cpu-timers: Provide array based sample functions Thomas Gleixner
  2019-08-23 22:08   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     b0d524f77956eec887b30732af1f5f98cbf62b9f
Gitweb:        https://git.kernel.org/tip/b0d524f77956eec887b30732af1f5f98cbf62b9f
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:12 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:38 +02:00

posix-cpu-timers: Provide array based sample functions

Instead of using task_cputime and doing the addition of utime and stime at
all call sites, it's way simpler to have a sample array which allows
indexed based checks against the expiry cache array.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192921.590362974@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 220e3c7..11c841c 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -202,6 +202,32 @@ static u64 cpu_clock_sample(const clockid_t clkid, struct task_struct *p)
 	return 0;
 }
 
+static inline void store_samples(u64 *samples, u64 stime, u64 utime, u64 rtime)
+{
+	samples[CPUCLOCK_PROF] = stime + utime;
+	samples[CPUCLOCK_VIRT] = utime;
+	samples[CPUCLOCK_SCHED] = rtime;
+}
+
+static void task_sample_cputime(struct task_struct *p, u64 *samples)
+{
+	u64 stime, utime;
+
+	task_cputime(p, &utime, &stime);
+	store_samples(samples, stime, utime, p->se.sum_exec_runtime);
+}
+
+static void proc_sample_cputime_atomic(struct task_cputime_atomic *at,
+				       u64 *samples)
+{
+	u64 stime, utime, rtime;
+
+	utime = atomic64_read(&at->utime);
+	stime = atomic64_read(&at->stime);
+	rtime = atomic64_read(&at->sum_exec_runtime);
+	store_samples(samples, stime, utime, rtime);
+}
+
 /*
  * Set cputime to sum_cputime if sum_cputime > cputime. Use cmpxchg
  * to avoid race conditions with concurrent updates to cputime.

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Switch thread group sampling to array
  2019-08-21 19:09 ` [patch V2 29/38] posix-cpu-timers: Switch thread group sampling to array Thomas Gleixner
  2019-08-26 21:12   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     b7be4ef1365dcb56fdffc6689e41058b23f5996d
Gitweb:        https://git.kernel.org/tip/b7be4ef1365dcb56fdffc6689e41058b23f5996d
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:16 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:39 +02:00

posix-cpu-timers: Switch thread group sampling to array

That allows more simplifications in various places.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192921.988426956@linutronix.de

---
 include/linux/sched/cputime.h  |   2 +-
 kernel/time/itimer.c           |  11 +---
 kernel/time/posix-cpu-timers.c | 104 +++++++++++++-------------------
 3 files changed, 49 insertions(+), 68 deletions(-)

diff --git a/include/linux/sched/cputime.h b/include/linux/sched/cputime.h
index 2638fd0..eefa5df 100644
--- a/include/linux/sched/cputime.h
+++ b/include/linux/sched/cputime.h
@@ -61,7 +61,7 @@ extern void cputime_adjust(struct task_cputime *curr, struct prev_cputime *prev,
  * Thread group CPU time accounting.
  */
 void thread_group_cputime(struct task_struct *tsk, struct task_cputime *times);
-void thread_group_sample_cputime(struct task_struct *tsk, struct task_cputime *times);
+void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples);
 
 /*
  * The following are functions that support scheduler-internal time accounting.
diff --git a/kernel/time/itimer.c b/kernel/time/itimer.c
index ae04bc2..77f1e56 100644
--- a/kernel/time/itimer.c
+++ b/kernel/time/itimer.c
@@ -55,15 +55,10 @@ static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
 	val = it->expires;
 	interval = it->incr;
 	if (val) {
-		struct task_cputime cputime;
-		u64 t;
+		u64 t, samples[CPUCLOCK_MAX];
 
-		thread_group_sample_cputime(tsk, &cputime);
-		if (clock_id == CPUCLOCK_PROF)
-			t = cputime.utime + cputime.stime;
-		else
-			/* CPUCLOCK_VIRT */
-			t = cputime.utime;
+		thread_group_sample_cputime(tsk, samples);
+		t = samples[clock_id];
 
 		if (val < t)
 			/* about to fire */
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 9ac601a..e62139a 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -225,22 +225,14 @@ static inline void __update_gt_cputime(atomic64_t *cputime, u64 sum_cputime)
 	}
 }
 
-static void update_gt_cputime(struct task_cputime_atomic *cputime_atomic, struct task_cputime *sum)
+static void update_gt_cputime(struct task_cputime_atomic *cputime_atomic,
+			      struct task_cputime *sum)
 {
 	__update_gt_cputime(&cputime_atomic->utime, sum->utime);
 	__update_gt_cputime(&cputime_atomic->stime, sum->stime);
 	__update_gt_cputime(&cputime_atomic->sum_exec_runtime, sum->sum_exec_runtime);
 }
 
-/* Sample task_cputime_atomic values in "atomic_timers", store results in "times". */
-static inline void sample_cputime_atomic(struct task_cputime *times,
-					 struct task_cputime_atomic *atomic_times)
-{
-	times->utime = atomic64_read(&atomic_times->utime);
-	times->stime = atomic64_read(&atomic_times->stime);
-	times->sum_exec_runtime = atomic64_read(&atomic_times->sum_exec_runtime);
-}
-
 /**
  * thread_group_sample_cputime - Sample cputime for a given task
  * @tsk:	Task for which cputime needs to be started
@@ -252,20 +244,19 @@ static inline void sample_cputime_atomic(struct task_cputime *times,
  *
  * Updates @times with an uptodate sample of the thread group cputimes.
  */
-void thread_group_sample_cputime(struct task_struct *tsk,
-				struct task_cputime *times)
+void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples)
 {
 	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
 
 	WARN_ON_ONCE(!cputimer->running);
 
-	sample_cputime_atomic(times, &cputimer->cputime_atomic);
+	proc_sample_cputime_atomic(&cputimer->cputime_atomic, samples);
 }
 
 /**
  * thread_group_start_cputime - Start cputime and return a sample
  * @tsk:	Task for which cputime needs to be started
- * @iimes:	Storage for time samples
+ * @samples:	Storage for time samples
  *
  * The thread group cputime accouting is avoided when there are no posix
  * CPU timers armed. Before starting a timer it's required to check whether
@@ -274,14 +265,14 @@ void thread_group_sample_cputime(struct task_struct *tsk,
  *
  * Updates @times with an uptodate sample of the thread group cputimes.
  */
-static void
-thread_group_start_cputime(struct task_struct *tsk, struct task_cputime *times)
+static void thread_group_start_cputime(struct task_struct *tsk, u64 *samples)
 {
 	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
-	struct task_cputime sum;
 
 	/* Check if cputimer isn't running. This is accessed without locking. */
 	if (!READ_ONCE(cputimer->running)) {
+		struct task_cputime sum;
+
 		/*
 		 * The POSIX timer interface allows for absolute time expiry
 		 * values through the TIMER_ABSTIME flag, therefore we have
@@ -299,7 +290,15 @@ thread_group_start_cputime(struct task_struct *tsk, struct task_cputime *times)
 		 */
 		WRITE_ONCE(cputimer->running, true);
 	}
-	sample_cputime_atomic(times, &cputimer->cputime_atomic);
+	proc_sample_cputime_atomic(&cputimer->cputime_atomic, samples);
+}
+
+static void __thread_group_cputime(struct task_struct *tsk, u64 *samples)
+{
+	struct task_cputime ct;
+
+	thread_group_cputime(tsk, &ct);
+	store_samples(samples, ct.stime, ct.utime, ct.sum_exec_runtime);
 }
 
 /*
@@ -313,28 +312,18 @@ static u64 cpu_clock_sample_group(const clockid_t clkid, struct task_struct *p,
 				  bool start)
 {
 	struct thread_group_cputimer *cputimer = &p->signal->cputimer;
-	struct task_cputime cputime;
+	u64 samples[CPUCLOCK_MAX];
 
 	if (!READ_ONCE(cputimer->running)) {
 		if (start)
-			thread_group_start_cputime(p, &cputime);
+			thread_group_start_cputime(p, samples);
 		else
-			thread_group_cputime(p, &cputime);
+			__thread_group_cputime(p, samples);
 	} else {
-		sample_cputime_atomic(&cputime, &cputimer->cputime_atomic);
+		proc_sample_cputime_atomic(&cputimer->cputime_atomic, samples);
 	}
 
-	switch (clkid) {
-	case CPUCLOCK_PROF:
-		return cputime.utime + cputime.stime;
-	case CPUCLOCK_VIRT:
-		return cputime.utime;
-	case CPUCLOCK_SCHED:
-		return cputime.sum_exec_runtime;
-	default:
-		WARN_ON_ONCE(1);
-	}
-	return 0;
+	return samples[clkid];
 }
 
 static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)
@@ -889,9 +878,7 @@ static void check_process_timers(struct task_struct *tsk,
 {
 	struct signal_struct *const sig = tsk->signal;
 	struct posix_cputimer_base *base = sig->posix_cputimers.bases;
-	u64 utime, ptime, virt_expires, prof_expires;
-	u64 sum_sched_runtime, sched_expires;
-	struct task_cputime cputime;
+	u64 virt_exp, prof_exp, sched_exp, samples[CPUCLOCK_MAX];
 	unsigned long soft;
 
 	/*
@@ -911,30 +898,29 @@ static void check_process_timers(struct task_struct *tsk,
 	 * Collect the current process totals. Group accounting is active
 	 * so the sample can be taken directly.
 	 */
-	sample_cputime_atomic(&cputime, &sig->cputimer.cputime_atomic);
-	utime = cputime.utime;
-	ptime = utime + cputime.stime;
-	sum_sched_runtime = cputime.sum_exec_runtime;
-
-	prof_expires = check_timers_list(&base[CPUCLOCK_PROF].cpu_timers,
-					 firing, ptime);
-	virt_expires = check_timers_list(&base[CPUCLOCK_VIRT].cpu_timers,
-					 firing, utime);
-	sched_expires = check_timers_list(&base[CPUCLOCK_SCHED].cpu_timers,
-					  firing, sum_sched_runtime);
+	proc_sample_cputime_atomic(&sig->cputimer.cputime_atomic, samples);
+
+	prof_exp = check_timers_list(&base[CPUCLOCK_PROF].cpu_timers,
+				     firing, samples[CPUCLOCK_PROF]);
+	virt_exp = check_timers_list(&base[CPUCLOCK_VIRT].cpu_timers,
+				     firing, samples[CPUCLOCK_VIRT]);
+	sched_exp = check_timers_list(&base[CPUCLOCK_SCHED].cpu_timers,
+				      firing, samples[CPUCLOCK_SCHED]);
 
 	/*
 	 * Check for the special case process timers.
 	 */
-	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_PROF], &prof_expires, ptime,
-			 SIGPROF);
-	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_VIRT], &virt_expires, utime,
-			 SIGVTALRM);
+	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_PROF], &prof_exp,
+			 samples[CPUCLOCK_PROF], SIGPROF);
+	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_VIRT], &virt_exp,
+			 samples[CPUCLOCK_PROF], SIGVTALRM);
+
 	soft = task_rlimit(tsk, RLIMIT_CPU);
 	if (soft != RLIM_INFINITY) {
-		unsigned long psecs = div_u64(ptime, NSEC_PER_SEC);
+		u64 softns, ptime = samples[CPUCLOCK_PROF];
 		unsigned long hard = task_rlimit_max(tsk, RLIMIT_CPU);
-		u64 x;
+		unsigned long psecs = div_u64(ptime, NSEC_PER_SEC);
+
 		if (psecs >= hard) {
 			/*
 			 * At the hard limit, we just die.
@@ -961,14 +947,14 @@ static void check_process_timers(struct task_struct *tsk,
 				sig->rlim[RLIMIT_CPU].rlim_cur = soft;
 			}
 		}
-		x = soft * NSEC_PER_SEC;
-		if (!prof_expires || x < prof_expires)
-			prof_expires = x;
+		softns = soft * NSEC_PER_SEC;
+		if (!prof_exp || softns < prof_exp)
+			prof_exp = softns;
 	}
 
-	base[CPUCLOCK_PROF].nextevt = prof_expires;
-	base[CPUCLOCK_VIRT].nextevt = virt_expires;
-	base[CPUCLOCK_SCHED].nextevt = sched_expires;
+	base[CPUCLOCK_PROF].nextevt = prof_exp;
+	base[CPUCLOCK_VIRT].nextevt = virt_exp;
+	base[CPUCLOCK_SCHED].nextevt = sched_exp;
 
 	if (expiry_cache_is_zero(&sig->posix_cputimers))
 		stop_process_timers(sig);

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Restructure expiry array
  2019-08-26 18:22       ` [patch V3 " Thomas Gleixner
  2019-08-26 19:45         ` Frederic Weisbecker
@ 2019-08-28 10:16         ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Ingo Molnar, Thomas Gleixner, Frederic Weisbecker,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     87dc64480fb19a6a0fedbdff1e2557be50673287
Gitweb:        https://git.kernel.org/tip/87dc64480fb19a6a0fedbdff1e2557be50673287
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Mon, 26 Aug 2019 20:22:24 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:39 +02:00

posix-cpu-timers: Restructure expiry array

Now that the abused struct task_cputime is gone, it's more natural to
bundle the expiry cache and the list head of each clock into a struct and
have an array of those structs.

Follow the hrtimer naming convention of 'bases' and rename the expiry cache
to 'nextevt' and adapt all usage sites.

Generates also better code .text size shrinks by 80 bytes.

Suggested-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/alpine.DEB.2.21.1908262021140.1939@nanos.tec.linutronix.de

---
 include/linux/posix-timers.h   |  41 +++++++-----
 kernel/time/posix-cpu-timers.c | 105 +++++++++++++++++---------------
 2 files changed, 83 insertions(+), 63 deletions(-)

diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index fd90984..64bd10d 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -63,24 +63,33 @@ static inline int clockid_to_fd(const clockid_t clk)
 }
 
 #ifdef CONFIG_POSIX_TIMERS
+
 /**
- * posix_cputimers - Container for posix CPU timer related data
- * @expiries:		Earliest-expiration cache array based
+ * posix_cputimer_base - Container per posix CPU clock
+ * @nextevt:		Earliest-expiration cache
  * @cpu_timers:		List heads to queue posix CPU timers
+ */
+struct posix_cputimer_base {
+	u64			nextevt;
+	struct list_head	cpu_timers;
+};
+
+/**
+ * posix_cputimers - Container for posix CPU timer related data
+ * @bases:		Base container for posix CPU clocks
  *
  * Used in task_struct and signal_struct
  */
 struct posix_cputimers {
-	u64			expiries[CPUCLOCK_MAX];
-	struct list_head	cpu_timers[CPUCLOCK_MAX];
+	struct posix_cputimer_base	bases[CPUCLOCK_MAX];
 };
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
 {
-	memset(&pct->expiries, 0, sizeof(pct->expiries));
-	INIT_LIST_HEAD(&pct->cpu_timers[0]);
-	INIT_LIST_HEAD(&pct->cpu_timers[1]);
-	INIT_LIST_HEAD(&pct->cpu_timers[2]);
+	memset(pct->bases, 0, sizeof(pct->bases));
+	INIT_LIST_HEAD(&pct->bases[0].cpu_timers);
+	INIT_LIST_HEAD(&pct->bases[1].cpu_timers);
+	INIT_LIST_HEAD(&pct->bases[2].cpu_timers);
 }
 
 void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit);
@@ -88,19 +97,23 @@ void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit);
 static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct,
 					       u64 runtime)
 {
-	pct->expiries[CPUCLOCK_SCHED] = runtime;
+	pct->bases[CPUCLOCK_SCHED].nextevt = runtime;
 }
 
 /* Init task static initializer */
-#define INIT_CPU_TIMERLISTS(c)	{					\
-	LIST_HEAD_INIT(c.cpu_timers[0]),				\
-	LIST_HEAD_INIT(c.cpu_timers[1]),				\
-	LIST_HEAD_INIT(c.cpu_timers[2]),				\
+#define INIT_CPU_TIMERBASE(b) {						\
+	.cpu_timers = LIST_HEAD_INIT(b.cpu_timers),			\
+}
+
+#define INIT_CPU_TIMERBASES(b) {					\
+	INIT_CPU_TIMERBASE(b[0]),					\
+	INIT_CPU_TIMERBASE(b[1]),					\
+	INIT_CPU_TIMERBASE(b[2]),					\
 }
 
 #define INIT_CPU_TIMERS(s)						\
 	.posix_cputimers = {						\
-		.cpu_timers = INIT_CPU_TIMERLISTS(s.posix_cputimers),	\
+		.bases = INIT_CPU_TIMERBASES(s.posix_cputimers.bases),	\
 	},
 #else
 struct posix_cputimers { };
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index ffd4918..9ac601a 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -24,13 +24,13 @@ void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit)
 {
 	posix_cputimers_init(pct);
 	if (cpu_limit != RLIM_INFINITY)
-		pct->expiries[CPUCLOCK_PROF] = cpu_limit * NSEC_PER_SEC;
+		pct->bases[CPUCLOCK_PROF].nextevt = cpu_limit * NSEC_PER_SEC;
 }
 
 /*
  * Called after updating RLIMIT_CPU to run cpu timer and update
- * tsk->signal->posix_cputimers.expiries expiration cache if
- * necessary. Needs siglock protection since other code may update
+ * tsk->signal->posix_cputimers.bases[clock].nextevt expiration cache if
+ * necessary. Needs siglock protection since other code may update the
  * expiration cache as well.
  */
 void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new)
@@ -122,9 +122,11 @@ static void bump_cpu_timer(struct k_itimer *timer, u64 now)
 	}
 }
 
-static inline bool expiry_cache_is_zero(const u64 *ec)
+static inline bool expiry_cache_is_zero(const struct posix_cputimers *pct)
 {
-	return !(ec[CPUCLOCK_PROF] | ec[CPUCLOCK_VIRT] | ec[CPUCLOCK_SCHED]);
+	return !(pct->bases[CPUCLOCK_PROF].nextevt |
+		 pct->bases[CPUCLOCK_VIRT].nextevt |
+		 pct->bases[CPUCLOCK_SCHED].nextevt);
 }
 
 static int
@@ -432,9 +434,9 @@ static void cleanup_timers_list(struct list_head *head)
  */
 static void cleanup_timers(struct posix_cputimers *pct)
 {
-	cleanup_timers_list(&pct->cpu_timers[CPUCLOCK_PROF]);
-	cleanup_timers_list(&pct->cpu_timers[CPUCLOCK_VIRT]);
-	cleanup_timers_list(&pct->cpu_timers[CPUCLOCK_SCHED]);
+	cleanup_timers_list(&pct->bases[CPUCLOCK_PROF].cpu_timers);
+	cleanup_timers_list(&pct->bases[CPUCLOCK_VIRT].cpu_timers);
+	cleanup_timers_list(&pct->bases[CPUCLOCK_SCHED].cpu_timers);
 }
 
 /*
@@ -464,21 +466,19 @@ static void arm_timer(struct k_itimer *timer)
 {
 	struct cpu_timer_list *const nt = &timer->it.cpu;
 	int clkidx = CPUCLOCK_WHICH(timer->it_clock);
-	u64 *cpuexp, newexp = timer->it.cpu.expires;
 	struct task_struct *p = timer->it.cpu.task;
+	u64 newexp = timer->it.cpu.expires;
+	struct posix_cputimer_base *base;
 	struct list_head *head, *listpos;
 	struct cpu_timer_list *next;
 
-	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
-		head = p->posix_cputimers.cpu_timers + clkidx;
-		cpuexp = p->posix_cputimers.expiries + clkidx;
-	} else {
-		head = p->signal->posix_cputimers.cpu_timers + clkidx;
-		cpuexp = p->signal->posix_cputimers.expiries + clkidx;
-	}
+	if (CPUCLOCK_PERTHREAD(timer->it_clock))
+		base = p->posix_cputimers.bases + clkidx;
+	else
+		base = p->signal->posix_cputimers.bases + clkidx;
 
-	listpos = head;
-	list_for_each_entry(next, head, entry) {
+	listpos = head = &base->cpu_timers;
+	list_for_each_entry(next,head, entry) {
 		if (nt->expires < next->expires)
 			break;
 		listpos = &next->entry;
@@ -494,8 +494,8 @@ static void arm_timer(struct k_itimer *timer)
 	 * for process timers we share expiration cache with itimers
 	 * and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME.
 	 */
-	if (expires_gt(*cpuexp, newexp))
-		*cpuexp = newexp;
+	if (expires_gt(base->nextevt, newexp))
+		base->nextevt = newexp;
 
 	if (CPUCLOCK_PERTHREAD(timer->it_clock))
 		tick_dep_set_task(p, TICK_DEP_BIT_POSIX_TIMER);
@@ -783,9 +783,9 @@ static inline void check_dl_overrun(struct task_struct *tsk)
 static void check_thread_timers(struct task_struct *tsk,
 				struct list_head *firing)
 {
-	struct list_head *timers = tsk->posix_cputimers.cpu_timers;
-	u64 stime, utime, *expires = tsk->posix_cputimers.expiries;
+	struct posix_cputimer_base *base = tsk->posix_cputimers.bases;
 	unsigned long soft;
+	u64 stime, utime;
 
 	if (dl_task(tsk))
 		check_dl_overrun(tsk);
@@ -794,14 +794,18 @@ static void check_thread_timers(struct task_struct *tsk,
 	 * If the expiry cache is zero, then there are no active per thread
 	 * CPU timers.
 	 */
-	if (expiry_cache_is_zero(tsk->posix_cputimers.expiries))
+	if (expiry_cache_is_zero(&tsk->posix_cputimers))
 		return;
 
 	task_cputime(tsk, &utime, &stime);
 
-	*expires++ = check_timers_list(timers, firing, utime + stime);
-	*expires++ = check_timers_list(++timers, firing, utime);
-	*expires = check_timers_list(++timers, firing, tsk->se.sum_exec_runtime);
+	base->nextevt = check_timers_list(&base->cpu_timers, firing,
+					  utime + stime);
+	base++;
+	base->nextevt = check_timers_list(&base->cpu_timers, firing, utime);
+	base++;
+	base->nextevt = check_timers_list(&base->cpu_timers, firing,
+					  tsk->se.sum_exec_runtime);
 
 	/*
 	 * Check for the special case thread timers.
@@ -840,7 +844,7 @@ static void check_thread_timers(struct task_struct *tsk,
 		}
 	}
 
-	if (expiry_cache_is_zero(tsk->posix_cputimers.expiries))
+	if (expiry_cache_is_zero(&tsk->posix_cputimers))
 		tick_dep_clear_task(tsk, TICK_DEP_BIT_POSIX_TIMER);
 }
 
@@ -884,7 +888,7 @@ static void check_process_timers(struct task_struct *tsk,
 				 struct list_head *firing)
 {
 	struct signal_struct *const sig = tsk->signal;
-	struct list_head *timers = sig->posix_cputimers.cpu_timers;
+	struct posix_cputimer_base *base = sig->posix_cputimers.bases;
 	u64 utime, ptime, virt_expires, prof_expires;
 	u64 sum_sched_runtime, sched_expires;
 	struct task_cputime cputime;
@@ -912,9 +916,12 @@ static void check_process_timers(struct task_struct *tsk,
 	ptime = utime + cputime.stime;
 	sum_sched_runtime = cputime.sum_exec_runtime;
 
-	prof_expires = check_timers_list(timers, firing, ptime);
-	virt_expires = check_timers_list(++timers, firing, utime);
-	sched_expires = check_timers_list(++timers, firing, sum_sched_runtime);
+	prof_expires = check_timers_list(&base[CPUCLOCK_PROF].cpu_timers,
+					 firing, ptime);
+	virt_expires = check_timers_list(&base[CPUCLOCK_VIRT].cpu_timers,
+					 firing, utime);
+	sched_expires = check_timers_list(&base[CPUCLOCK_SCHED].cpu_timers,
+					  firing, sum_sched_runtime);
 
 	/*
 	 * Check for the special case process timers.
@@ -959,11 +966,11 @@ static void check_process_timers(struct task_struct *tsk,
 			prof_expires = x;
 	}
 
-	sig->posix_cputimers.expiries[CPUCLOCK_PROF] = prof_expires;
-	sig->posix_cputimers.expiries[CPUCLOCK_VIRT] = virt_expires;
-	sig->posix_cputimers.expiries[CPUCLOCK_SCHED] = sched_expires;
+	base[CPUCLOCK_PROF].nextevt = prof_expires;
+	base[CPUCLOCK_VIRT].nextevt = virt_expires;
+	base[CPUCLOCK_SCHED].nextevt = sched_expires;
 
-	if (expiry_cache_is_zero(sig->posix_cputimers.expiries))
+	if (expiry_cache_is_zero(&sig->posix_cputimers))
 		stop_process_timers(sig);
 
 	sig->cputimer.checking_timer = false;
@@ -1028,20 +1035,21 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
 }
 
 /**
- * task_cputimers_expired - Compare two task_cputime entities.
+ * task_cputimers_expired - Check whether posix CPU timers are expired
  *
  * @samples:	Array of current samples for the CPUCLOCK clocks
- * @expiries:	Array of expiry values for the CPUCLOCK clocks
+ * @pct:	Pointer to a posix_cputimers container
  *
- * Returns true if any mmember of @samples is greater than the corresponding
- * member of @expiries if that member is non zero. False otherwise
+ * Returns true if any member of @samples is greater than the corresponding
+ * member of @pct->bases[CLK].nextevt. False otherwise
  */
-static inline bool task_cputimers_expired(const u64 *sample, const u64 *expiries)
+static inline bool
+task_cputimers_expired(const u64 *sample, struct posix_cputimers *pct)
 {
 	int i;
 
 	for (i = 0; i < CPUCLOCK_MAX; i++) {
-		if (expiries[i] && sample[i] >= expiries[i])
+		if (pct->bases[i].nextevt && sample[i] >= pct->bases[i].nextevt)
 			return true;
 	}
 	return false;
@@ -1059,14 +1067,13 @@ static inline bool task_cputimers_expired(const u64 *sample, const u64 *expiries
  */
 static inline bool fastpath_timer_check(struct task_struct *tsk)
 {
-	u64 *expiries = tsk->posix_cputimers.expiries;
 	struct signal_struct *sig;
 
-	if (!expiry_cache_is_zero(expiries)) {
+	if (!expiry_cache_is_zero(&tsk->posix_cputimers)) {
 		u64 samples[CPUCLOCK_MAX];
 
 		task_sample_cputime(tsk, samples);
-		if (task_cputimers_expired(samples, expiries))
+		if (task_cputimers_expired(samples, &tsk->posix_cputimers))
 			return true;
 	}
 
@@ -1092,8 +1099,7 @@ static inline bool fastpath_timer_check(struct task_struct *tsk)
 		proc_sample_cputime_atomic(&sig->cputimer.cputime_atomic,
 					   samples);
 
-		if (task_cputimers_expired(samples,
-					   sig->posix_cputimers.expiries))
+		if (task_cputimers_expired(samples, &sig->posix_cputimers))
 			return true;
 	}
 
@@ -1176,11 +1182,12 @@ void run_posix_cpu_timers(void)
 void set_process_cpu_timer(struct task_struct *tsk, unsigned int clkid,
 			   u64 *newval, u64 *oldval)
 {
-	u64 now, *expiry = tsk->signal->posix_cputimers.expiries + clkid;
+	u64 now, *nextevt;
 
 	if (WARN_ON_ONCE(clkid >= CPUCLOCK_SCHED))
 		return;
 
+	nextevt = &tsk->signal->posix_cputimers.bases[clkid].nextevt;
 	now = cpu_clock_sample_group(clkid, tsk, true);
 
 	if (oldval) {
@@ -1207,8 +1214,8 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clkid,
 	 * Update expiration cache if this is the earliest timer. CPUCLOCK_PROF
 	 * expiry cache is also used by RLIMIT_CPU!.
 	 */
-	if (expires_gt(*expiry, *newval))
-		*expiry = *newval;
+	if (expires_gt(*nextevt, *newval))
+		*nextevt = *newval;
 
 	tick_dep_set_signal(tsk->signal, TICK_DEP_BIT_POSIX_TIMER);
 }

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Remove cputime_expires
  2019-08-21 19:09 ` [patch V2 27/38] posix-cpu-timers: Remove cputime_expires Thomas Gleixner
  2019-08-23 22:50   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     46b883995c88520f2c4de6a64cccc04c69d59f83
Gitweb:        https://git.kernel.org/tip/46b883995c88520f2c4de6a64cccc04c69d59f83
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:14 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:38 +02:00

posix-cpu-timers: Remove cputime_expires

The last users of the magic struct cputime based expiry cache are
gone. Remove the leftovers.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192921.790209622@linutronix.de

---
 include/linux/posix-timers.h   |  9 ++-------
 kernel/time/posix-cpu-timers.c | 10 ----------
 2 files changed, 2 insertions(+), 17 deletions(-)

diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index e36c6fd..fd90984 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -65,19 +65,14 @@ static inline int clockid_to_fd(const clockid_t clk)
 #ifdef CONFIG_POSIX_TIMERS
 /**
  * posix_cputimers - Container for posix CPU timer related data
- * @cputime_expires:	Earliest-expiration cache task_cputime based
  * @expiries:		Earliest-expiration cache array based
  * @cpu_timers:		List heads to queue posix CPU timers
  *
  * Used in task_struct and signal_struct
  */
 struct posix_cputimers {
-	/* Temporary union until all users are cleaned up */
-	union {
-		struct task_cputime	cputime_expires;
-		u64			expiries[CPUCLOCK_MAX];
-	};
-	struct list_head		cpu_timers[CPUCLOCK_MAX];
+	u64			expiries[CPUCLOCK_MAX];
+	struct list_head	cpu_timers[CPUCLOCK_MAX];
 };
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index e159b03..ffd4918 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -18,16 +18,6 @@
 
 #include "posix-timers.h"
 
-static inline void temporary_check(void)
-{
-	BUILD_BUG_ON(offsetof(struct task_cputime, stime) !=
-		     CPUCLOCK_PROF * sizeof(u64));
-	BUILD_BUG_ON(offsetof(struct task_cputime, utime) !=
-		     CPUCLOCK_VIRT * sizeof(u64));
-	BUILD_BUG_ON(offsetof(struct task_cputime, sum_exec_runtime) !=
-		     CPUCLOCK_SCHED * sizeof(u64));
-}
-
 static void posix_cpu_timer_rearm(struct k_itimer *timer);
 
 void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit)

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] rlimit: Rewrite non-sensical RLIMIT_CPU comment
  2019-08-21 19:09 ` [patch V2 31/38] rlimit: Rewrite non-sensical RLIMIT_CPU comment Thomas Gleixner
  2019-08-26 21:41   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     24db4dd90dd53ad6e3331b6f01cb985e466cface
Gitweb:        https://git.kernel.org/tip/24db4dd90dd53ad6e3331b6f01cb985e466cface
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:18 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:40 +02:00

rlimit: Rewrite non-sensical RLIMIT_CPU comment

The comment above the function which arms RLIMIT_CPU in the posix CPU timer
code makes no sense at all. It claims that the kernel does not return an
error code when it rejected the attempt to set RLIMIT_CPU. That's clearly
bogus as the code does an error check and the rlimit is only set and
activated when the permission checks are ok. In case of a rejection an
appropriate error code is returned.

This is a historical and outdated comment which got dragged along even when
the rlimit handling code was rewritten.

Replace it with an explanation why the setup function is not called when
the rlimit value is RLIM_INFINITY and how the 'disarming' is handled.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192922.185511287@linutronix.de

---
 kernel/sys.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/kernel/sys.c b/kernel/sys.c
index 2969304..c578b75 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1576,10 +1576,9 @@ int do_prlimit(struct task_struct *tsk, unsigned int resource,
 	task_unlock(tsk->group_leader);
 
 	/*
-	 * RLIMIT_CPU handling.   Note that the kernel fails to return an error
-	 * code if it rejected the user's attempt to set RLIMIT_CPU.  This is a
-	 * very long-standing error, and fixing it now risks breakage of
-	 * applications, so we live with it
+	 * RLIMIT_CPU handling. Arm the posix CPU timer if the limit is not
+	 * infite. In case of RLIM_INFINITY the posix CPU timer code
+	 * ignores the rlimit.
 	 */
 	 if (!retval && new_rlim && resource == RLIMIT_CPU &&
 	     new_rlim->rlim_cur != RLIM_INFINITY &&

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Respect INFINITY for hard RTTIME limit
  2019-08-21 19:09 ` [patch V2 30/38] posix-cpu-timers: Respect INFINITY for hard RTTIME limit Thomas Gleixner
  2019-08-26 21:19   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     fe0517f893d36636de20d0a809fc0c788ca0cade
Gitweb:        https://git.kernel.org/tip/fe0517f893d36636de20d0a809fc0c788ca0cade
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:17 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:39 +02:00

posix-cpu-timers: Respect INFINITY for hard RTTIME limit

The RTIME limit expiry code does not check the hard RTTIME limit for
INFINITY, i.e. being disabled.  Add it.

While this could be considered an ABI breakage if something would depend on
this behaviour. Though it's highly unlikely to have an effect because
RLIM_INFINITY is at minimum INT_MAX and the RTTIME limit is in seconds, so
the timer would fire after ~68 years.

Adding this obvious correct limit check also allows further consolidation
of that code and is a prerequisite for cleaning up the 0 based checks and
the rlimit setter code.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192922.078293002@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index e62139a..a738d76 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -921,7 +921,7 @@ static void check_process_timers(struct task_struct *tsk,
 		unsigned long hard = task_rlimit_max(tsk, RLIMIT_CPU);
 		unsigned long psecs = div_u64(ptime, NSEC_PER_SEC);
 
-		if (psecs >= hard) {
+		if (hard != RLIM_INFINITY && psecs >= hard) {
 			/*
 			 * At the hard limit, we just die.
 			 * No need to calculate anything else now.

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Get rid of zero checks
  2019-08-21 19:09 ` [patch V2 32/38] posix-cpu-timers: Get rid of zero checks Thomas Gleixner
  2019-08-26 21:57   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     2bbdbdae05167c688b6d3499a7dab74208b80a22
Gitweb:        https://git.kernel.org/tip/2bbdbdae05167c688b6d3499a7dab74208b80a22
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:19 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:40 +02:00

posix-cpu-timers: Get rid of zero checks

Deactivation of the expiry cache is done by setting all clock caches to
0. That requires to have a check for zero in all places which update the
expiry cache:

	if (cache == 0 || new < cache)
		cache = new;

Use U64_MAX as the deactivated value, which allows to remove the zero
checks when updating the cache and reduces it to the obvious check:

	if (new < cache)
		cache = new;

This also removes the weird workaround in do_prlimit() which was required
to convert a RLIMIT_CPU value of 0 (immediate expiry) to 1 because handing
in 0 to the posix CPU timer code would have effectively disarmed it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192922.275086128@linutronix.de

---
 include/linux/posix-timers.h   |  7 ++++--
 kernel/sys.c                   |  9 +--------
 kernel/time/posix-cpu-timers.c | 38 +++++++++++++--------------------
 3 files changed, 20 insertions(+), 34 deletions(-)

diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 64bd10d..3ea920e 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -86,7 +86,9 @@ struct posix_cputimers {
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
 {
-	memset(pct->bases, 0, sizeof(pct->bases));
+	pct->bases[0].nextevt = U64_MAX;
+	pct->bases[1].nextevt = U64_MAX;
+	pct->bases[2].nextevt = U64_MAX;
 	INIT_LIST_HEAD(&pct->bases[0].cpu_timers);
 	INIT_LIST_HEAD(&pct->bases[1].cpu_timers);
 	INIT_LIST_HEAD(&pct->bases[2].cpu_timers);
@@ -102,7 +104,8 @@ static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct,
 
 /* Init task static initializer */
 #define INIT_CPU_TIMERBASE(b) {						\
-	.cpu_timers = LIST_HEAD_INIT(b.cpu_timers),			\
+	.nextevt	= U64_MAX,					\
+	.cpu_timers	= LIST_HEAD_INIT(b.cpu_timers),			\
 }
 
 #define INIT_CPU_TIMERBASES(b) {					\
diff --git a/kernel/sys.c b/kernel/sys.c
index c578b75..2462aa8 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1557,15 +1557,6 @@ int do_prlimit(struct task_struct *tsk, unsigned int resource,
 			retval = -EPERM;
 		if (!retval)
 			retval = security_task_setrlimit(tsk, resource, new_rlim);
-		if (resource == RLIMIT_CPU && new_rlim->rlim_cur == 0) {
-			/*
-			 * The caller is asking for an immediate RLIMIT_CPU
-			 * expiry.  But we use the zero value to mean "it was
-			 * never set".  So let's cheat and make it one second
-			 * instead
-			 */
-			new_rlim->rlim_cur = 1;
-		}
 	}
 	if (!retval) {
 		if (old_rlim)
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index a738d76..cf85292 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -122,11 +122,12 @@ static void bump_cpu_timer(struct k_itimer *timer, u64 now)
 	}
 }
 
-static inline bool expiry_cache_is_zero(const struct posix_cputimers *pct)
+/* Check whether all cache entries contain U64_MAX, i.e. eternal expiry time */
+static inline bool expiry_cache_is_inactive(const struct posix_cputimers *pct)
 {
-	return !(pct->bases[CPUCLOCK_PROF].nextevt |
-		 pct->bases[CPUCLOCK_VIRT].nextevt |
-		 pct->bases[CPUCLOCK_SCHED].nextevt);
+	return !(~pct->bases[CPUCLOCK_PROF].nextevt |
+		 ~pct->bases[CPUCLOCK_VIRT].nextevt |
+		 ~pct->bases[CPUCLOCK_SCHED].nextevt);
 }
 
 static int
@@ -442,11 +443,6 @@ void posix_cpu_timers_exit_group(struct task_struct *tsk)
 	cleanup_timers(&tsk->signal->posix_cputimers);
 }
 
-static inline int expires_gt(u64 expires, u64 new_exp)
-{
-	return expires == 0 || expires > new_exp;
-}
-
 /*
  * Insert the timer on the appropriate list before any timers that
  * expire later.  This must be called with the sighand lock held.
@@ -483,7 +479,7 @@ static void arm_timer(struct k_itimer *timer)
 	 * for process timers we share expiration cache with itimers
 	 * and RLIMIT_CPU and for thread timers with RLIMIT_RTTIME.
 	 */
-	if (expires_gt(base->nextevt, newexp))
+	if (newexp < base->nextevt)
 		base->nextevt = newexp;
 
 	if (CPUCLOCK_PERTHREAD(timer->it_clock))
@@ -753,7 +749,7 @@ check_timers_list(struct list_head *timers,
 		list_move_tail(&t->entry, firing);
 	}
 
-	return 0;
+	return U64_MAX;
 }
 
 static inline void check_dl_overrun(struct task_struct *tsk)
@@ -779,11 +775,7 @@ static void check_thread_timers(struct task_struct *tsk,
 	if (dl_task(tsk))
 		check_dl_overrun(tsk);
 
-	/*
-	 * If the expiry cache is zero, then there are no active per thread
-	 * CPU timers.
-	 */
-	if (expiry_cache_is_zero(&tsk->posix_cputimers))
+	if (expiry_cache_is_inactive(&tsk->posix_cputimers))
 		return;
 
 	task_cputime(tsk, &utime, &stime);
@@ -833,7 +825,7 @@ static void check_thread_timers(struct task_struct *tsk,
 		}
 	}
 
-	if (expiry_cache_is_zero(&tsk->posix_cputimers))
+	if (expiry_cache_is_inactive(&tsk->posix_cputimers))
 		tick_dep_clear_task(tsk, TICK_DEP_BIT_POSIX_TIMER);
 }
 
@@ -864,7 +856,7 @@ static void check_cpu_itimer(struct task_struct *tsk, struct cpu_itimer *it,
 		__group_send_sig_info(signo, SEND_SIG_PRIV, tsk);
 	}
 
-	if (it->expires && (!*expires || it->expires < *expires))
+	if (it->expires && it->expires < *expires)
 		*expires = it->expires;
 }
 
@@ -948,7 +940,7 @@ static void check_process_timers(struct task_struct *tsk,
 			}
 		}
 		softns = soft * NSEC_PER_SEC;
-		if (!prof_exp || softns < prof_exp)
+		if (softns < prof_exp)
 			prof_exp = softns;
 	}
 
@@ -956,7 +948,7 @@ static void check_process_timers(struct task_struct *tsk,
 	base[CPUCLOCK_VIRT].nextevt = virt_exp;
 	base[CPUCLOCK_SCHED].nextevt = sched_exp;
 
-	if (expiry_cache_is_zero(&sig->posix_cputimers))
+	if (expiry_cache_is_inactive(&sig->posix_cputimers))
 		stop_process_timers(sig);
 
 	sig->cputimer.checking_timer = false;
@@ -1035,7 +1027,7 @@ task_cputimers_expired(const u64 *sample, struct posix_cputimers *pct)
 	int i;
 
 	for (i = 0; i < CPUCLOCK_MAX; i++) {
-		if (pct->bases[i].nextevt && sample[i] >= pct->bases[i].nextevt)
+		if (sample[i] >= pct->bases[i].nextevt)
 			return true;
 	}
 	return false;
@@ -1055,7 +1047,7 @@ static inline bool fastpath_timer_check(struct task_struct *tsk)
 {
 	struct signal_struct *sig;
 
-	if (!expiry_cache_is_zero(&tsk->posix_cputimers)) {
+	if (!expiry_cache_is_inactive(&tsk->posix_cputimers)) {
 		u64 samples[CPUCLOCK_MAX];
 
 		task_sample_cputime(tsk, samples);
@@ -1200,7 +1192,7 @@ void set_process_cpu_timer(struct task_struct *tsk, unsigned int clkid,
 	 * Update expiration cache if this is the earliest timer. CPUCLOCK_PROF
 	 * expiry cache is also used by RLIMIT_CPU!.
 	 */
-	if (expires_gt(*nextevt, *newval))
+	if (*newval < *nextevt)
 		*nextevt = *newval;
 
 	tick_dep_set_signal(tsk->signal, TICK_DEP_BIT_POSIX_TIMER);

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Consolidate timer expiry further
  2019-08-21 19:09 ` [patch V2 33/38] posix-cpu-timers: Consolidate timer expiry further Thomas Gleixner
  2019-08-26 22:29   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     1cd07c0b94f2c320270d76edb7dd49bceb09c1df
Gitweb:        https://git.kernel.org/tip/1cd07c0b94f2c320270d76edb7dd49bceb09c1df
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:20 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:41 +02:00

posix-cpu-timers: Consolidate timer expiry further

With the array based samples and expiry cache, the expiry function can use
a loop to collect timers from the clock specific lists.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192922.365469982@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 63 +++++++++++++++------------------
 1 file changed, 30 insertions(+), 33 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index cf85292..caafdfd 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -752,6 +752,18 @@ check_timers_list(struct list_head *timers,
 	return U64_MAX;
 }
 
+static void collect_posix_cputimers(struct posix_cputimers *pct,
+				    u64 *samples, struct list_head *firing)
+{
+	struct posix_cputimer_base *base = pct->bases;
+	int i;
+
+	for (i = 0; i < CPUCLOCK_MAX; i++, base++) {
+		base->nextevt = check_timers_list(&base->cpu_timers, firing,
+						   samples[i]);
+	}
+}
+
 static inline void check_dl_overrun(struct task_struct *tsk)
 {
 	if (tsk->dl.dl_overrun) {
@@ -768,25 +780,18 @@ static inline void check_dl_overrun(struct task_struct *tsk)
 static void check_thread_timers(struct task_struct *tsk,
 				struct list_head *firing)
 {
-	struct posix_cputimer_base *base = tsk->posix_cputimers.bases;
+	struct posix_cputimers *pct = &tsk->posix_cputimers;
+	u64 samples[CPUCLOCK_MAX];
 	unsigned long soft;
-	u64 stime, utime;
 
 	if (dl_task(tsk))
 		check_dl_overrun(tsk);
 
-	if (expiry_cache_is_inactive(&tsk->posix_cputimers))
+	if (expiry_cache_is_inactive(pct))
 		return;
 
-	task_cputime(tsk, &utime, &stime);
-
-	base->nextevt = check_timers_list(&base->cpu_timers, firing,
-					  utime + stime);
-	base++;
-	base->nextevt = check_timers_list(&base->cpu_timers, firing, utime);
-	base++;
-	base->nextevt = check_timers_list(&base->cpu_timers, firing,
-					  tsk->se.sum_exec_runtime);
+	task_sample_cputime(tsk, samples);
+	collect_posix_cputimers(pct, samples, firing);
 
 	/*
 	 * Check for the special case thread timers.
@@ -825,7 +830,7 @@ static void check_thread_timers(struct task_struct *tsk,
 		}
 	}
 
-	if (expiry_cache_is_inactive(&tsk->posix_cputimers))
+	if (expiry_cache_is_inactive(pct))
 		tick_dep_clear_task(tsk, TICK_DEP_BIT_POSIX_TIMER);
 }
 
@@ -869,15 +874,15 @@ static void check_process_timers(struct task_struct *tsk,
 				 struct list_head *firing)
 {
 	struct signal_struct *const sig = tsk->signal;
-	struct posix_cputimer_base *base = sig->posix_cputimers.bases;
-	u64 virt_exp, prof_exp, sched_exp, samples[CPUCLOCK_MAX];
+	struct posix_cputimers *pct = &sig->posix_cputimers;
+	u64 samples[CPUCLOCK_MAX];
 	unsigned long soft;
 
 	/*
 	 * If cputimer is not running, then there are no active
 	 * process wide timers (POSIX 1.b, itimers, RLIMIT_CPU).
 	 */
-	if (!READ_ONCE(tsk->signal->cputimer.running))
+	if (!READ_ONCE(sig->cputimer.running))
 		return;
 
        /*
@@ -891,21 +896,17 @@ static void check_process_timers(struct task_struct *tsk,
 	 * so the sample can be taken directly.
 	 */
 	proc_sample_cputime_atomic(&sig->cputimer.cputime_atomic, samples);
-
-	prof_exp = check_timers_list(&base[CPUCLOCK_PROF].cpu_timers,
-				     firing, samples[CPUCLOCK_PROF]);
-	virt_exp = check_timers_list(&base[CPUCLOCK_VIRT].cpu_timers,
-				     firing, samples[CPUCLOCK_VIRT]);
-	sched_exp = check_timers_list(&base[CPUCLOCK_SCHED].cpu_timers,
-				      firing, samples[CPUCLOCK_SCHED]);
+	collect_posix_cputimers(pct, samples, firing);
 
 	/*
 	 * Check for the special case process timers.
 	 */
-	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_PROF], &prof_exp,
+	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_PROF],
+			 &pct->bases[CPUCLOCK_PROF].nextevt,
 			 samples[CPUCLOCK_PROF], SIGPROF);
-	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_VIRT], &virt_exp,
-			 samples[CPUCLOCK_PROF], SIGVTALRM);
+	check_cpu_itimer(tsk, &sig->it[CPUCLOCK_VIRT],
+			 &pct->bases[CPUCLOCK_VIRT].nextevt,
+			 samples[CPUCLOCK_VIRT], SIGVTALRM);
 
 	soft = task_rlimit(tsk, RLIMIT_CPU);
 	if (soft != RLIM_INFINITY) {
@@ -940,15 +941,11 @@ static void check_process_timers(struct task_struct *tsk,
 			}
 		}
 		softns = soft * NSEC_PER_SEC;
-		if (softns < prof_exp)
-			prof_exp = softns;
+		if (softns < pct->bases[CPUCLOCK_PROF].nextevt)
+			pct->bases[CPUCLOCK_PROF].nextevt = softns;
 	}
 
-	base[CPUCLOCK_PROF].nextevt = prof_exp;
-	base[CPUCLOCK_VIRT].nextevt = virt_exp;
-	base[CPUCLOCK_SCHED].nextevt = sched_exp;
-
-	if (expiry_cache_is_inactive(&sig->posix_cputimers))
+	if (expiry_cache_is_inactive(pct))
 		stop_process_timers(sig);
 
 	sig->cputimer.checking_timer = false;

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Get rid of 64bit divisions
  2019-08-21 19:09 ` [patch V2 34/38] posix-cpu-timers: Get rid of 64bit divisions Thomas Gleixner
  2019-08-26 22:51   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     8ea1de90a5eccdc18c8f05f8596bae8660a3ff9a
Gitweb:        https://git.kernel.org/tip/8ea1de90a5eccdc18c8f05f8596bae8660a3ff9a
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:21 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:41 +02:00

posix-cpu-timers: Get rid of 64bit divisions

Instead of dividing A to match the units of B it's more efficient to
multiply B to match the units of A.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192922.458286860@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 24 ++++++++++++++----------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index caafdfd..dcdf9c8 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -798,10 +798,11 @@ static void check_thread_timers(struct task_struct *tsk,
 	 */
 	soft = task_rlimit(tsk, RLIMIT_RTTIME);
 	if (soft != RLIM_INFINITY) {
+		/* Task RT timeout is accounted in jiffies. RTTIME is usec */
+		unsigned long rtim = tsk->rt.timeout * (USEC_PER_SEC / HZ);
 		unsigned long hard = task_rlimit_max(tsk, RLIMIT_RTTIME);
 
-		if (hard != RLIM_INFINITY &&
-		    tsk->rt.timeout > DIV_ROUND_UP(hard, USEC_PER_SEC/HZ)) {
+		if (hard != RLIM_INFINITY && rtim >= hard) {
 			/*
 			 * At the hard limit, we just die.
 			 * No need to calculate anything else now.
@@ -813,7 +814,7 @@ static void check_thread_timers(struct task_struct *tsk,
 			__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
 			return;
 		}
-		if (tsk->rt.timeout > DIV_ROUND_UP(soft, USEC_PER_SEC/HZ)) {
+		if (rtim >= soft) {
 			/*
 			 * At the soft limit, send a SIGXCPU every second.
 			 */
@@ -910,11 +911,13 @@ static void check_process_timers(struct task_struct *tsk,
 
 	soft = task_rlimit(tsk, RLIMIT_CPU);
 	if (soft != RLIM_INFINITY) {
-		u64 softns, ptime = samples[CPUCLOCK_PROF];
+		/* RLIMIT_CPU is in seconds. Samples are nanoseconds */
 		unsigned long hard = task_rlimit_max(tsk, RLIMIT_CPU);
-		unsigned long psecs = div_u64(ptime, NSEC_PER_SEC);
+		u64 ptime = samples[CPUCLOCK_PROF];
+		u64 softns = (u64)soft * NSEC_PER_SEC;
+		u64 hardns = (u64)hard * NSEC_PER_SEC;
 
-		if (hard != RLIM_INFINITY && psecs >= hard) {
+		if (hard != RLIM_INFINITY && ptime >= hardns) {
 			/*
 			 * At the hard limit, we just die.
 			 * No need to calculate anything else now.
@@ -926,7 +929,7 @@ static void check_process_timers(struct task_struct *tsk,
 			__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
 			return;
 		}
-		if (psecs >= soft) {
+		if (ptime >= softns) {
 			/*
 			 * At the soft limit, send a SIGXCPU every second.
 			 */
@@ -936,11 +939,12 @@ static void check_process_timers(struct task_struct *tsk,
 			}
 			__group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
 			if (soft < hard) {
-				soft++;
-				sig->rlim[RLIMIT_CPU].rlim_cur = soft;
+				sig->rlim[RLIMIT_CPU].rlim_cur = soft + 1;
+				softns += NSEC_PER_SEC;
 			}
 		}
-		softns = soft * NSEC_PER_SEC;
+
+		/* Update the expiry cache */
 		if (softns < pct->bases[CPUCLOCK_PROF].nextevt)
 			pct->bases[CPUCLOCK_PROF].nextevt = softns;
 	}

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Remove pointless comparisons
  2019-08-21 19:09 ` [patch V2 35/38] posix-cpu-timers: Remove pointless comparisons Thomas Gleixner
  2019-08-26 22:59   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     dd6702241337bcd0bae01d2644b7bae1a496d937
Gitweb:        https://git.kernel.org/tip/dd6702241337bcd0bae01d2644b7bae1a496d937
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:22 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:42 +02:00

posix-cpu-timers: Remove pointless comparisons

The soft RLIMIT expiry code checks whether the soft limit is greater than
the hard limit. That's pointless because if the soft RLIMIT is greater than
the hard RLIMIT then that code cannot be reached as the hard RLIMIT check
is before that and already killed the process.

Remove it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192922.548747613@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index dcdf9c8..115c8df 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -814,15 +814,14 @@ static void check_thread_timers(struct task_struct *tsk,
 			__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
 			return;
 		}
+
 		if (rtim >= soft) {
 			/*
 			 * At the soft limit, send a SIGXCPU every second.
 			 */
-			if (soft < hard) {
-				soft += USEC_PER_SEC;
-				tsk->signal->rlim[RLIMIT_RTTIME].rlim_cur =
-					soft;
-			}
+			soft += USEC_PER_SEC;
+			tsk->signal->rlim[RLIMIT_RTTIME].rlim_cur = soft;
+
 			if (print_fatal_signals) {
 				pr_info("RT Watchdog Timeout (soft): %s[%d]\n",
 					tsk->comm, task_pid_nr(tsk));
@@ -938,10 +937,9 @@ static void check_process_timers(struct task_struct *tsk,
 					tsk->comm, task_pid_nr(tsk));
 			}
 			__group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
-			if (soft < hard) {
-				sig->rlim[RLIMIT_CPU].rlim_cur = soft + 1;
-				softns += NSEC_PER_SEC;
-			}
+
+			sig->rlim[RLIMIT_CPU].rlim_cur = soft + 1;
+			softns += NSEC_PER_SEC;
 		}
 
 		/* Update the expiry cache */

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Deduplicate rlimit handling
  2019-08-21 19:09 ` [patch V2 36/38] posix-cpu-timers: Deduplicate rlimit handling Thomas Gleixner
  2019-08-26 23:13   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     8991afe2640d05a805eba01277856e8549cdc838
Gitweb:        https://git.kernel.org/tip/8991afe2640d05a805eba01277856e8549cdc838
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:23 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:42 +02:00

posix-cpu-timers: Deduplicate rlimit handling

Both thread and process expiry functions have the same functionality for
sending signals for soft and hard RLIMITs duplicated in 4 different
ways.

Split it out into a common function and cleanup the callsites.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/20190821192922.653276779@linutronix.de

---
 kernel/time/posix-cpu-timers.c | 67 ++++++++++++---------------------
 1 file changed, 25 insertions(+), 42 deletions(-)

diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 115c8df..ef39a7a 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -772,6 +772,20 @@ static inline void check_dl_overrun(struct task_struct *tsk)
 	}
 }
 
+static bool check_rlimit(u64 time, u64 limit, int signo, bool rt, bool hard)
+{
+	if (time < limit)
+		return false;
+
+	if (print_fatal_signals) {
+		pr_info("%s Watchdog Timeout (%s): %s[%d]\n",
+			rt ? "RT" : "CPU", hard ? "hard" : "soft",
+			current->comm, task_pid_nr(current));
+	}
+	__group_send_sig_info(signo, SEND_SIG_PRIV, current);
+	return true;
+}
+
 /*
  * 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
@@ -799,34 +813,18 @@ static void check_thread_timers(struct task_struct *tsk,
 	soft = task_rlimit(tsk, RLIMIT_RTTIME);
 	if (soft != RLIM_INFINITY) {
 		/* Task RT timeout is accounted in jiffies. RTTIME is usec */
-		unsigned long rtim = tsk->rt.timeout * (USEC_PER_SEC / HZ);
+		unsigned long rttime = tsk->rt.timeout * (USEC_PER_SEC / HZ);
 		unsigned long hard = task_rlimit_max(tsk, RLIMIT_RTTIME);
 
-		if (hard != RLIM_INFINITY && rtim >= hard) {
-			/*
-			 * At the hard limit, we just die.
-			 * No need to calculate anything else now.
-			 */
-			if (print_fatal_signals) {
-				pr_info("CPU Watchdog Timeout (hard): %s[%d]\n",
-					tsk->comm, task_pid_nr(tsk));
-			}
-			__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
+		/* At the hard limit, send SIGKILL. No further action. */
+		if (hard != RLIM_INFINITY &&
+		    check_rlimit(rttime, hard, SIGKILL, true, true))
 			return;
-		}
 
-		if (rtim >= soft) {
-			/*
-			 * At the soft limit, send a SIGXCPU every second.
-			 */
+		/* At the soft limit, send a SIGXCPU every second */
+		if (check_rlimit(rttime, soft, SIGXCPU, true, false)) {
 			soft += USEC_PER_SEC;
 			tsk->signal->rlim[RLIMIT_RTTIME].rlim_cur = soft;
-
-			if (print_fatal_signals) {
-				pr_info("RT Watchdog Timeout (soft): %s[%d]\n",
-					tsk->comm, task_pid_nr(tsk));
-			}
-			__group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
 		}
 	}
 
@@ -916,28 +914,13 @@ static void check_process_timers(struct task_struct *tsk,
 		u64 softns = (u64)soft * NSEC_PER_SEC;
 		u64 hardns = (u64)hard * NSEC_PER_SEC;
 
-		if (hard != RLIM_INFINITY && ptime >= hardns) {
-			/*
-			 * At the hard limit, we just die.
-			 * No need to calculate anything else now.
-			 */
-			if (print_fatal_signals) {
-				pr_info("RT Watchdog Timeout (hard): %s[%d]\n",
-					tsk->comm, task_pid_nr(tsk));
-			}
-			__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
+		/* At the hard limit, send SIGKILL. No further action. */
+		if (hard != RLIM_INFINITY &&
+		    check_rlimit(ptime, hardns, SIGKILL, false, true))
 			return;
-		}
-		if (ptime >= softns) {
-			/*
-			 * At the soft limit, send a SIGXCPU every second.
-			 */
-			if (print_fatal_signals) {
-				pr_info("CPU Watchdog Timeout (soft): %s[%d]\n",
-					tsk->comm, task_pid_nr(tsk));
-			}
-			__group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
 
+		/* At the soft limit, send a SIGXCPU every second */
+		if (check_rlimit(ptime, softns, SIGXCPU, false, false)) {
 			sig->rlim[RLIMIT_CPU].rlim_cur = soft + 1;
 			softns += NSEC_PER_SEC;
 		}

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Move state tracking to struct posix_cputimers
  2019-08-21 19:09 ` [patch V2 37/38] posix-cpu-timers: Move state tracking to struct posix_cputimers Thomas Gleixner
  2019-08-26 23:28   ` Frederic Weisbecker
@ 2019-08-28 10:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Ingo Molnar, Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     244d49e30653658d4e7e9b2b8427777cbbc5affe
Gitweb:        https://git.kernel.org/tip/244d49e30653658d4e7e9b2b8427777cbbc5affe
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Wed, 21 Aug 2019 21:09:24 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:42 +02:00

posix-cpu-timers: Move state tracking to struct posix_cputimers

Put it where it belongs and clean up the ifdeffery in fork completely.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20190821192922.743229404@linutronix.de

---
 include/linux/posix-timers.h   |  8 ++++-
 include/linux/sched/cputime.h  |  9 ++--
 include/linux/sched/signal.h   |  6 +---
 init/init_task.c               |  2 +-
 kernel/fork.c                  |  6 +---
 kernel/time/posix-cpu-timers.c | 73 ++++++++++++++++++---------------
 6 files changed, 54 insertions(+), 50 deletions(-)

diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 3ea920e..a9e3f69 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -77,15 +77,23 @@ struct posix_cputimer_base {
 /**
  * posix_cputimers - Container for posix CPU timer related data
  * @bases:		Base container for posix CPU clocks
+ * @timers_active:	Timers are queued.
+ * @expiry_active:	Timer expiry is active. Used for
+ *			process wide timers to avoid multiple
+ *			task trying to handle expiry concurrently
  *
  * Used in task_struct and signal_struct
  */
 struct posix_cputimers {
 	struct posix_cputimer_base	bases[CPUCLOCK_MAX];
+	unsigned int			timers_active;
+	unsigned int			expiry_active;
 };
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
 {
+	pct->timers_active = 0;
+	pct->expiry_active = 0;
 	pct->bases[0].nextevt = U64_MAX;
 	pct->bases[1].nextevt = U64_MAX;
 	pct->bases[2].nextevt = U64_MAX;
diff --git a/include/linux/sched/cputime.h b/include/linux/sched/cputime.h
index eefa5df..6c9f19a 100644
--- a/include/linux/sched/cputime.h
+++ b/include/linux/sched/cputime.h
@@ -70,7 +70,7 @@ void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples);
  */
 
 /**
- * get_running_cputimer - return &tsk->signal->cputimer if cputimer is running
+ * get_running_cputimer - return &tsk->signal->cputimer if cputimers are active
  *
  * @tsk:	Pointer to target task.
  */
@@ -80,8 +80,11 @@ struct thread_group_cputimer *get_running_cputimer(struct task_struct *tsk)
 {
 	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
 
-	/* Check if cputimer isn't running. This is accessed without locking. */
-	if (!READ_ONCE(cputimer->running))
+	/*
+	 * Check whether posix CPU timers are active. If not the thread
+	 * group accounting is not active either. Lockless check.
+	 */
+	if (!READ_ONCE(tsk->signal->posix_cputimers.timers_active))
 		return NULL;
 
 	/*
diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h
index 729bd89..8805025 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -57,18 +57,12 @@ struct task_cputime_atomic {
 /**
  * struct thread_group_cputimer - thread group interval timer counts
  * @cputime_atomic:	atomic thread group interval timers.
- * @running:		true when there are timers running and
- *			@cputime_atomic receives updates.
- * @checking_timer:	true when a thread in the group is in the
- *			process of checking for thread group timers.
  *
  * This structure contains the version of task_cputime, above, that is
  * used for thread group CPU timer calculations.
  */
 struct thread_group_cputimer {
 	struct task_cputime_atomic cputime_atomic;
-	bool running;
-	bool checking_timer;
 };
 
 struct multiprocess_signals {
diff --git a/init/init_task.c b/init/init_task.c
index 7ab773b..d49692a 100644
--- a/init/init_task.c
+++ b/init/init_task.c
@@ -30,8 +30,6 @@ static struct signal_struct init_signals = {
 	.posix_timers = LIST_HEAD_INIT(init_signals.posix_timers),
 	.cputimer	= {
 		.cputime_atomic	= INIT_CPUTIME_ATOMIC,
-		.running	= false,
-		.checking_timer = false,
 	},
 #endif
 	INIT_CPU_TIMERS(init_signals)
diff --git a/kernel/fork.c b/kernel/fork.c
index 52bfe7c..f1228d9 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1517,7 +1517,6 @@ void __cleanup_sighand(struct sighand_struct *sighand)
 	}
 }
 
-#ifdef CONFIG_POSIX_TIMERS
 /*
  * Initialize POSIX timer handling for a thread group.
  */
@@ -1528,12 +1527,7 @@ static void posix_cpu_timers_init_group(struct signal_struct *sig)
 
 	cpu_limit = READ_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur);
 	posix_cputimers_group_init(pct, cpu_limit);
-	if (cpu_limit != RLIM_INFINITY)
-		sig->cputimer.running = true;
 }
-#else
-static inline void posix_cpu_timers_init_group(struct signal_struct *sig) { }
-#endif
 
 static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
 {
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index ef39a7a..52f4c99 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -23,8 +23,10 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer);
 void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit)
 {
 	posix_cputimers_init(pct);
-	if (cpu_limit != RLIM_INFINITY)
+	if (cpu_limit != RLIM_INFINITY) {
 		pct->bases[CPUCLOCK_PROF].nextevt = cpu_limit * NSEC_PER_SEC;
+		pct->timers_active = true;
+	}
 }
 
 /*
@@ -248,8 +250,9 @@ static void update_gt_cputime(struct task_cputime_atomic *cputime_atomic,
 void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples)
 {
 	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
+	struct posix_cputimers *pct = &tsk->signal->posix_cputimers;
 
-	WARN_ON_ONCE(!cputimer->running);
+	WARN_ON_ONCE(!pct->timers_active);
 
 	proc_sample_cputime_atomic(&cputimer->cputime_atomic, samples);
 }
@@ -269,9 +272,10 @@ void thread_group_sample_cputime(struct task_struct *tsk, u64 *samples)
 static void thread_group_start_cputime(struct task_struct *tsk, u64 *samples)
 {
 	struct thread_group_cputimer *cputimer = &tsk->signal->cputimer;
+	struct posix_cputimers *pct = &tsk->signal->posix_cputimers;
 
 	/* Check if cputimer isn't running. This is accessed without locking. */
-	if (!READ_ONCE(cputimer->running)) {
+	if (!READ_ONCE(pct->timers_active)) {
 		struct task_cputime sum;
 
 		/*
@@ -283,13 +287,13 @@ static void thread_group_start_cputime(struct task_struct *tsk, u64 *samples)
 		update_gt_cputime(&cputimer->cputime_atomic, &sum);
 
 		/*
-		 * We're setting cputimer->running without a lock. Ensure
-		 * this only gets written to in one operation. We set
-		 * running after update_gt_cputime() as a small optimization,
-		 * but barriers are not required because update_gt_cputime()
+		 * We're setting timers_active without a lock. Ensure this
+		 * only gets written to in one operation. We set it after
+		 * update_gt_cputime() as a small optimization, but
+		 * barriers are not required because update_gt_cputime()
 		 * can handle concurrent updates.
 		 */
-		WRITE_ONCE(cputimer->running, true);
+		WRITE_ONCE(pct->timers_active, true);
 	}
 	proc_sample_cputime_atomic(&cputimer->cputime_atomic, samples);
 }
@@ -313,9 +317,10 @@ static u64 cpu_clock_sample_group(const clockid_t clkid, struct task_struct *p,
 				  bool start)
 {
 	struct thread_group_cputimer *cputimer = &p->signal->cputimer;
+	struct posix_cputimers *pct = &p->signal->posix_cputimers;
 	u64 samples[CPUCLOCK_MAX];
 
-	if (!READ_ONCE(cputimer->running)) {
+	if (!READ_ONCE(pct->timers_active)) {
 		if (start)
 			thread_group_start_cputime(p, samples);
 		else
@@ -834,10 +839,10 @@ static void check_thread_timers(struct task_struct *tsk,
 
 static inline void stop_process_timers(struct signal_struct *sig)
 {
-	struct thread_group_cputimer *cputimer = &sig->cputimer;
+	struct posix_cputimers *pct = &sig->posix_cputimers;
 
-	/* Turn off cputimer->running. This is done without locking. */
-	WRITE_ONCE(cputimer->running, false);
+	/* Turn off the active flag. This is done without locking. */
+	WRITE_ONCE(pct->timers_active, false);
 	tick_dep_clear_signal(sig, TICK_DEP_BIT_POSIX_TIMER);
 }
 
@@ -877,17 +882,17 @@ static void check_process_timers(struct task_struct *tsk,
 	unsigned long soft;
 
 	/*
-	 * If cputimer is not running, then there are no active
-	 * process wide timers (POSIX 1.b, itimers, RLIMIT_CPU).
+	 * If there are no active process wide timers (POSIX 1.b, itimers,
+	 * RLIMIT_CPU) nothing to check.
 	 */
-	if (!READ_ONCE(sig->cputimer.running))
+	if (!READ_ONCE(pct->timers_active))
 		return;
 
        /*
 	 * Signify that a thread is checking for process timers.
 	 * Write access to this field is protected by the sighand lock.
 	 */
-	sig->cputimer.checking_timer = true;
+	pct->timers_active = true;
 
 	/*
 	 * Collect the current process totals. Group accounting is active
@@ -933,7 +938,7 @@ static void check_process_timers(struct task_struct *tsk,
 	if (expiry_cache_is_inactive(pct))
 		stop_process_timers(sig);
 
-	sig->cputimer.checking_timer = false;
+	pct->expiry_active = false;
 }
 
 /*
@@ -1027,39 +1032,41 @@ task_cputimers_expired(const u64 *sample, struct posix_cputimers *pct)
  */
 static inline bool fastpath_timer_check(struct task_struct *tsk)
 {
+	struct posix_cputimers *pct = &tsk->posix_cputimers;
 	struct signal_struct *sig;
 
-	if (!expiry_cache_is_inactive(&tsk->posix_cputimers)) {
+	if (!expiry_cache_is_inactive(pct)) {
 		u64 samples[CPUCLOCK_MAX];
 
 		task_sample_cputime(tsk, samples);
-		if (task_cputimers_expired(samples, &tsk->posix_cputimers))
+		if (task_cputimers_expired(samples, pct))
 			return true;
 	}
 
 	sig = tsk->signal;
+	pct = &sig->posix_cputimers;
 	/*
-	 * Check if thread group timers expired when the cputimer is
-	 * running and no other thread in the group is already checking
-	 * for thread group cputimers. These fields are read without the
-	 * sighand lock. However, this is fine because this is meant to
-	 * be a fastpath heuristic to determine whether we should try to
-	 * acquire the sighand lock to check/handle timers.
+	 * Check if thread group timers expired when timers are active and
+	 * no other thread in the group is already handling expiry for
+	 * thread group cputimers. These fields are read without the
+	 * sighand lock. However, this is fine because this is meant to be
+	 * a fastpath heuristic to determine whether we should try to
+	 * acquire the sighand lock to handle timer expiry.
 	 *
-	 * In the worst case scenario, if 'running' or 'checking_timer' gets
-	 * set but the current thread doesn't see the change yet, we'll wait
-	 * until the next thread in the group gets a scheduler interrupt to
-	 * handle the timer. This isn't an issue in practice because these
-	 * types of delays with signals actually getting sent are expected.
+	 * In the worst case scenario, if concurrently timers_active is set
+	 * or expiry_active is cleared, but the current thread doesn't see
+	 * the change yet, the timer checks are delayed until the next
+	 * thread in the group gets a scheduler interrupt to handle the
+	 * timer. This isn't an issue in practice because these types of
+	 * delays with signals actually getting sent are expected.
 	 */
-	if (READ_ONCE(sig->cputimer.running) &&
-	    !READ_ONCE(sig->cputimer.checking_timer)) {
+	if (READ_ONCE(pct->timers_active) && !READ_ONCE(pct->expiry_active)) {
 		u64 samples[CPUCLOCK_MAX];
 
 		proc_sample_cputime_atomic(&sig->cputimer.cputime_atomic,
 					   samples);
 
-		if (task_cputimers_expired(samples, &sig->posix_cputimers))
+		if (task_cputimers_expired(samples, pct))
 			return true;
 	}
 

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* [tip: timers/core] posix-cpu-timers: Utilize timerqueue for storage
  2019-08-27 19:31           ` [patch V3 " Thomas Gleixner
  2019-08-27 22:23             ` Frederic Weisbecker
@ 2019-08-28 10:16             ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 137+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2019-08-28 10:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Thomas Gleixner, Frederic Weisbecker, Ingo Molnar,
	Borislav Petkov, linux-kernel

The following commit has been merged into the timers/core branch of tip:

Commit-ID:     60bda037f1dd8151e0c9ee5b09f0c091a0f643cd
Gitweb:        https://git.kernel.org/tip/60bda037f1dd8151e0c9ee5b09f0c091a0f643cd
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Tue, 27 Aug 2019 21:31:02 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Wed, 28 Aug 2019 11:50:43 +02:00

posix-cpu-timers: Utilize timerqueue for storage

Using a linear O(N) search for timer insertion affects execution time and
D-cache footprint badly with a larger number of timers.

Switch the storage to a timerqueue which is already used for hrtimers and
alarmtimers. It does not affect the size of struct k_itimer as it.alarm is
still larger.

The extra list head for the expiry list will go away later once the expiry
is moved into task work context.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://lkml.kernel.org/r/alpine.DEB.2.21.1908272129220.1939@nanos.tec.linutronix.de

---
 include/linux/posix-timers.h   |  65 ++++++++---
 include/linux/timerqueue.h     |  10 ++-
 kernel/time/posix-cpu-timers.c | 189 ++++++++++++++++----------------
 3 files changed, 155 insertions(+), 109 deletions(-)

diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index a9e3f69..f9fbb4c 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -5,17 +5,11 @@
 #include <linux/spinlock.h>
 #include <linux/list.h>
 #include <linux/alarmtimer.h>
+#include <linux/timerqueue.h>
 
 struct kernel_siginfo;
 struct task_struct;
 
-struct cpu_timer_list {
-	struct list_head entry;
-	u64 expires;
-	struct task_struct *task;
-	int firing;
-};
-
 /*
  * Bit fields within a clockid:
  *
@@ -65,13 +59,57 @@ static inline int clockid_to_fd(const clockid_t clk)
 #ifdef CONFIG_POSIX_TIMERS
 
 /**
+ * cpu_timer - Posix CPU timer representation for k_itimer
+ * @node:	timerqueue node to queue in the task/sig
+ * @head:	timerqueue head on which this timer is queued
+ * @task:	Pointer to target task
+ * @elist:	List head for the expiry list
+ * @firing:	Timer is currently firing
+ */
+struct cpu_timer {
+	struct timerqueue_node	node;
+	struct timerqueue_head	*head;
+	struct task_struct	*task;
+	struct list_head	elist;
+	int			firing;
+};
+
+static inline bool cpu_timer_requeue(struct cpu_timer *ctmr)
+{
+	return timerqueue_add(ctmr->head, &ctmr->node);
+}
+
+static inline bool cpu_timer_enqueue(struct timerqueue_head *head,
+				     struct cpu_timer *ctmr)
+{
+	ctmr->head = head;
+	return timerqueue_add(head, &ctmr->node);
+}
+
+static inline void cpu_timer_dequeue(struct cpu_timer *ctmr)
+{
+	if (!RB_EMPTY_NODE(&ctmr->node.node))
+		timerqueue_del(ctmr->head, &ctmr->node);
+}
+
+static inline u64 cpu_timer_getexpires(struct cpu_timer *ctmr)
+{
+	return ctmr->node.expires;
+}
+
+static inline void cpu_timer_setexpires(struct cpu_timer *ctmr, u64 exp)
+{
+	ctmr->node.expires = exp;
+}
+
+/**
  * posix_cputimer_base - Container per posix CPU clock
  * @nextevt:		Earliest-expiration cache
- * @cpu_timers:		List heads to queue posix CPU timers
+ * @tqhead:		timerqueue head for cpu_timers
  */
 struct posix_cputimer_base {
 	u64			nextevt;
-	struct list_head	cpu_timers;
+	struct timerqueue_head	tqhead;
 };
 
 /**
@@ -92,14 +130,10 @@ struct posix_cputimers {
 
 static inline void posix_cputimers_init(struct posix_cputimers *pct)
 {
-	pct->timers_active = 0;
-	pct->expiry_active = 0;
+	memset(pct, 0, sizeof(*pct));
 	pct->bases[0].nextevt = U64_MAX;
 	pct->bases[1].nextevt = U64_MAX;
 	pct->bases[2].nextevt = U64_MAX;
-	INIT_LIST_HEAD(&pct->bases[0].cpu_timers);
-	INIT_LIST_HEAD(&pct->bases[1].cpu_timers);
-	INIT_LIST_HEAD(&pct->bases[2].cpu_timers);
 }
 
 void posix_cputimers_group_init(struct posix_cputimers *pct, u64 cpu_limit);
@@ -113,7 +147,6 @@ static inline void posix_cputimers_rt_watchdog(struct posix_cputimers *pct,
 /* Init task static initializer */
 #define INIT_CPU_TIMERBASE(b) {						\
 	.nextevt	= U64_MAX,					\
-	.cpu_timers	= LIST_HEAD_INIT(b.cpu_timers),			\
 }
 
 #define INIT_CPU_TIMERBASES(b) {					\
@@ -182,7 +215,7 @@ struct k_itimer {
 		struct {
 			struct hrtimer	timer;
 		} real;
-		struct cpu_timer_list	cpu;
+		struct cpu_timer	cpu;
 		struct {
 			struct alarm	alarmtimer;
 		} alarm;
diff --git a/include/linux/timerqueue.h b/include/linux/timerqueue.h
index aff122f..9388408 100644
--- a/include/linux/timerqueue.h
+++ b/include/linux/timerqueue.h
@@ -43,6 +43,16 @@ static inline void timerqueue_init(struct timerqueue_node *node)
 	RB_CLEAR_NODE(&node->node);
 }
 
+static inline bool timerqueue_node_queued(struct timerqueue_node *node)
+{
+	return !RB_EMPTY_NODE(&node->node);
+}
+
+static inline bool timerqueue_node_expires(struct timerqueue_node *node)
+{
+	return node->expires;
+}
+
 static inline void timerqueue_init_head(struct timerqueue_head *head)
 {
 	head->rb_root = RB_ROOT_CACHED;
diff --git a/kernel/time/posix-cpu-timers.c b/kernel/time/posix-cpu-timers.c
index 52f4c99..73c492c 100644
--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -96,19 +96,19 @@ static inline int validate_clock_permissions(const clockid_t clock)
  * Update expiry time from increment, and increase overrun count,
  * given the current clock sample.
  */
-static void bump_cpu_timer(struct k_itimer *timer, u64 now)
+static u64 bump_cpu_timer(struct k_itimer *timer, u64 now)
 {
+	u64 delta, incr, expires = timer->it.cpu.node.expires;
 	int i;
-	u64 delta, incr;
 
 	if (!timer->it_interval)
-		return;
+		return expires;
 
-	if (now < timer->it.cpu.expires)
-		return;
+	if (now < expires)
+		return expires;
 
 	incr = timer->it_interval;
-	delta = now + incr - timer->it.cpu.expires;
+	delta = now + incr - expires;
 
 	/* Don't use (incr*2 < delta), incr*2 might overflow. */
 	for (i = 0; incr < delta - incr; i++)
@@ -118,10 +118,11 @@ static void bump_cpu_timer(struct k_itimer *timer, u64 now)
 		if (delta < incr)
 			continue;
 
-		timer->it.cpu.expires += incr;
+		timer->it.cpu.node.expires += incr;
 		timer->it_overrun += 1LL << i;
 		delta -= incr;
 	}
+	return timer->it.cpu.node.expires;
 }
 
 /* Check whether all cache entries contain U64_MAX, i.e. eternal expiry time */
@@ -365,7 +366,7 @@ static int posix_cpu_timer_create(struct k_itimer *new_timer)
 		return -EINVAL;
 
 	new_timer->kclock = &clock_posix_cpu;
-	INIT_LIST_HEAD(&new_timer->it.cpu.entry);
+	timerqueue_init(&new_timer->it.cpu.node);
 	new_timer->it.cpu.task = p;
 	return 0;
 }
@@ -378,10 +379,11 @@ static int posix_cpu_timer_create(struct k_itimer *new_timer)
  */
 static int posix_cpu_timer_del(struct k_itimer *timer)
 {
-	int ret = 0;
-	unsigned long flags;
+	struct cpu_timer *ctmr = &timer->it.cpu;
+	struct task_struct *p = ctmr->task;
 	struct sighand_struct *sighand;
-	struct task_struct *p = timer->it.cpu.task;
+	unsigned long flags;
+	int ret = 0;
 
 	if (WARN_ON_ONCE(!p))
 		return -EINVAL;
@@ -393,15 +395,15 @@ static int posix_cpu_timer_del(struct k_itimer *timer)
 	sighand = lock_task_sighand(p, &flags);
 	if (unlikely(sighand == NULL)) {
 		/*
-		 * We raced with the reaping of the task.
-		 * The deletion should have cleared us off the list.
+		 * This raced with the reaping of the task. The exit cleanup
+		 * should have removed this timer from the timer queue.
 		 */
-		WARN_ON_ONCE(!list_empty(&timer->it.cpu.entry));
+		WARN_ON_ONCE(ctmr->head || timerqueue_node_queued(&ctmr->node));
 	} else {
 		if (timer->it.cpu.firing)
 			ret = TIMER_RETRY;
 		else
-			list_del(&timer->it.cpu.entry);
+			cpu_timer_dequeue(ctmr);
 
 		unlock_task_sighand(p, &flags);
 	}
@@ -412,12 +414,16 @@ static int posix_cpu_timer_del(struct k_itimer *timer)
 	return ret;
 }
 
-static void cleanup_timers_list(struct list_head *head)
+static void cleanup_timerqueue(struct timerqueue_head *head)
 {
-	struct cpu_timer_list *timer, *next;
+	struct timerqueue_node *node;
+	struct cpu_timer *ctmr;
 
-	list_for_each_entry_safe(timer, next, head, entry)
-		list_del_init(&timer->entry);
+	while ((node = timerqueue_getnext(head))) {
+		timerqueue_del(head, node);
+		ctmr = container_of(node, struct cpu_timer, node);
+		ctmr->head = NULL;
+	}
 }
 
 /*
@@ -429,9 +435,9 @@ static void cleanup_timers_list(struct list_head *head)
  */
 static void cleanup_timers(struct posix_cputimers *pct)
 {
-	cleanup_timers_list(&pct->bases[CPUCLOCK_PROF].cpu_timers);
-	cleanup_timers_list(&pct->bases[CPUCLOCK_VIRT].cpu_timers);
-	cleanup_timers_list(&pct->bases[CPUCLOCK_SCHED].cpu_timers);
+	cleanup_timerqueue(&pct->bases[CPUCLOCK_PROF].tqhead);
+	cleanup_timerqueue(&pct->bases[CPUCLOCK_VIRT].tqhead);
+	cleanup_timerqueue(&pct->bases[CPUCLOCK_SCHED].tqhead);
 }
 
 /*
@@ -454,28 +460,18 @@ void posix_cpu_timers_exit_group(struct task_struct *tsk)
  */
 static void arm_timer(struct k_itimer *timer)
 {
-	struct cpu_timer_list *const nt = &timer->it.cpu;
 	int clkidx = CPUCLOCK_WHICH(timer->it_clock);
-	struct task_struct *p = timer->it.cpu.task;
-	u64 newexp = timer->it.cpu.expires;
+	struct cpu_timer *ctmr = &timer->it.cpu;
+	u64 newexp = cpu_timer_getexpires(ctmr);
+	struct task_struct *p = ctmr->task;
 	struct posix_cputimer_base *base;
-	struct list_head *head, *listpos;
-	struct cpu_timer_list *next;
 
 	if (CPUCLOCK_PERTHREAD(timer->it_clock))
 		base = p->posix_cputimers.bases + clkidx;
 	else
 		base = p->signal->posix_cputimers.bases + clkidx;
 
-	listpos = head = &base->cpu_timers;
-	list_for_each_entry(next,head, entry) {
-		if (nt->expires < next->expires)
-			break;
-		listpos = &next->entry;
-	}
-	list_add(&nt->entry, listpos);
-
-	if (listpos != head)
+	if (!cpu_timer_enqueue(&base->tqhead, ctmr))
 		return;
 
 	/*
@@ -498,24 +494,26 @@ static void arm_timer(struct k_itimer *timer)
  */
 static void cpu_timer_fire(struct k_itimer *timer)
 {
+	struct cpu_timer *ctmr = &timer->it.cpu;
+
 	if ((timer->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) {
 		/*
 		 * User don't want any signal.
 		 */
-		timer->it.cpu.expires = 0;
+		cpu_timer_setexpires(ctmr, 0);
 	} else if (unlikely(timer->sigq == NULL)) {
 		/*
 		 * This a special case for clock_nanosleep,
 		 * not a normal timer from sys_timer_create.
 		 */
 		wake_up_process(timer->it_process);
-		timer->it.cpu.expires = 0;
+		cpu_timer_setexpires(ctmr, 0);
 	} else if (!timer->it_interval) {
 		/*
 		 * One-shot timer.  Clear it as soon as it's fired.
 		 */
 		posix_timer_event(timer, 0);
-		timer->it.cpu.expires = 0;
+		cpu_timer_setexpires(ctmr, 0);
 	} else if (posix_timer_event(timer, ++timer->it_requeue_pending)) {
 		/*
 		 * The signal did not get queued because the signal
@@ -539,10 +537,11 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
 {
 	clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
 	u64 old_expires, new_expires, old_incr, val;
-	struct task_struct *p = timer->it.cpu.task;
+	struct cpu_timer *ctmr = &timer->it.cpu;
+	struct task_struct *p = ctmr->task;
 	struct sighand_struct *sighand;
 	unsigned long flags;
-	int ret;
+	int ret = 0;
 
 	if (WARN_ON_ONCE(!p))
 		return -EINVAL;
@@ -562,22 +561,21 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
 	 * If p has just been reaped, we can no
 	 * longer get any information about it at all.
 	 */
-	if (unlikely(sighand == NULL)) {
+	if (unlikely(sighand == NULL))
 		return -ESRCH;
-	}
 
 	/*
 	 * Disarm any old timer after extracting its expiry time.
 	 */
-
-	ret = 0;
 	old_incr = timer->it_interval;
-	old_expires = timer->it.cpu.expires;
+	old_expires = cpu_timer_getexpires(ctmr);
+
 	if (unlikely(timer->it.cpu.firing)) {
 		timer->it.cpu.firing = -1;
 		ret = TIMER_RETRY;
-	} else
-		list_del_init(&timer->it.cpu.entry);
+	} else {
+		cpu_timer_dequeue(ctmr);
+	}
 
 	/*
 	 * We need to sample the current value to convert the new
@@ -598,18 +596,16 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
 			old->it_value.tv_nsec = 0;
 		} else {
 			/*
-			 * Update the timer in case it has
-			 * overrun already.  If it has,
-			 * we'll report it as having overrun
-			 * and with the next reloaded timer
-			 * already ticking, though we are
-			 * swallowing that pending
-			 * notification here to install the
-			 * new setting.
+			 * Update the timer in case it has overrun already.
+			 * If it has, we'll report it as having overrun and
+			 * with the next reloaded timer already ticking,
+			 * though we are swallowing that pending
+			 * notification here to install the new setting.
 			 */
-			bump_cpu_timer(timer, val);
-			if (val < timer->it.cpu.expires) {
-				old_expires = timer->it.cpu.expires - val;
+			u64 exp = bump_cpu_timer(timer, val);
+
+			if (val < exp) {
+				old_expires = exp - val;
 				old->it_value = ns_to_timespec64(old_expires);
 			} else {
 				old->it_value.tv_nsec = 1;
@@ -638,7 +634,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
 	 * For a timer with no notification action, we don't actually
 	 * arm the timer (we'll just fake it for timer_gettime).
 	 */
-	timer->it.cpu.expires = new_expires;
+	cpu_timer_setexpires(ctmr, new_expires);
 	if (new_expires != 0 && val < new_expires) {
 		arm_timer(timer);
 	}
@@ -680,8 +676,9 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
 static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp)
 {
 	clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
-	struct task_struct *p = timer->it.cpu.task;
-	u64 now;
+	struct cpu_timer *ctmr = &timer->it.cpu;
+	u64 now, expires = cpu_timer_getexpires(ctmr);
+	struct task_struct *p = ctmr->task;
 
 	if (WARN_ON_ONCE(!p))
 		return;
@@ -691,7 +688,7 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
 	 */
 	itp->it_interval = ktime_to_timespec64(timer->it_interval);
 
-	if (!timer->it.cpu.expires)
+	if (!expires)
 		return;
 
 	/*
@@ -713,9 +710,9 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
 			/*
 			 * The process has been reaped.
 			 * We can't even collect a sample any more.
-			 * Call the timer disarmed, nothing else to do.
+			 * Disarm the timer, nothing else to do.
 			 */
-			timer->it.cpu.expires = 0;
+			cpu_timer_setexpires(ctmr, 0);
 			return;
 		} else {
 			now = cpu_clock_sample_group(clkid, p, false);
@@ -723,8 +720,8 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
 		}
 	}
 
-	if (now < timer->it.cpu.expires) {
-		itp->it_value = ns_to_timespec64(timer->it.cpu.expires - now);
+	if (now < expires) {
+		itp->it_value = ns_to_timespec64(expires - now);
 	} else {
 		/*
 		 * The timer should have expired already, but the firing
@@ -735,37 +732,41 @@ static void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec64 *itp
 	}
 }
 
-static unsigned long long
-check_timers_list(struct list_head *timers,
-		  struct list_head *firing,
-		  unsigned long long curr)
-{
-	int maxfire = 20;
-
-	while (!list_empty(timers)) {
-		struct cpu_timer_list *t;
-
-		t = list_first_entry(timers, struct cpu_timer_list, entry);
+#define MAX_COLLECTED	20
 
-		if (!--maxfire || curr < t->expires)
-			return t->expires;
-
-		t->firing = 1;
-		list_move_tail(&t->entry, firing);
+static u64 collect_timerqueue(struct timerqueue_head *head,
+			      struct list_head *firing, u64 now)
+{
+	struct timerqueue_node *next;
+	int i = 0;
+
+	while ((next = timerqueue_getnext(head))) {
+		struct cpu_timer *ctmr;
+		u64 expires;
+
+		ctmr = container_of(next, struct cpu_timer, node);
+		expires = cpu_timer_getexpires(ctmr);
+		/* Limit the number of timers to expire at once */
+		if (++i == MAX_COLLECTED || now < expires)
+			return expires;
+
+		ctmr->firing = 1;
+		cpu_timer_dequeue(ctmr);
+		list_add_tail(&ctmr->elist, firing);
 	}
 
 	return U64_MAX;
 }
 
-static void collect_posix_cputimers(struct posix_cputimers *pct,
-				    u64 *samples, struct list_head *firing)
+static void collect_posix_cputimers(struct posix_cputimers *pct, u64 *samples,
+				    struct list_head *firing)
 {
 	struct posix_cputimer_base *base = pct->bases;
 	int i;
 
 	for (i = 0; i < CPUCLOCK_MAX; i++, base++) {
-		base->nextevt = check_timers_list(&base->cpu_timers, firing,
-						   samples[i]);
+		base->nextevt = collect_timerqueue(&base->tqhead, firing,
+						    samples[i]);
 	}
 }
 
@@ -948,7 +949,8 @@ static void check_process_timers(struct task_struct *tsk,
 static void posix_cpu_timer_rearm(struct k_itimer *timer)
 {
 	clockid_t clkid = CPUCLOCK_WHICH(timer->it_clock);
-	struct task_struct *p = timer->it.cpu.task;
+	struct cpu_timer *ctmr = &timer->it.cpu;
+	struct task_struct *p = ctmr->task;
 	struct sighand_struct *sighand;
 	unsigned long flags;
 	u64 now;
@@ -980,7 +982,7 @@ static void posix_cpu_timer_rearm(struct k_itimer *timer)
 			 * The process has been reaped.
 			 * We can't even collect a sample any more.
 			 */
-			timer->it.cpu.expires = 0;
+			cpu_timer_setexpires(ctmr, 0);
 			return;
 		} else if (unlikely(p->exit_state) && thread_group_empty(p)) {
 			/* If the process is dying, no need to rearm */
@@ -1124,11 +1126,11 @@ void run_posix_cpu_timers(void)
 	 * each timer's lock before clearing its firing flag, so no
 	 * timer call will interfere.
 	 */
-	list_for_each_entry_safe(timer, next, &firing, it.cpu.entry) {
+	list_for_each_entry_safe(timer, next, &firing, it.cpu.elist) {
 		int cpu_firing;
 
 		spin_lock(&timer->it_lock);
-		list_del_init(&timer->it.cpu.entry);
+		list_del_init(&timer->it.cpu.elist);
 		cpu_firing = timer->it.cpu.firing;
 		timer->it.cpu.firing = 0;
 		/*
@@ -1204,6 +1206,7 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 	timer.it_overrun = -1;
 	error = posix_cpu_timer_create(&timer);
 	timer.it_process = current;
+
 	if (!error) {
 		static struct itimerspec64 zero_it;
 		struct restart_block *restart;
@@ -1219,7 +1222,7 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 		}
 
 		while (!signal_pending(current)) {
-			if (timer.it.cpu.expires == 0) {
+			if (!cpu_timer_getexpires(&timer.it.cpu)) {
 				/*
 				 * Our timer fired and was reset, below
 				 * deletion can not fail.
@@ -1241,7 +1244,7 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags,
 		/*
 		 * We were interrupted by a signal.
 		 */
-		expires = timer.it.cpu.expires;
+		expires = cpu_timer_getexpires(&timer.it.cpu);
 		error = posix_cpu_timer_set(&timer, 0, &zero_it, &it);
 		if (!error) {
 			/*

^ permalink raw reply related	[flat|nested] 137+ messages in thread

* Re: [tip: timers/core] posix-cpu-timers: Use common permission check in posix_cpu_clock_get()
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
@ 2019-08-29 11:00     ` kbuild test robot
  2019-08-29 11:21       ` Thomas Gleixner
  2019-08-29 11:23     ` kbuild test robot
  1 sibling, 1 reply; 137+ messages in thread
From: kbuild test robot @ 2019-08-29 11:00 UTC (permalink / raw)
  To: tip-bot2 for Thomas Gleixner
  Cc: kbuild-all, linux-tip-commits, Thomas Gleixner,
	Frederic Weisbecker, Ingo Molnar, Borislav Petkov, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2215 bytes --]

Hi tip-bot2,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[cannot apply to v5.3-rc6 next-20190828]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/tip-bot2-for-Thomas-Gleixner/posix-cpu-timers-Use-common-permission-check-in-posix_cpu_clock_get/20190829-181227
config: parisc-c3000_defconfig (attached as .config)
compiler: hppa-linux-gcc (GCC) 7.4.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=7.4.0 make.cross ARCH=parisc 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

   kernel/time/posix-cpu-timers.c: In function 'posix_cpu_clock_get':
>> kernel/time/posix-cpu-timers.c:275:8: error: implicit declaration of function 'get_task_for_clock'; did you mean 'get_task_struct'? [-Werror=implicit-function-declaration]
     tsk = get_task_for_clock(clock);
           ^~~~~~~~~~~~~~~~~~
           get_task_struct
>> kernel/time/posix-cpu-timers.c:275:6: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
     tsk = get_task_for_clock(clock);
         ^
   cc1: some warnings being treated as errors

vim +275 kernel/time/posix-cpu-timers.c

   268	
   269	static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)
   270	{
   271		const clockid_t clkid = CPUCLOCK_WHICH(clock);
   272		struct task_struct *tsk;
   273		u64 t;
   274	
 > 275		tsk = get_task_for_clock(clock);
   276		if (!tsk)
   277			return -EINVAL;
   278	
   279		if (CPUCLOCK_PERTHREAD(clock))
   280			cpu_clock_sample(clkid, tsk, &t);
   281		else
   282			cpu_clock_sample_group(clkid, tsk, &t);
   283		put_task_struct(tsk);
   284	
   285		*tp = ns_to_timespec64(t);
   286		return 0;
   287	}
   288	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 15667 bytes --]

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [tip: timers/core] posix-cpu-timers: Use common permission check in posix_cpu_clock_get()
  2019-08-29 11:00     ` kbuild test robot
@ 2019-08-29 11:21       ` Thomas Gleixner
  2019-08-30  1:08         ` [kbuild-all] " Philip Li
  0 siblings, 1 reply; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-29 11:21 UTC (permalink / raw)
  To: kbuild test robot
  Cc: tip-bot2 for Thomas Gleixner, kbuild-all, linux-tip-commits,
	Frederic Weisbecker, Ingo Molnar, Borislav Petkov, linux-kernel

On Thu, 29 Aug 2019, kbuild test robot wrote:
> Thank you for the patch! Yet something to improve:
> 
> [auto build test ERROR on linus/master]
> [cannot apply to v5.3-rc6 next-20190828]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

I have no idea what you are testing there.

>    kernel/time/posix-cpu-timers.c: In function 'posix_cpu_clock_get':
> >> kernel/time/posix-cpu-timers.c:275:8: error: implicit declaration of function 'get_task_for_clock'; did you mean 'get_task_struct'? [-Werror=implicit-function-declaration]
>      tsk = get_task_for_clock(clock);
>            ^~~~~~~~~~~~~~~~~~
>            get_task_struct
> >> kernel/time/posix-cpu-timers.c:275:6: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
>      tsk = get_task_for_clock(clock);
>          ^
>    cc1: some warnings being treated as errors

That commit comes _after_ the commit which introduced the function and
get_task_for_clock() is defined above posix_cpu_clock_get(), so I assume
you missed to apply the commit on which this depends on.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [tip: timers/core] posix-cpu-timers: Use common permission check in posix_cpu_clock_get()
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
  2019-08-29 11:00     ` kbuild test robot
@ 2019-08-29 11:23     ` kbuild test robot
  1 sibling, 0 replies; 137+ messages in thread
From: kbuild test robot @ 2019-08-29 11:23 UTC (permalink / raw)
  To: tip-bot2 for Thomas Gleixner
  Cc: kbuild-all, linux-tip-commits, Thomas Gleixner,
	Frederic Weisbecker, Ingo Molnar, Borislav Petkov, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2247 bytes --]

Hi tip-bot2,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[cannot apply to v5.3-rc6 next-20190827]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/tip-bot2-for-Thomas-Gleixner/posix-cpu-timers-Use-common-permission-check-in-posix_cpu_clock_get/20190829-181227
config: nds32-defconfig (attached as .config)
compiler: nds32le-linux-gcc (GCC) 8.1.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=8.1.0 make.cross ARCH=nds32 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   kernel/time/posix-cpu-timers.c: In function 'posix_cpu_clock_get':
   kernel/time/posix-cpu-timers.c:275:8: error: implicit declaration of function 'get_task_for_clock'; did you mean 'get_task_struct'? [-Werror=implicit-function-declaration]
     tsk = get_task_for_clock(clock);
           ^~~~~~~~~~~~~~~~~~
           get_task_struct
>> kernel/time/posix-cpu-timers.c:275:6: warning: assignment to 'struct task_struct *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     tsk = get_task_for_clock(clock);
         ^
   cc1: some warnings being treated as errors

vim +275 kernel/time/posix-cpu-timers.c

   268	
   269	static int posix_cpu_clock_get(const clockid_t clock, struct timespec64 *tp)
   270	{
   271		const clockid_t clkid = CPUCLOCK_WHICH(clock);
   272		struct task_struct *tsk;
   273		u64 t;
   274	
 > 275		tsk = get_task_for_clock(clock);
   276		if (!tsk)
   277			return -EINVAL;
   278	
   279		if (CPUCLOCK_PERTHREAD(clock))
   280			cpu_clock_sample(clkid, tsk, &t);
   281		else
   282			cpu_clock_sample_group(clkid, tsk, &t);
   283		put_task_struct(tsk);
   284	
   285		*tp = ns_to_timespec64(t);
   286		return 0;
   287	}
   288	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 10614 bytes --]

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [tip: timers/core] itimers: Use quick sample function
  2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
@ 2019-08-29 23:47     ` kbuild test robot
  2019-08-30  6:01       ` Thomas Gleixner
  0 siblings, 1 reply; 137+ messages in thread
From: kbuild test robot @ 2019-08-29 23:47 UTC (permalink / raw)
  To: tip-bot2 for Thomas Gleixner
  Cc: kbuild-all, linux-tip-commits, Thomas Gleixner,
	Frederic Weisbecker, Ingo Molnar, Borislav Petkov, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2222 bytes --]

Hi tip-bot2,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[cannot apply to v5.3-rc6 next-20190829]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/tip-bot2-for-Thomas-Gleixner/itimers-Use-quick-sample-function/20190830-063115
config: i386-defconfig (attached as .config)
compiler: gcc-7 (Debian 7.4.0-11) 7.4.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   kernel/time/itimer.c: In function 'get_cpu_itimer':
>> kernel/time/itimer.c:61:3: error: implicit declaration of function 'thread_group_sample_cputime'; did you mean 'thread_group_cputime'? [-Werror=implicit-function-declaration]
      thread_group_sample_cputime(tsk, &cputime);
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~
      thread_group_cputime
   cc1: some warnings being treated as errors

vim +61 kernel/time/itimer.c

    46	
    47	static void get_cpu_itimer(struct task_struct *tsk, unsigned int clock_id,
    48				   struct itimerval *const value)
    49	{
    50		u64 val, interval;
    51		struct cpu_itimer *it = &tsk->signal->it[clock_id];
    52	
    53		spin_lock_irq(&tsk->sighand->siglock);
    54	
    55		val = it->expires;
    56		interval = it->incr;
    57		if (val) {
    58			struct task_cputime cputime;
    59			u64 t;
    60	
  > 61			thread_group_sample_cputime(tsk, &cputime);
    62			if (clock_id == CPUCLOCK_PROF)
    63				t = cputime.utime + cputime.stime;
    64			else
    65				/* CPUCLOCK_VIRT */
    66				t = cputime.utime;
    67	
    68			if (val < t)
    69				/* about to fire */
    70				val = TICK_NSEC;
    71			else
    72				val -= t;
    73		}
    74	
    75		spin_unlock_irq(&tsk->sighand->siglock);
    76	
    77		value->it_value = ns_to_timeval(val);
    78		value->it_interval = ns_to_timeval(interval);
    79	}
    80	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 28074 bytes --]

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [kbuild-all] [tip: timers/core] posix-cpu-timers: Use common permission check in posix_cpu_clock_get()
  2019-08-29 11:21       ` Thomas Gleixner
@ 2019-08-30  1:08         ` Philip Li
  0 siblings, 0 replies; 137+ messages in thread
From: Philip Li @ 2019-08-30  1:08 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: kbuild test robot, linux-tip-commits, Frederic Weisbecker,
	linux-kernel, tip-bot2 for Thomas Gleixner, Borislav Petkov,
	kbuild-all, Ingo Molnar

On Thu, Aug 29, 2019 at 01:21:59PM +0200, Thomas Gleixner wrote:
> On Thu, 29 Aug 2019, kbuild test robot wrote:
> > Thank you for the patch! Yet something to improve:
> > 
> > [auto build test ERROR on linus/master]
> > [cannot apply to v5.3-rc6 next-20190828]
> > [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
> 
> I have no idea what you are testing there.
oops, looks we have missed some info in report. We actually test patches
from mailing list we monitor.
> 
> >    kernel/time/posix-cpu-timers.c: In function 'posix_cpu_clock_get':
> > >> kernel/time/posix-cpu-timers.c:275:8: error: implicit declaration of function 'get_task_for_clock'; did you mean 'get_task_struct'? [-Werror=implicit-function-declaration]
> >      tsk = get_task_for_clock(clock);
> >            ^~~~~~~~~~~~~~~~~~
> >            get_task_struct
> > >> kernel/time/posix-cpu-timers.c:275:6: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
> >      tsk = get_task_for_clock(clock);
> >          ^
> >    cc1: some warnings being treated as errors
> 
> That commit comes _after_ the commit which introduced the function and
> get_task_for_clock() is defined above posix_cpu_clock_get(), so I assume
> you missed to apply the commit on which this depends on.
thanks for info, currently the bot can't figure out the dependency if two
patches are not in one series, or we didn't find the right base repo to
apply, which we will improve continuously.

> 
> Thanks,
> 
> 	tglx
> _______________________________________________
> kbuild-all mailing list
> kbuild-all@lists.01.org
> https://lists.01.org/mailman/listinfo/kbuild-all

^ permalink raw reply	[flat|nested] 137+ messages in thread

* Re: [tip: timers/core] itimers: Use quick sample function
  2019-08-29 23:47     ` kbuild test robot
@ 2019-08-30  6:01       ` Thomas Gleixner
  0 siblings, 0 replies; 137+ messages in thread
From: Thomas Gleixner @ 2019-08-30  6:01 UTC (permalink / raw)
  To: kbuild test robot
  Cc: tip-bot2 for Thomas Gleixner, kbuild-all, linux-tip-commits,
	Frederic Weisbecker, Ingo Molnar, Borislav Petkov, LKML,
	Dave Hansen, Dan Williams

On Fri, 30 Aug 2019, kbuild test robot wrote:

> Thank you for the patch! Yet something to improve:
> 
> [auto build test ERROR on linus/master]
> [cannot apply to v5.3-rc6 next-20190829]

Of course not. Because the patch is already in v5.3-rc6 next-20190829

> [if your patch is applied to the wrong git tree, please drop us a note to
> help improve the system]

I did so several times now and so did Borislav.

Can you please stop applying random patches from tip-bot2 notifications
which are part of a larger series and if applied alone obviously fail
because the prerequisite patches fail?

tip-bot2 mails are notifications that a patch has been merged into a branch
of the tip tree. They contain the information in which branch these patches
are applied so please start testing that branch in the proper order or
ignore tip-bot2 completely.

I really value your service, but recently the usefulness to noise ratio has
degraded massively.

Thanks,

	tglx

^ permalink raw reply	[flat|nested] 137+ messages in thread

end of thread, other threads:[~2019-08-30  6:01 UTC | newest]

Thread overview: 137+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-21 19:08 [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Thomas Gleixner
2019-08-21 19:08 ` [patch V2 01/38] posix-cpu-timers: Provide task validation functions Thomas Gleixner
2019-08-21 22:33   ` Frederic Weisbecker
2019-08-21 23:03     ` Frederic Weisbecker
2019-08-23 15:33       ` Thomas Gleixner
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:08 ` [patch V2 02/38] posix-cpu-timers: Use common permission check in posix_cpu_clock_get() Thomas Gleixner
2019-08-21 23:40   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-29 11:00     ` kbuild test robot
2019-08-29 11:21       ` Thomas Gleixner
2019-08-30  1:08         ` [kbuild-all] " Philip Li
2019-08-29 11:23     ` kbuild test robot
2019-08-21 19:08 ` [patch V2 03/38] posix-cpu-timers: Use common permission check in posix_cpu_timer_create() Thomas Gleixner
2019-08-21 23:49   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:08 ` [patch V2 04/38] posix-cpu-timers: Provide quick sample function for itimer Thomas Gleixner
2019-08-22 12:13   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:08 ` [patch V2 05/38] itimers: Use quick sample function Thomas Gleixner
2019-08-22 12:15   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-29 23:47     ` kbuild test robot
2019-08-30  6:01       ` Thomas Gleixner
2019-08-21 19:08 ` [patch V2 06/38] posix-cpu-timers: Sample directly in timer check Thomas Gleixner
2019-08-22 12:30   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:08 ` [patch V2 07/38] posix-cpu-timers: Rename thread_group_cputimer() and make it static Thomas Gleixner
2019-08-22 12:41   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:08 ` [patch V2 08/38] posix-cpu-timers: Consolidate thread group sample code Thomas Gleixner
2019-08-22 13:49   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:08 ` [patch V2 09/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_set() Thomas Gleixner
2019-08-22 13:58   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:08 ` [patch V2 10/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_get() Thomas Gleixner
2019-08-22 14:07   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:08 ` [patch V2 11/38] posix-cpu-timers: Use clock ID in posix_cpu_timer_rearm() Thomas Gleixner
2019-08-22 14:12   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:08 ` [patch V2 12/38] posix-cpu-timers: Remove pointless return value check Thomas Gleixner
2019-08-22 14:15   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 13/38] posix-cpu-timers: Simplify sample functions Thomas Gleixner
2019-08-22 14:20   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 14/38] posix-cpu-timers: Get rid of pointer indirection Thomas Gleixner
2019-08-22 14:41   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 15/38] posix-cpu-timers: Sample task times once in expiry check Thomas Gleixner
2019-08-22 15:00   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 16/38] posix-cpu-timers: Move prof/virt_ticks into caller Thomas Gleixner
2019-08-22 15:05   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 17/38] posix-cpu-timers: Create a container struct Thomas Gleixner
2019-08-22 15:32   ` Frederic Weisbecker
2019-08-23 15:34     ` Thomas Gleixner
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 19/38] posix-cpu-timers: Move expiry cache into struct posix_cputimers Thomas Gleixner
2019-08-22 16:29   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 20/38] posix-cpu-timers: Provide array based access to expiry cache Thomas Gleixner
2019-08-23 17:33   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 21/38] posix-cpu-timers: Simplify timer queueing Thomas Gleixner
2019-08-23 17:51   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 22/38] posix-cpu-timers: Simplify set_process_cpu_timer() Thomas Gleixner
2019-08-23 18:00   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 23/38] posix-cpu-timers: Switch check_*_timers() to array cache Thomas Gleixner
2019-08-23 18:13   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 24/38] posix-cpu-timers: Remove the odd field rename defines Thomas Gleixner
2019-08-23 18:36   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 25/38] posix-cpu-timers: Provide array based sample functions Thomas Gleixner
2019-08-23 22:08   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 26/38] posix-cpu-timers: Make expiry checks array based Thomas Gleixner
2019-08-23 22:44   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 27/38] posix-cpu-timers: Remove cputime_expires Thomas Gleixner
2019-08-23 22:50   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 28/38] posix-cpu-timers: Restructure expiry array Thomas Gleixner
2019-08-26 16:32   ` Frederic Weisbecker
2019-08-26 18:16     ` Thomas Gleixner
2019-08-26 18:22       ` [patch V3 " Thomas Gleixner
2019-08-26 19:45         ` Frederic Weisbecker
2019-08-28 10:16         ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-26 21:06   ` [patch V2 28/38] " Frederic Weisbecker
2019-08-26 21:46     ` Thomas Gleixner
2019-08-21 19:09 ` [patch V2 29/38] posix-cpu-timers: Switch thread group sampling to array Thomas Gleixner
2019-08-26 21:12   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 30/38] posix-cpu-timers: Respect INFINITY for hard RTTIME limit Thomas Gleixner
2019-08-26 21:19   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 31/38] rlimit: Rewrite non-sensical RLIMIT_CPU comment Thomas Gleixner
2019-08-26 21:41   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 32/38] posix-cpu-timers: Get rid of zero checks Thomas Gleixner
2019-08-26 21:57   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 33/38] posix-cpu-timers: Consolidate timer expiry further Thomas Gleixner
2019-08-26 22:29   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 34/38] posix-cpu-timers: Get rid of 64bit divisions Thomas Gleixner
2019-08-26 22:51   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 35/38] posix-cpu-timers: Remove pointless comparisons Thomas Gleixner
2019-08-26 22:59   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 36/38] posix-cpu-timers: Deduplicate rlimit handling Thomas Gleixner
2019-08-26 23:13   ` Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 37/38] posix-cpu-timers: Move state tracking to struct posix_cputimers Thomas Gleixner
2019-08-26 23:28   ` Frederic Weisbecker
2019-08-26 23:33     ` Thomas Gleixner
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-21 19:09 ` [patch V2 38/38] posix-cpu-timers: Utilize timerqueue for storage Thomas Gleixner
2019-08-27  0:48   ` Frederic Weisbecker
2019-08-27  6:08     ` Thomas Gleixner
2019-08-27 13:17       ` Frederic Weisbecker
2019-08-27 13:46         ` Thomas Gleixner
2019-08-27 19:31           ` [patch V3 " Thomas Gleixner
2019-08-27 22:23             ` Frederic Weisbecker
2019-08-28 10:16             ` [tip: timers/core] " tip-bot2 for Thomas Gleixner
2019-08-22  0:54 ` [patch V2 00/38] posix-cpu-timers: Cleanup and consolidation Christoph Hellwig
2019-08-22  1:02   ` Frederic Weisbecker
2019-08-22  1:02     ` Christoph Hellwig
     [not found] ` <20190821192920.909530418@linutronix.de>
2019-08-22 16:06   ` [patch V2 18/38] sched: Move struct task_cputime to types.h Frederic Weisbecker
2019-08-28 10:16   ` [tip: timers/core] " tip-bot2 for Thomas Gleixner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).