From: Daniel Church <dchurch@andplus.com>
To: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org, libc-alpha@sourceware.org,
Daniel Church <dchurch@andplus.com>
Subject: [PATCH v2 1/2] posix-timers: Prevents overrun counter overflow
Date: Sat, 24 Jan 2015 12:48:56 -0500 [thread overview]
Message-ID: <1422121737-3686-2-git-send-email-dchurch@andplus.com> (raw)
In-Reply-To: <1422121737-3686-1-git-send-email-dchurch@andplus.com>
If a timer overruns too many times before a call to timer_getoverrun the
overrun count can overflow and go negative. Adds delaytimer_max value
to cap overrun count and prevent overflow.
Signed-off-by: Daniel Church <dchurch@andplus.com>
---
include/linux/posix-timers.h | 3 +++
kernel/time/posix-timers.c | 45 ++++++++++++++++++++++++++++++++++++--------
2 files changed, 40 insertions(+), 8 deletions(-)
diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h
index 907f3fd..dc8a1e7 100644
--- a/include/linux/posix-timers.h
+++ b/include/linux/posix-timers.h
@@ -138,4 +138,7 @@ long clock_nanosleep_restart(struct restart_block *restart_block);
void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new);
+#define DELAYTIMER_MAX_DEFAULT 1000000
+extern int delaytimer_max;
+
#endif
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index 31ea01f..010344e 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -68,6 +68,8 @@ static struct kmem_cache *posix_timers_cache;
static DEFINE_HASHTABLE(posix_timers_hashtable, 9);
static DEFINE_SPINLOCK(hash_lock);
+int delaytimer_max = DELAYTIMER_MAX_DEFAULT;
+
/*
* we assume that the new SIGEV_THREAD_ID shares no bits with the other
* SIGEV values. Here we put out an error if this assumption fails.
@@ -202,6 +204,24 @@ static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
spin_unlock_irqrestore(&timr->it_lock, flags);
}
+/*
+ * Updates a timer's overrun count while capping it to delaytimer_max
+ */
+static void posix_timer_update_overrun_count(struct k_itimer *timer,
+ unsigned int overruns)
+{
+ const bool newOverrunsAboveMax = overruns >= delaytimer_max;
+ const bool totalOverrunsAboveMax =
+ timer->it_overrun >= 0 &&
+ timer->it_overrun >= delaytimer_max - overruns;
+
+ if (newOverrunsAboveMax || totalOverrunsAboveMax) {
+ timer->it_overrun = delaytimer_max;
+ } else {
+ timer->it_overrun += overruns;
+ }
+}
+
/* Get clock_realtime */
static int posix_clock_realtime_get(clockid_t which_clock, struct timespec *tp)
{
@@ -350,14 +370,17 @@ __initcall(init_posix_timers);
static void schedule_next_timer(struct k_itimer *timr)
{
+ unsigned int overruns;
struct hrtimer *timer = &timr->it.real.timer;
if (timr->it.real.interval.tv64 == 0)
return;
- timr->it_overrun += (unsigned int) hrtimer_forward(timer,
- timer->base->get_time(),
- timr->it.real.interval);
+ overruns = (unsigned int) hrtimer_forward(timer,
+ timer->base->get_time(),
+ timr->it.real.interval);
+
+ posix_timer_update_overrun_count(timr, overruns);
timr->it_overrun_last = timr->it_overrun;
timr->it_overrun = -1;
@@ -436,6 +459,7 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
{
struct k_itimer *timr;
unsigned long flags;
+ unsigned int overruns;
int si_private = 0;
enum hrtimer_restart ret = HRTIMER_NORESTART;
@@ -484,9 +508,10 @@ static enum hrtimer_restart posix_timer_fn(struct hrtimer *timer)
now = ktime_add(now, kj);
}
#endif
- timr->it_overrun += (unsigned int)
- hrtimer_forward(timer, now,
- timr->it.real.interval);
+ overruns = (unsigned int) hrtimer_forward(timer, now,
+ timr->it.real.interval);
+ posix_timer_update_overrun_count(timr, overruns);
+
ret = HRTIMER_RESTART;
++timr->it_requeue_pending;
}
@@ -729,6 +754,7 @@ static void
common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
{
ktime_t now, remaining, iv;
+ unsigned int overruns;
struct hrtimer *timer = &timr->it.real.timer;
memset(cur_setting, 0, sizeof(struct itimerspec));
@@ -750,8 +776,10 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
* expiry is > now.
*/
if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING ||
- (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
- timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv);
+ (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) {
+ overruns = (unsigned int) hrtimer_forward(timer, now, iv);
+ posix_timer_update_overrun_count(timr, overruns);
+ }
remaining = ktime_sub(hrtimer_get_expires(timer), now);
/* Return 0 only, when the timer is expired and not pending */
@@ -1122,3 +1150,4 @@ long clock_nanosleep_restart(struct restart_block *restart_block)
return kc->nsleep_restart(restart_block);
}
+
--
1.9.1
next prev parent reply other threads:[~2015-01-24 17:49 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <[PATCH 0/2] posix-timers: Prevents overrun counter overflow, adds DELAYTIMER_MAX>
2015-01-24 17:48 ` [PATCH v2 0/2] posix-timers: Prevents overrun counter overflow, adds DELAYTIMER_MAX Daniel Church
2015-01-24 17:48 ` Daniel Church [this message]
2015-01-24 18:17 ` [PATCH v2 1/2] posix-timers: Prevents overrun counter overflow Richard Cochran
2015-01-24 19:14 ` Thomas Gleixner
2015-01-24 19:37 ` Carlos O'Donell
2015-01-24 17:48 ` [PATCH v2 2/2] posix-timers: Exposes DELAYTIMER_MAX constant used to govern overruns Daniel Church
2015-01-24 19:20 ` Thomas Gleixner
2015-01-24 19:36 ` Carlos O'Donell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1422121737-3686-2-git-send-email-dchurch@andplus.com \
--to=dchurch@andplus.com \
--cc=libc-alpha@sourceware.org \
--cc=linux-kernel@vger.kernel.org \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®