From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9C4F93ACA6B for ; Tue, 24 Feb 2026 16:39:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771951146; cv=none; b=rj0XXL3GZpvnynDS2wvYngZfLm6SuuQF4sT0Kekk7ZjwqrC9emYv/DdvjlrZ7U8AqECSXYBVufLU/PtKzaiOyWzqKDtzUvbzkpiM6JXbS460rQDpQSQCNDxrh+cgqShOUcE0lV9A8x8bQtg9ux6t+shAhYZWFfq1UwB0Kzgi4MY= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1771951146; c=relaxed/simple; bh=IlOwTicNdJJjJl9a9mKJb5nsgfJlG9h1i8fnUx6Rknk=; h=Date:Message-ID:From:To:Cc:Subject:References:MIME-Version: Content-Type; b=cRDQWXLvKwt6rFK/QHGrg4Qq7xCp1Qj29bn0FcrTetdL/k17hlxOQk0MksUXHvyefkW1tb0u0xPoM0Btk9F4edOWHE2gK5weWde2czMwGcEoHwivQxiHOmdwillZ4R/1tGCHvQ4H4GaEfZdRwF5rimHZOg63VlkDF31hzJ0SCFI= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=gaS1nkhO; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="gaS1nkhO" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 651ECC116D0; Tue, 24 Feb 2026 16:39:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1771951146; bh=IlOwTicNdJJjJl9a9mKJb5nsgfJlG9h1i8fnUx6Rknk=; h=Date:From:To:Cc:Subject:References:From; b=gaS1nkhO/vbk7IFa1tIUjUaFw1pPjnpe6eE+g96srCq/FncErG42Q3YRBUv9HjUTu 1kYNOECWkfAqafuT+uj8e+R0OnNRQdUqM5aor9kxIiJUoHLycRD8Iq+BIHkoG37o8y wEf4uEnpyRvXF5arcmVa4ZQ9KndVVaRq1UNFSO4A00sNfQApYrIw7xXzKuZWbHxdLU anXKWeM3xehnObVKicDlHSdLIw6jbwBj7uAcqcs4RXDPBoBfFaGvJuEBMybL2prrPw BxNSHKmp9oaLylJXUu+iIeWDwgMEb+KHgcUEBLDPmoHZc3ZpINkEHXaHJewK/uFe0I n5Ij+3Wdz2LEA== Date: Tue, 24 Feb 2026 17:39:02 +0100 Message-ID: <20260224163431.873359816@kernel.org> User-Agent: quilt/0.68 From: Thomas Gleixner To: LKML Cc: Anna-Maria Behnsen , John Stultz , Stephen Boyd , Daniel Lezcano , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Valentin Schneider , x86@kernel.org, Peter Zijlstra , Frederic Weisbecker , Eric Dumazet Subject: [patch 47/48] hrtimer: Try to modify timers in place References: <20260224163022.795809588@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 When modifying the expiry of a armed timer it is first dequeued, then the expiry value is updated and then it is queued again. This can be avoided when the new expiry value is within the range of the previous and the next timer as that does not change the position in the RB tree. The linked timerqueue allows to peak ahead to the neighbours and check whether the new expiry time is within the range of the previous and next timer. If so just modify the timer in place and spare the enqueue and requeue effort, which might end up rotating the RB tree twice for nothing. This speeds up the handling of frequently rearmed hrtimers, like the hrtick scheduler timer significantly. Signed-off-by: Thomas Gleixner node); + struct timerqueue_linked_node *prev = timerqueue_linked_prev(&timer->node); + + /* If the new expiry goes behind the next timer, requeue is required */ + if (next && expires > next->expires) + return false; + + /* If this is the first timer, update in place */ + if (!prev) + return true; + + /* Update in place when it does not go ahead of the previous one */ + return expires >= prev->expires; +} + static inline bool remove_and_enqueue_same_base(struct hrtimer *timer, struct hrtimer_clock_base *base, const enum hrtimer_mode mode, ktime_t expires, u64 delta_ns) @@ -1211,8 +1236,18 @@ remove_and_enqueue_same_base(struct hrti /* Remove it from the timer queue if active */ if (timer->is_queued) { - debug_hrtimer_deactivate(timer); was_first = !timerqueue_linked_prev(&timer->node); + + /* Try to update in place to avoid the de/enqueue dance */ + if (hrtimer_can_update_in_place(timer, base, expires)) { + hrtimer_set_expires_range_ns(timer, expires, delta_ns); + trace_hrtimer_start(timer, mode, true); + if (was_first) + base->expires_next = expires; + return was_first; + } + + debug_hrtimer_deactivate(timer); timerqueue_linked_del(&base->active, &timer->node); }