From: Ingo Molnar <mingo@elte.hu>
To: Arjan van de Ven <arjan@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>,
linux-kernel@vger.kernel.org, alan@linux.intel.com
Subject: Re: [patch] timer: Add a mod_timer_msec() API function
Date: Mon, 23 Nov 2009 09:26:48 +0100 [thread overview]
Message-ID: <20091123082648.GB13186@elte.hu> (raw)
In-Reply-To: <20091122154111.197e1a8a@infradead.org>
* Arjan van de Ven <arjan@infradead.org> wrote:
> Subject: timer: add a mod_timer_msec() API function
> From: Arjan van de Ven <arjan@linux.intel.com>
>
> There is a common pattern in the kernel, where the caller wants
> to set a timer a specified number of milliseconds into the future.
>
> The typical solution then ends up
>
> mod_timer(&timer, jiffies + msecs_to_jiffies(msec_amount));
>
> or
>
> mod_timer(&timer, jiffies + HZ/some_value);
>
> This patch aims to simplify this pattern for the caller, and at
> the same time, make for a more power-friendly API.
>
> The new pattern for identical behavior will be
>
> mod_timer_msec(&timer, msec_amount, 0);
>
> while
>
> mod_timer_msec(&time, msec_amount, 100);
>
> would give the kernel 100 milliseconds of slack to find a power
> friendly time to group timers into one CPU wakeup.
>
> A patch to convert a number of users, to show how the API is used,
> will be sent as reply to this email.
the basic API idea looks good to me. A few comments:
> Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
>
> diff --git a/include/linux/timer.h b/include/linux/timer.h
> index a2d1eb6..006d4da 100644
> --- a/include/linux/timer.h
> +++ b/include/linux/timer.h
> @@ -162,6 +162,7 @@ static inline int timer_pending(const struct timer_list * timer)
> extern void add_timer_on(struct timer_list *timer, int cpu);
> extern int del_timer(struct timer_list * timer);
> extern int mod_timer(struct timer_list *timer, unsigned long expires);
> +extern int mod_timer_msec(struct timer_list *timer, unsigned long delay_ms, unsigned long slack_ms);
> extern int mod_timer_pending(struct timer_list *timer, unsigned long expires);
> extern int mod_timer_pinned(struct timer_list *timer, unsigned long expires);
>
> diff --git a/kernel/timer.c b/kernel/timer.c
> index 5db5a8d..c9d5cbf 100644
> --- a/kernel/timer.c
> +++ b/kernel/timer.c
> @@ -751,6 +751,47 @@ int mod_timer(struct timer_list *timer, unsigned long expires)
> EXPORT_SYMBOL(mod_timer);
>
> /**
> + * mod_timer_msec - modify a timer's timeout, using relative milliseconds
> + * @timer: the timer to be modified
> + * @delay_ms: the desired minimum delay in milliseconds
> + * @slack_ms: the amount of slack is ok in firing the timer
> + *
> + * Changes the timeout of a timer similar to mod_timer().
> + *
> + * mod_timer_msec() takes relative milliseconds rather than absolute
> + * jiffies as argument and also takes a "slack" amount, which is
> + * an explicit permission to treat the time of the timer as less
> + * precise in order to allow grouping of timers.
> + *
> + * The function returns whether it has modified a pending timer or not.
> + * (ie. mod_timer() of an inactive timer returns 0, mod_timer() of an
> + * active timer returns 1.)
> + */
> +int mod_timer_msec(struct timer_list *timer, unsigned long delay_ms, unsigned long slack_ms)
> +{
> + unsigned long next_jiffies, max_jiffies;
> + unsigned long rounded_jiffies;
> +
> + next_jiffies = jiffies + msecs_to_jiffies(delay_ms);
> + max_jiffies = jiffies + msecs_to_jiffies(delay_ms + slack_ms);
> + rounded_jiffies = round_jiffies(next_jiffies);
> +
> + /* check if rounding up next_jiffies is within the max */
> + if (rounded_jiffies <= max_jiffies && rounded_jiffies >= next_jiffies) {
> + next_jiffies = rounded_jiffies;
Is this comparison jiffies wraparound safe?
> + } else {
> + /* regular rounding failed; try a rounding to multiple-of-16 */
> + rounded_jiffies = (next_jiffies + 15) & ~0xF;
> + if (rounded_jiffies <= max_jiffies)
> + next_jiffies = rounded_jiffies;
> + }
> +
> + return mod_timer(timer, next_jiffies);
> +}
> +EXPORT_SYMBOL_GPL(mod_timer_msec);
This code first rounds to 1 second - and if that doesnt fall within the
slack window it rounds to the (rather aribtrary) rounding of 16 jiffies.
I'd suggest to use up the slack to its maximum, by rounding up modulo
the largest power-of-2 value that still fits into the slack.
So if slack is 30, the rounding is 16. If slack is 5, the rounding is 4,
etc.
Ingo
next prev parent reply other threads:[~2009-11-23 8:27 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-11-22 23:41 Arjan van de Ven
2009-11-22 23:42 ` Arjan van de Ven
2009-11-23 8:26 ` Ingo Molnar [this message]
2009-11-23 14:51 ` Arjan van de Ven
2009-11-23 17:19 ` Thomas Gleixner
2009-11-24 10:14 ` Alan Cox
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=20091123082648.GB13186@elte.hu \
--to=mingo@elte.hu \
--cc=alan@linux.intel.com \
--cc=arjan@infradead.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®