All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] relay: Use irq_work instead of plain timer for deferred wakeup
@ 2016-09-02  9:05 akash.goel
  2016-09-02 10:49 ` kbuild test robot
  0 siblings, 1 reply; 3+ messages in thread
From: akash.goel @ 2016-09-02  9:05 UTC (permalink / raw)
  To: akpm, linux-kernel
  Cc: Peter Zijlstra, Tom Zanussi, Chris Wilson, Tvrtko Ursulin, Akash Goel

From: Peter Zijlstra <peterz@infradead.org>

Relay avoids calling wake_up_interruptible() for doing the wakeup of
readers/consumers, waiting for the generation of new data, from the
context of a process which produced the data. This is apparently done
to prevent the possibility of a deadlock in case Scheduler itself is
is generating data for the relay, after acquiring rq->lock.

The following patch used a timer (to be scheduled at next jiffy), for
delegating the wakeup to another context.
	commit 7c9cb38302e78d24e37f7d8a2ea7eed4ae5f2fa7
	Author: Tom Zanussi <zanussi@comcast.net>
	Date:   Wed May 9 02:34:01 2007 -0700

	relay: use plain timer instead of delayed work

	relay doesn't need to use schedule_delayed_work() for waking readers
	when a simple timer will do.

Scheduling a plain timer, at next jiffies boundary, to do the wakeup causes
a significant wakeup latency for the Userspace client, which makes relay less
suitable for the high-frequency low-payload use cases where the data gets
generated at a very high rate, like multiple sub buffers getting filled
within a milli second.
Moreover the timer is re-scheduled on every newly produced sub buffer so the
timer keeps getting pushed out if sub buffers are filled in a very quick
succession (less than a jiffy gap between filling of 2 sub buffers).
As a result relay runs out of sub buffers to store the new data.

By using irq_work it is ensured that wakeup of userspace client, blocked in
the poll call, is done at earliest (through self IPI or next timer tick)
enabling him to always consume the data in time.

Cc: Tom Zanussi <tzanussi@gmail.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Akash Goel <akash.goel@intel.com>
---
 include/linux/relay.h |  3 ++-
 kernel/relay.c        | 20 +++++++++++---------
 2 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/include/linux/relay.h b/include/linux/relay.h
index eb295e3..54960a5 100644
--- a/include/linux/relay.h
+++ b/include/linux/relay.h
@@ -20,6 +20,7 @@
 #include <linux/poll.h>
 #include <linux/kref.h>
 #include <linux/percpu.h>
+#include <linux/irq_work.h>
 
 /*
  * Tracks changes to rchan/rchan_buf structs
@@ -38,7 +39,7 @@ struct rchan_buf
 	size_t subbufs_consumed;	/* count of sub-buffers consumed */
 	struct rchan *chan;		/* associated channel */
 	wait_queue_head_t read_wait;	/* reader wait queue */
-	struct timer_list timer; 	/* reader wake-up timer */
+	struct irq_work wakeup_work;	/* reader wakeup */
 	struct dentry *dentry;		/* channel file dentry */
 	struct kref kref;		/* channel buffer refcount */
 	struct page **page_array;	/* array of current buffer pages */
diff --git a/kernel/relay.c b/kernel/relay.c
index f55ab82..6899f60 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -330,11 +330,11 @@ static struct rchan_callbacks default_channel_callbacks = {
  *	wakeup_readers - wake up readers waiting on a channel
  *	@data: contains the channel buffer
  *
- *	This is the timer function used to defer reader waking.
+ *	This is the function used to defer reader waking
  */
-static void wakeup_readers(unsigned long data)
+static void wakeup_readers(struct irq_work *work)
 {
-	struct rchan_buf *buf = (struct rchan_buf *)data;
+	struct rchan_buf *buf = container_of(work, struct rchan_buf, wakeup_work);
 	wake_up_interruptible(&buf->read_wait);
 }
 
@@ -352,9 +352,10 @@ static void __relay_reset(struct rchan_buf *buf, unsigned int init)
 	if (init) {
 		init_waitqueue_head(&buf->read_wait);
 		kref_init(&buf->kref);
-		setup_timer(&buf->timer, wakeup_readers, (unsigned long)buf);
-	} else
-		del_timer_sync(&buf->timer);
+		init_irq_work(&buf->wakeup_work, wakeup_readers);
+	} else {
+		irq_work_sync(&buf->wakeup_work);
+	}
 
 	buf->subbufs_produced = 0;
 	buf->subbufs_consumed = 0;
@@ -487,7 +488,7 @@ free_buf:
 static void relay_close_buf(struct rchan_buf *buf)
 {
 	buf->finalized = 1;
-	del_timer_sync(&buf->timer);
+	irq_work_sync(&buf->wakeup_work);
 	buf->chan->cb->remove_buf_file(buf->dentry);
 	kref_put(&buf->kref, relay_remove_buf);
 }
@@ -777,14 +778,15 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
 			buf->early_bytes += buf->chan->subbuf_size -
 					    buf->padding[old_subbuf];
 		smp_mb();
-		if (waitqueue_active(&buf->read_wait))
+		if (waitqueue_active(&buf->read_wait)) {
 			/*
 			 * Calling wake_up_interruptible() from here
 			 * will deadlock if we happen to be logging
 			 * from the scheduler (trying to re-grab
 			 * rq->lock), so defer it.
 			 */
-			mod_timer(&buf->timer, jiffies + 1);
+			irq_work_queue(&buf->wakeup_work);
+		}
 	}
 
 	old = buf->data;
-- 
1.9.2

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] relay: Use irq_work instead of plain timer for deferred wakeup
  2016-09-02  9:05 [PATCH] relay: Use irq_work instead of plain timer for deferred wakeup akash.goel
@ 2016-09-02 10:49 ` kbuild test robot
  2016-09-03 12:41   ` [PATCH v2] " akash.goel
  0 siblings, 1 reply; 3+ messages in thread
From: kbuild test robot @ 2016-09-02 10:49 UTC (permalink / raw)
  To: akash.goel
  Cc: kbuild-all, akpm, linux-kernel, Peter Zijlstra, Tom Zanussi,
	Chris Wilson, Tvrtko Ursulin, Akash Goel

[-- Attachment #1: Type: text/plain, Size: 3719 bytes --]

Hi Peter,

[auto build test WARNING on next-20160825]
[cannot apply to linus/master linux/master v4.8-rc4 v4.8-rc3 v4.8-rc2 v4.8-rc4]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
[Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on]
[Check https://git-scm.com/docs/git-format-patch for more information]

url:    https://github.com/0day-ci/linux/commits/akash-goel-intel-com/relay-Use-irq_work-instead-of-plain-timer-for-deferred-wakeup/20160902-165512
reproduce: make htmldocs

All warnings (new ones prefixed by >>):

   lib/crc32.c:148: warning: No description found for parameter 'tab)[256]'
   lib/crc32.c:148: warning: Excess function parameter 'tab' description in 'crc32_le_generic'
   lib/crc32.c:293: warning: No description found for parameter 'tab)[256]'
   lib/crc32.c:293: warning: Excess function parameter 'tab' description in 'crc32_be_generic'
   lib/crc32.c:1: warning: no structured comments found
>> kernel/relay.c:336: warning: No description found for parameter 'work'
>> kernel/relay.c:336: warning: Excess function parameter 'data' description in 'wakeup_readers'
>> kernel/relay.c:336: warning: No description found for parameter 'work'
>> kernel/relay.c:336: warning: Excess function parameter 'data' description in 'wakeup_readers'

vim +/work +336 kernel/relay.c

b86ff981a Jens Axboe     2006-03-23  320  /* relay channel default callbacks */
b86ff981a Jens Axboe     2006-03-23  321  static struct rchan_callbacks default_channel_callbacks = {
b86ff981a Jens Axboe     2006-03-23  322  	.subbuf_start = subbuf_start_default_callback,
b86ff981a Jens Axboe     2006-03-23  323  	.buf_mapped = buf_mapped_default_callback,
b86ff981a Jens Axboe     2006-03-23  324  	.buf_unmapped = buf_unmapped_default_callback,
b86ff981a Jens Axboe     2006-03-23  325  	.create_buf_file = create_buf_file_default_callback,
b86ff981a Jens Axboe     2006-03-23  326  	.remove_buf_file = remove_buf_file_default_callback,
b86ff981a Jens Axboe     2006-03-23  327  };
b86ff981a Jens Axboe     2006-03-23  328  
b86ff981a Jens Axboe     2006-03-23  329  /**
b86ff981a Jens Axboe     2006-03-23  330   *	wakeup_readers - wake up readers waiting on a channel
9a9136e27 Linus Torvalds 2007-05-09  331   *	@data: contains the channel buffer
b86ff981a Jens Axboe     2006-03-23  332   *
60538b154 Peter Zijlstra 2016-09-02  333   *	This is the function used to defer reader waking
b86ff981a Jens Axboe     2006-03-23  334   */
60538b154 Peter Zijlstra 2016-09-02  335  static void wakeup_readers(struct irq_work *work)
b86ff981a Jens Axboe     2006-03-23 @336  {
60538b154 Peter Zijlstra 2016-09-02  337  	struct rchan_buf *buf = container_of(work, struct rchan_buf, wakeup_work);
b86ff981a Jens Axboe     2006-03-23  338  	wake_up_interruptible(&buf->read_wait);
b86ff981a Jens Axboe     2006-03-23  339  }
b86ff981a Jens Axboe     2006-03-23  340  
b86ff981a Jens Axboe     2006-03-23  341  /**
b86ff981a Jens Axboe     2006-03-23  342   *	__relay_reset - reset a channel buffer
b86ff981a Jens Axboe     2006-03-23  343   *	@buf: the channel buffer
b86ff981a Jens Axboe     2006-03-23  344   *	@init: 1 if this is a first-time initialization

:::::: The code at line 336 was first introduced by commit
:::::: b86ff981a8252d83d6a7719ae09f3a05307e3592 [PATCH] relay: migrate from relayfs to a generic relay API

:::::: TO: Jens Axboe <axboe@suse.de>
:::::: CC: Jens Axboe <axboe@suse.de>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 6443 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH v2] relay: Use irq_work instead of plain timer for deferred wakeup
  2016-09-02 10:49 ` kbuild test robot
@ 2016-09-03 12:41   ` akash.goel
  0 siblings, 0 replies; 3+ messages in thread
From: akash.goel @ 2016-09-03 12:41 UTC (permalink / raw)
  To: akpm, linux-kernel
  Cc: Peter Zijlstra, Tom Zanussi, Chris Wilson, Tvrtko Ursulin, Akash Goel

From: Peter Zijlstra <peterz@infradead.org>

Relay avoids calling wake_up_interruptible() for doing the wakeup of
readers/consumers, waiting for the generation of new data, from the
context of a process which produced the data. This is apparently done
to prevent the possibility of a deadlock in case Scheduler itself is
is generating data for the relay, after acquiring rq->lock.

The following patch used a timer (to be scheduled at next jiffy), for
delegating the wakeup to another context.
	commit 7c9cb38302e78d24e37f7d8a2ea7eed4ae5f2fa7
	Author: Tom Zanussi <zanussi@comcast.net>
	Date:   Wed May 9 02:34:01 2007 -0700

	relay: use plain timer instead of delayed work

	relay doesn't need to use schedule_delayed_work() for waking readers
	when a simple timer will do.

Scheduling a plain timer, at next jiffies boundary, to do the wakeup causes
a significant wakeup latency for the Userspace client, which makes relay less
suitable for the high-frequency low-payload use cases where the data gets
generated at a very high rate, like multiple sub buffers getting filled
within a milli second.
Moreover the timer is re-scheduled on every newly produced sub buffer so the
timer keeps getting pushed out if sub buffers are filled in a very quick
succession (less than a jiffy gap between filling of 2 sub buffers).
As a result relay runs out of sub buffers to store the new data.

By using irq_work it is ensured that wakeup of userspace client, blocked in
the poll call, is done at earliest (through self IPI or next timer tick)
enabling him to always consume the data in time.
Also this makes relay consistent with printk & ring buffers (trace), as they
too use irq_work for deferred wake up of readers.

v2: Fix the documentation related warning.

Cc: Tom Zanussi <tzanussi@gmail.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Akash Goel <akash.goel@intel.com>
---
 include/linux/relay.h |  3 ++-
 kernel/relay.c        | 22 ++++++++++++----------
 2 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/include/linux/relay.h b/include/linux/relay.h
index eb295e3..54960a5 100644
--- a/include/linux/relay.h
+++ b/include/linux/relay.h
@@ -20,6 +20,7 @@
 #include <linux/poll.h>
 #include <linux/kref.h>
 #include <linux/percpu.h>
+#include <linux/irq_work.h>
 
 /*
  * Tracks changes to rchan/rchan_buf structs
@@ -38,7 +39,7 @@ struct rchan_buf
 	size_t subbufs_consumed;	/* count of sub-buffers consumed */
 	struct rchan *chan;		/* associated channel */
 	wait_queue_head_t read_wait;	/* reader wait queue */
-	struct timer_list timer; 	/* reader wake-up timer */
+	struct irq_work wakeup_work;	/* reader wakeup */
 	struct dentry *dentry;		/* channel file dentry */
 	struct kref kref;		/* channel buffer refcount */
 	struct page **page_array;	/* array of current buffer pages */
diff --git a/kernel/relay.c b/kernel/relay.c
index f55ab82..946f976 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -328,13 +328,13 @@ static struct rchan_callbacks default_channel_callbacks = {
 
 /**
  *	wakeup_readers - wake up readers waiting on a channel
- *	@data: contains the channel buffer
+ *	@work: contains the channel buffer
  *
- *	This is the timer function used to defer reader waking.
+ *	This is the function used to defer reader waking
  */
-static void wakeup_readers(unsigned long data)
+static void wakeup_readers(struct irq_work *work)
 {
-	struct rchan_buf *buf = (struct rchan_buf *)data;
+	struct rchan_buf *buf = container_of(work, struct rchan_buf, wakeup_work);
 	wake_up_interruptible(&buf->read_wait);
 }
 
@@ -352,9 +352,10 @@ static void __relay_reset(struct rchan_buf *buf, unsigned int init)
 	if (init) {
 		init_waitqueue_head(&buf->read_wait);
 		kref_init(&buf->kref);
-		setup_timer(&buf->timer, wakeup_readers, (unsigned long)buf);
-	} else
-		del_timer_sync(&buf->timer);
+		init_irq_work(&buf->wakeup_work, wakeup_readers);
+	} else {
+		irq_work_sync(&buf->wakeup_work);
+	}
 
 	buf->subbufs_produced = 0;
 	buf->subbufs_consumed = 0;
@@ -487,7 +488,7 @@ free_buf:
 static void relay_close_buf(struct rchan_buf *buf)
 {
 	buf->finalized = 1;
-	del_timer_sync(&buf->timer);
+	irq_work_sync(&buf->wakeup_work);
 	buf->chan->cb->remove_buf_file(buf->dentry);
 	kref_put(&buf->kref, relay_remove_buf);
 }
@@ -777,14 +778,15 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
 			buf->early_bytes += buf->chan->subbuf_size -
 					    buf->padding[old_subbuf];
 		smp_mb();
-		if (waitqueue_active(&buf->read_wait))
+		if (waitqueue_active(&buf->read_wait)) {
 			/*
 			 * Calling wake_up_interruptible() from here
 			 * will deadlock if we happen to be logging
 			 * from the scheduler (trying to re-grab
 			 * rq->lock), so defer it.
 			 */
-			mod_timer(&buf->timer, jiffies + 1);
+			irq_work_queue(&buf->wakeup_work);
+		}
 	}
 
 	old = buf->data;
-- 
1.9.2

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-09-03 12:27 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-02  9:05 [PATCH] relay: Use irq_work instead of plain timer for deferred wakeup akash.goel
2016-09-02 10:49 ` kbuild test robot
2016-09-03 12:41   ` [PATCH v2] " akash.goel

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.