linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
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

  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).