Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752842AbdFLTRc (ORCPT ); Mon, 12 Jun 2017 15:17:32 -0400 Received: from terminus.zytor.com ([65.50.211.136]:39063 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752086AbdFLTRb (ORCPT ); Mon, 12 Jun 2017 15:17:31 -0400 Date: Mon, 12 Jun 2017 12:13:49 -0700 From: tip-bot for Thomas Gleixner Message-ID: Cc: avagin@virtuozzo.com, tglx@linutronix.de, john.stultz@linaro.org, gorcunov@openvz.org, peterz@infradead.org, hpa@zytor.com, mingo@kernel.org, linux-kernel@vger.kernel.org Reply-To: gorcunov@openvz.org, avagin@virtuozzo.com, john.stultz@linaro.org, tglx@linutronix.de, peterz@infradead.org, mingo@kernel.org, hpa@zytor.com, linux-kernel@vger.kernel.org In-Reply-To: <20170609201156.GB21491@outlook.office365.com> References: <20170609201156.GB21491@outlook.office365.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:timers/core] posix-timers: Handle relative posix-timers correctly Git-Commit-ID: 67edab48caeb75d412706f4b9d3107afd1e07623 X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3119 Lines: 69 Commit-ID: 67edab48caeb75d412706f4b9d3107afd1e07623 Gitweb: http://git.kernel.org/tip/67edab48caeb75d412706f4b9d3107afd1e07623 Author: Thomas Gleixner AuthorDate: Mon, 12 Jun 2017 19:39:49 +0200 Committer: Thomas Gleixner CommitDate: Mon, 12 Jun 2017 21:07:41 +0200 posix-timers: Handle relative posix-timers correctly The recent rework of the posix timer internals broke the magic posix mechanism, which requires that relative timers are not affected by modifications of the underlying clock. That means relative CLOCK_REALTIME timers cannot use CLOCK_REALTIME, because that can be set and adjusted. The underlying hrtimer switches the clock for these timers to CLOCK_MONOTONIC. That still works, but reading the remaining time of such a timer has been broken in the rework. The old code used the hrtimer internals directly and avoided the posix clock callbacks. Now common_timer_get() uses the underlying kclock->timer_get() callback, which is still CLOCK_REALTIME based. So the remaining time of such a timer is calculated against the wrong time base. Handle it by switching the k_itimer->kclock pointer according to the resulting hrtimer mode. k_itimer->it_clock still contains CLOCK_REALTIME because the timer might be set with ABSTIME later and then it needs to switch back to the realtime posix clock implementation. Fixes: eae1c4ae275f ("posix-timers: Make use of cancel/arm callbacks") Reported-by: Andrei Vagin Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: John Stultz Cc: Cyrill Gorcunov Link: http://lkml.kernel.org/r/20170609201156.GB21491@outlook.office365.com --- kernel/time/posix-timers.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 88517dc..58c0f60 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c @@ -72,6 +72,7 @@ static DEFINE_SPINLOCK(hash_lock); static const struct k_clock * const posix_clocks[]; static const struct k_clock *clockid_to_kclock(const clockid_t id); +static const struct k_clock clock_realtime, clock_monotonic; /* * we assume that the new SIGEV_THREAD_ID shares no bits with the other @@ -750,6 +751,18 @@ static void common_hrtimer_arm(struct k_itimer *timr, ktime_t expires, enum hrtimer_mode mode; mode = absolute ? HRTIMER_MODE_ABS : HRTIMER_MODE_REL; + /* + * Posix magic: Relative CLOCK_REALTIME timers are not affected by + * clock modifications, so they become CLOCK_MONOTONIC based under the + * hood. See hrtimer_init(). Update timr->kclock, so the generic + * functions which use timr->kclock->clock_get() work. + * + * Note: it_clock stays unmodified, because the next timer_set() might + * use ABSTIME, so it needs to switch back. + */ + if (timr->it_clock == CLOCK_REALTIME) + timr->kclock = absolute ? &clock_realtime : &clock_monotonic; + hrtimer_init(&timr->it.real.timer, timr->it_clock, mode); timr->it.real.timer.function = posix_timer_fn;