From: Christoph Hellwig <hch@lst.de>
To: Thomas Gleixner <tglx@linutronix.de>
Cc: Mark Gross <mark.gross@intel.com>, Tejun Heo <tj@kernel.org>,
linuxppc-dev@lists.ozlabs.org, linux-s390@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH 2/9] timers: provide a "modern" variant of timers
Date: Tue, 16 May 2017 13:48:05 +0200 [thread overview]
Message-ID: <20170516114812.10660-3-hch@lst.de> (raw)
In-Reply-To: <20170516114812.10660-1-hch@lst.de>
The new callback gets a pointer to the timer_list itself, which can
then be used to get the containing structure using container_of
instead of casting from and to unsigned long all the time.
The setup helpers take a flags argument instead of needing countless
variants.
Note: this further reduces space for the cpumask. By the time we'll
need the additional cpumask space getting rid of the old-style timers
will hopefully be finished.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/linux/timer.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++--
kernel/time/timer.c | 24 ++++++++++++++----------
2 files changed, 62 insertions(+), 12 deletions(-)
diff --git a/include/linux/timer.h b/include/linux/timer.h
index e6789b8757d5..87afe52c8349 100644
--- a/include/linux/timer.h
+++ b/include/linux/timer.h
@@ -16,7 +16,10 @@ struct timer_list {
*/
struct hlist_node entry;
unsigned long expires;
- void (*function)(unsigned long);
+ union {
+ void (*func)(struct timer_list *timer);
+ void (*function)(unsigned long);
+ };
unsigned long data;
u32 flags;
@@ -52,7 +55,8 @@ struct timer_list {
* workqueue locking issues. It's not meant for executing random crap
* with interrupts disabled. Abuse is monitored!
*/
-#define TIMER_CPUMASK 0x0003FFFF
+#define TIMER_CPUMASK 0x0001FFFF
+#define TIMER_MODERN 0x00020000
#define TIMER_MIGRATING 0x00040000
#define TIMER_BASEMASK (TIMER_CPUMASK | TIMER_MIGRATING)
#define TIMER_DEFERRABLE 0x00080000
@@ -63,6 +67,22 @@ struct timer_list {
#define TIMER_TRACE_FLAGMASK (TIMER_MIGRATING | TIMER_DEFERRABLE | TIMER_PINNED | TIMER_IRQSAFE)
+#define INIT_TIMER(_func, _expires, _flags) \
+{ \
+ .entry = { .next = TIMER_ENTRY_STATIC }, \
+ .func = (_func), \
+ .expires = (_expires), \
+ .flags = TIMER_MODERN | (_flags), \
+ __TIMER_LOCKDEP_MAP_INITIALIZER(__FILE__ ":" __stringify(__LINE__)) \
+}
+
+#define DECLARE_TIMER(_name, _func, _expires, _flags) \
+ struct timer_list _name = INIT_TIMER(_func, _expires, _flags)
+
+/*
+ * Don't use the macros below, use DECLARE_TIMER and INIT_TIMER with their
+ * improved callback signature above.
+ */
#define __TIMER_INITIALIZER(_function, _expires, _data, _flags) { \
.entry = { .next = TIMER_ENTRY_STATIC }, \
.function = (_function), \
@@ -126,6 +146,32 @@ static inline void init_timer_on_stack_key(struct timer_list *timer,
init_timer_on_stack_key((_timer), (_flags), NULL, NULL)
#endif
+/**
+ * prepare_timer - initialize a timer before first use
+ * @timer: timer structure to prepare
+ * @func: callback to be called when the timer expires
+ * @flags %TIMER_* flags that control timer behavior
+ *
+ * This function initializes a timer_list structure so that it can
+ * be used (by calling add_timer() or mod_timer()).
+ */
+static inline void prepare_timer(struct timer_list *timer,
+ void (*func)(struct timer_list *timer), u32 flags)
+{
+ __init_timer(timer, TIMER_MODERN | flags);
+ timer->func = func;
+}
+
+static inline void prepare_timer_on_stack(struct timer_list *timer,
+ void (*func)(struct timer_list *timer), u32 flags)
+{
+ __init_timer_on_stack(timer, TIMER_MODERN | flags);
+ timer->func = func;
+}
+
+/*
+ * Don't use - use prepare_timer above for new code instead.
+ */
#define init_timer(timer) \
__init_timer((timer), 0)
#define init_timer_pinned(timer) \
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index c7978fcdbbea..48d8450cfa5f 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -579,7 +579,7 @@ static struct debug_obj_descr timer_debug_descr;
static void *timer_debug_hint(void *addr)
{
- return ((struct timer_list *) addr)->function;
+ return ((struct timer_list *) addr)->func;
}
static bool timer_is_static_object(void *addr)
@@ -930,7 +930,7 @@ __mod_timer(struct timer_list *timer, unsigned long expires, bool pending_only)
unsigned long clk = 0, flags;
int ret = 0;
- BUG_ON(!timer->function);
+ BUG_ON(!timer->func && !timer->function);
/*
* This is a common optimization triggered by the networking code - if
@@ -1064,12 +1064,12 @@ EXPORT_SYMBOL(mod_timer);
* add_timer - start a timer
* @timer: the timer to be added
*
- * The kernel will do a ->function(->data) callback from the
- * timer interrupt at the ->expires point in the future. The
- * current time is 'jiffies'.
+ * The kernel will do a ->func (or ->function(->data) for legacy timers)
+ * callback from the timer interrupt at the ->expires point in the future.
+ * The current time is 'jiffies'.
*
- * The timer's ->expires, ->function (and if the handler uses it, ->data)
- * fields must be set prior calling this function.
+ * The timer's ->expires, ->func / ->function (and if the handler uses it,
+ * ->data) fields must be set prior calling this function.
*
* Timers with an ->expires field in the past will be executed in the next
* timer tick.
@@ -1093,7 +1093,8 @@ void add_timer_on(struct timer_list *timer, int cpu)
struct timer_base *new_base, *base;
unsigned long flags;
- BUG_ON(timer_pending(timer) || !timer->function);
+ BUG_ON(timer_pending(timer));
+ BUG_ON(!timer->func && !timer->function);
new_base = get_timer_cpu_base(timer->flags, cpu);
@@ -1264,14 +1265,17 @@ static void call_timer_fn(struct timer_list *timer)
lock_map_acquire(&lockdep_map);
trace_timer_expire_entry(timer);
- timer->function(timer->data);
+ if (timer->flags & TIMER_MODERN)
+ timer->func(timer);
+ else
+ timer->function(timer->data);
trace_timer_expire_exit(timer);
lock_map_release(&lockdep_map);
if (count != preempt_count()) {
WARN_ONCE(1, "timer: %pF preempt leak: %08x -> %08x\n",
- timer->function, count, preempt_count());
+ timer->func, count, preempt_count());
/*
* Restore the preempt count. That gives us a decent
* chance to survive and extract information. If the
--
2.11.0
next prev parent reply other threads:[~2017-05-16 11:48 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-05-16 11:48 RFC: better timer interface Christoph Hellwig
2017-05-16 11:48 ` [PATCH 1/9] timers: remove the fn and data arguments to call_timer_fn Christoph Hellwig
2017-05-16 11:48 ` Christoph Hellwig [this message]
2017-05-16 19:29 ` [PATCH 2/9] timers: provide a "modern" variant of timers Randy Dunlap
2017-05-16 20:03 ` Arnd Bergmann
2017-05-18 8:24 ` Christoph Hellwig
2017-05-18 8:41 ` Christoph Hellwig
2017-05-18 8:57 ` Arnd Bergmann
2017-05-21 7:00 ` Christoph Hellwig
2017-05-21 12:29 ` Arnd Bergmann
2017-05-21 17:57 ` Thomas Gleixner
2017-05-21 18:23 ` Al Viro
2017-05-19 10:48 ` David Laight
2017-05-21 6:57 ` 'Christoph Hellwig'
2017-05-16 11:48 ` [PATCH 3/9] kthread: remove unused macros Christoph Hellwig
2017-05-17 12:09 ` Petr Mladek
2017-05-18 8:22 ` Christoph Hellwig
2017-05-16 11:48 ` [PATCH 4/9] workqueue: switch to modern timers Christoph Hellwig
2017-05-16 11:48 ` [PATCH 5/9] powerpc/numa: switch topology_timer to modern timer Christoph Hellwig
2017-05-16 11:48 ` [PATCH 6/9] s390: switch topology_timer to a " Christoph Hellwig
2017-05-16 11:48 ` [PATCH 7/9] s390: switch lgr timer " Christoph Hellwig
2017-05-16 11:48 ` [PATCH 8/9] tlclk: switch switchover_timer " Christoph Hellwig
2017-05-16 11:48 ` [PATCH 9/9] timers: remove old timer initialization macros Christoph Hellwig
2017-05-16 19:43 ` Arnd Bergmann
2017-05-18 8:25 ` Christoph Hellwig
2017-05-16 15:45 ` RFC: better timer interface Arnd Bergmann
2017-05-16 15:51 ` Christoph Hellwig
2017-05-16 20:26 ` Arnd Bergmann
2017-05-18 8:27 ` Christoph Hellwig
2017-05-21 17:13 ` Thomas Gleixner
2017-05-21 18:14 ` Thomas Gleixner
2017-05-22 11:26 ` Arnd Bergmann
2017-05-22 19:24 ` Thomas Gleixner
2017-05-23 11:36 ` David Laight
2017-05-23 11:58 ` Thomas Gleixner
2017-05-23 12:51 ` David Laight
2017-05-23 13:02 ` Thomas Gleixner
2017-05-22 13:32 ` Arnd Bergmann
2017-05-22 19:14 ` Thomas Gleixner
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=20170516114812.10660-3-hch@lst.de \
--to=hch@lst.de \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-s390@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=mark.gross@intel.com \
--cc=tglx@linutronix.de \
--cc=tj@kernel.org \
/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;
as well as URLs for NNTP newsgroup(s).