[12/45] posix-cpu-timers: Simplify posix_cpu_timer_set()

Message ID 20230606142031.705286109@linutronix.de
State New
Headers
Series posix-timers: Cure inconsistencies and the SIG_IGN mess |

Commit Message

Thomas Gleixner June 6, 2023, 2:37 p.m. UTC
  Avoid the late sighand lock/unlock dance when a timer is not armed to
enforce reevaluation of the timer base so that the process wide CPU timer
sampling can be disabled.

Do it right at the point where the arming decision is made which already
has sighand locked.

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

Comments

Frederic Weisbecker June 27, 2023, 10:51 a.m. UTC | #1
On Tue, Jun 06, 2023 at 04:37:37PM +0200, Thomas Gleixner wrote:
> Avoid the late sighand lock/unlock dance when a timer is not armed to
> enforce reevaluation of the timer base so that the process wide CPU timer
> sampling can be disabled.
> 
> Do it right at the point where the arming decision is made which already
> has sighand locked.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
>  kernel/time/posix-cpu-timers.c |   38 +++++++++++++-------------------------
>  1 file changed, 13 insertions(+), 25 deletions(-)
> 
> --- a/kernel/time/posix-cpu-timers.c
> +++ b/kernel/time/posix-cpu-timers.c
> @@ -720,10 +720,14 @@ static int posix_cpu_timer_set(struct k_
>  	/*
>  	 * Arm the timer if it is not disabled, the new expiry value has
>  	 * not yet expired and the timer requires signal delivery.
> -	 * SIGEV_NONE timers are never armed.
> +	 * SIGEV_NONE timers are never armed. In case the timer is not
> +	 * armed, enforce the reevaluation of the timer base so that the
> +	 * process wide cputime counter can be disabled eventually.
>  	 */
>  	if (!sigev_none && new_expires && now < new_expires)
>  		arm_timer(timer, p);
> +	else
> +		trigger_base_recalc_expires(timer, p);

We don't need a recalc if sigev_none, right?

Thanks.

>  
>  	unlock_task_sighand(p, &flags);
>  	/*
  
Thomas Gleixner June 29, 2023, 6:43 p.m. UTC | #2
On Tue, Jun 27 2023 at 12:51, Frederic Weisbecker wrote:
> On Tue, Jun 06, 2023 at 04:37:37PM +0200, Thomas Gleixner wrote:
>> Avoid the late sighand lock/unlock dance when a timer is not armed to
>> enforce reevaluation of the timer base so that the process wide CPU timer
>> sampling can be disabled.
>> +	 * SIGEV_NONE timers are never armed. In case the timer is not
>> +	 * armed, enforce the reevaluation of the timer base so that the
>> +	 * process wide cputime counter can be disabled eventually.
>>  	 */
>>  	if (!sigev_none && new_expires && now < new_expires)
>>  		arm_timer(timer, p);
>> +	else
>> +		trigger_base_recalc_expires(timer, p);
>
> We don't need a recalc if sigev_none, right?

Correct.
  

Patch

--- a/kernel/time/posix-cpu-timers.c
+++ b/kernel/time/posix-cpu-timers.c
@@ -720,10 +720,14 @@  static int posix_cpu_timer_set(struct k_
 	/*
 	 * Arm the timer if it is not disabled, the new expiry value has
 	 * not yet expired and the timer requires signal delivery.
-	 * SIGEV_NONE timers are never armed.
+	 * SIGEV_NONE timers are never armed. In case the timer is not
+	 * armed, enforce the reevaluation of the timer base so that the
+	 * process wide cputime counter can be disabled eventually.
 	 */
 	if (!sigev_none && new_expires && now < new_expires)
 		arm_timer(timer, p);
+	else
+		trigger_base_recalc_expires(timer, p);
 
 	unlock_task_sighand(p, &flags);
 	/*
@@ -742,30 +746,14 @@  static int posix_cpu_timer_set(struct k_
 	timer->it_overrun_last = 0;
 	timer->it_overrun = -1;
 
-	if (!sigev_none && now >= new_expires) {
-		if (new_expires != 0) {
-			/*
-			 * The designated time already passed, so we notify
-			 * immediately, even if the thread never runs to
-			 * accumulate more time on this clock.
-			 */
-			cpu_timer_fire(timer);
-		}
-
-		/*
-		 * Make sure we don't keep around the process wide cputime
-		 * counter or the tick dependency if they are not necessary.
-		 */
-		sighand = lock_task_sighand(p, &flags);
-		if (!sighand)
-			goto out;
-
-		if (!cpu_timer_queued(ctmr))
-			trigger_base_recalc_expires(timer, p);
-
-		unlock_task_sighand(p, &flags);
-	}
- out:
+	/*
+	 * If the new expiry time was already in the past the timer was not
+	 * queued. Fire it immediately even if the thread never runs to
+	 * accumulate more time on this clock.
+	 */
+	if (!sigev_none && new_expires && now >= new_expires)
+		cpu_timer_fire(timer);
+out:
 	rcu_read_unlock();
 	if (old)
 		old->it_interval = ns_to_timespec64(old_incr);