From: Mauro Carvalho Chehab <m.chehab@samsung.com>
To: "David Härdeman" <david@hardeman.nu>
Cc: linux-media@vger.kernel.org
Subject: Re: [PATCH 40/49] rc-ir-raw: simplify locking
Date: Fri, 25 Jul 2014 20:08:52 -0300 [thread overview]
Message-ID: <20140725200852.1aa56c69.m.chehab@samsung.com> (raw)
In-Reply-To: <20140403233438.27099.1183.stgit@zeus.muc.hardeman.nu>
Em Fri, 04 Apr 2014 01:34:38 +0200
David Härdeman <david@hardeman.nu> escreveu:
> Simplify and improve the locking in rc-ir-raw by making better use of
> the existing kfifo functionality and by using RCU where possible.
Please rebase.
>
> Signed-off-by: David Härdeman <david@hardeman.nu>
> ---
> drivers/media/rc/rc-core-priv.h | 6 +-
> drivers/media/rc/rc-ir-raw.c | 124 ++++++++++++++++-----------------------
> 2 files changed, 55 insertions(+), 75 deletions(-)
>
> diff --git a/drivers/media/rc/rc-core-priv.h b/drivers/media/rc/rc-core-priv.h
> index 0b32ef8..c3de26b 100644
> --- a/drivers/media/rc/rc-core-priv.h
> +++ b/drivers/media/rc/rc-core-priv.h
> @@ -37,11 +37,13 @@ struct ir_raw_handler {
> int (*raw_unregister)(struct rc_dev *dev);
> };
>
> +/* max number of pulse/space transitions to buffer */
> +#define RC_MAX_IR_EVENTS 512
> +
> struct ir_raw_event_ctrl {
> struct list_head list; /* to keep track of raw clients */
> struct task_struct *thread;
> - spinlock_t lock;
> - struct kfifo_rec_ptr_1 kfifo; /* fifo for the pulse/space durations */
> + DECLARE_KFIFO(kfifo, struct ir_raw_event, RC_MAX_IR_EVENTS); /* for pulse/space durations */
> ktime_t last_event; /* when last event occurred */
> enum raw_event_type last_type; /* last event type */
> struct rc_dev *dev; /* pointer to the parent rc_dev */
> diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
> index 86f5aa7..9631825 100644
> --- a/drivers/media/rc/rc-ir-raw.c
> +++ b/drivers/media/rc/rc-ir-raw.c
> @@ -21,15 +21,12 @@
> #include <linux/freezer.h>
> #include "rc-core-priv.h"
>
> -/* Define the max number of pulse/space transitions to buffer */
> -#define MAX_IR_EVENT_SIZE 512
> -
> -/* Used to keep track of IR raw clients, protected by ir_raw_handler_lock */
> +/* IR raw clients/handlers, writers synchronize with ir_raw_mutex */
> +static DEFINE_MUTEX(ir_raw_mutex);
> static LIST_HEAD(ir_raw_client_list);
> -
> -/* Used to handle IR raw handler extensions */
> -static DEFINE_MUTEX(ir_raw_handler_lock);
> static LIST_HEAD(ir_raw_handler_list);
> +
> +/* protocols supported by the currently loaded decoders */
> static u64 available_protocols;
>
> static int ir_raw_event_thread(void *data)
> @@ -37,32 +34,19 @@ static int ir_raw_event_thread(void *data)
> struct ir_raw_event ev;
> struct ir_raw_handler *handler;
> struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
> - int retval;
>
> while (!kthread_should_stop()) {
> -
> - spin_lock_irq(&raw->lock);
> - retval = kfifo_len(&raw->kfifo);
> -
> - if (retval < sizeof(ev)) {
> + if (kfifo_out(&raw->kfifo, &ev, 1) == 0) {
> set_current_state(TASK_INTERRUPTIBLE);
> -
> - if (kthread_should_stop())
> - set_current_state(TASK_RUNNING);
> -
> - spin_unlock_irq(&raw->lock);
> schedule();
> continue;
> }
>
> - retval = kfifo_out(&raw->kfifo, &ev, sizeof(ev));
> - spin_unlock_irq(&raw->lock);
> -
> - mutex_lock(&ir_raw_handler_lock);
> - list_for_each_entry(handler, &ir_raw_handler_list, list)
> + rcu_read_lock();
> + list_for_each_entry_rcu(handler, &ir_raw_handler_list, list)
> handler->decode(raw->dev, ev);
> + rcu_read_unlock();
> raw->prev_ev = ev;
> - mutex_unlock(&ir_raw_handler_lock);
> }
>
> return 0;
> @@ -76,7 +60,8 @@ static int ir_raw_event_thread(void *data)
> * This routine (which may be called from an interrupt context) stores a
> * pulse/space duration for the raw ir decoding state machines. Pulses are
> * signalled as positive values and spaces as negative values. A zero value
> - * will reset the decoding state machines.
> + * will reset the decoding state machines. Drivers are responsible for
> + * synchronizing calls to this function.
> */
> int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev)
> {
> @@ -86,7 +71,7 @@ int ir_raw_event_store(struct rc_dev *dev, struct ir_raw_event *ev)
> IR_dprintk(2, "sample: (%05dus %s)\n",
> TO_US(ev->duration), TO_STR(ev->pulse));
>
> - if (kfifo_in(&dev->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
> + if (kfifo_in(&dev->raw->kfifo, ev, 1) != 1)
> return -ENOMEM;
>
> return 0;
> @@ -258,14 +243,8 @@ EXPORT_SYMBOL_GPL(ir_raw_get_tx_event);
> */
> void ir_raw_event_handle(struct rc_dev *dev)
> {
> - unsigned long flags;
> -
> - if (!dev->raw)
> - return;
> -
> - spin_lock_irqsave(&dev->raw->lock, flags);
> - wake_up_process(dev->raw->thread);
> - spin_unlock_irqrestore(&dev->raw->lock, flags);
> + if (dev->raw)
> + wake_up_process(dev->raw->thread);
> }
> EXPORT_SYMBOL_GPL(ir_raw_event_handle);
>
> @@ -273,9 +252,9 @@ EXPORT_SYMBOL_GPL(ir_raw_event_handle);
> static u64 ir_raw_get_allowed_protocols(struct rc_dev *dev)
> {
> u64 protocols;
> - mutex_lock(&ir_raw_handler_lock);
> + mutex_lock(&ir_raw_mutex);
> protocols = available_protocols;
> - mutex_unlock(&ir_raw_handler_lock);
> + mutex_unlock(&ir_raw_mutex);
> return protocols;
> }
>
> @@ -290,52 +269,49 @@ static int change_protocol(struct rc_dev *dev, u64 *rc_type) {
> int rc_register_ir_raw_device(struct rc_dev *dev)
> {
> int rc;
> + struct ir_raw_event_ctrl *raw;
> struct ir_raw_handler *handler;
>
> if (!dev)
> return -EINVAL;
>
> - dev->raw = kzalloc(sizeof(*dev->raw), GFP_KERNEL);
> - if (!dev->raw)
> + raw = kzalloc(sizeof(*raw), GFP_KERNEL);
> + if (!raw)
> return -ENOMEM;
>
> - dev->raw->dev = dev;
> - dev->enabled_protocols = ~0;
> - dev->get_protocols = ir_raw_get_allowed_protocols;
> - dev->driver_type = RC_DRIVER_IR_RAW;
> - dev->change_protocol = change_protocol;
> - spin_lock_init(&dev->raw->lock);
> - rc = kfifo_alloc(&dev->raw->kfifo,
> - sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
> - GFP_KERNEL);
> - if (rc < 0)
> - goto out;
> -
> - dev->raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
> - dev_name(&dev->dev));
> + raw->dev = dev;
> + INIT_KFIFO(raw->kfifo);
> + raw->thread = kthread_run(ir_raw_event_thread, dev->raw,
> + dev_name(&dev->dev));
>
> - if (IS_ERR(dev->raw->thread)) {
> - rc = PTR_ERR(dev->raw->thread);
> + if (IS_ERR(raw->thread)) {
> + rc = PTR_ERR(raw->thread);
> goto out;
> }
>
> + dev->raw = raw;
> + dev->enabled_protocols = ~0;
> + dev->get_protocols = ir_raw_get_allowed_protocols;
> + dev->driver_type = RC_DRIVER_IR_RAW;
> + dev->change_protocol = change_protocol;
> rc = rc_register_device(dev);
> if (rc < 0)
> goto out_thread;
>
> - mutex_lock(&ir_raw_handler_lock);
> - list_add_tail(&dev->raw->list, &ir_raw_client_list);
> - list_for_each_entry(handler, &ir_raw_handler_list, list)
> + mutex_lock(&ir_raw_mutex);
> + list_add_tail_rcu(&dev->raw->list, &ir_raw_client_list);
> + list_for_each_entry_rcu(handler, &ir_raw_handler_list, list)
> if (handler->raw_register)
> handler->raw_register(dev);
> - mutex_unlock(&ir_raw_handler_lock);
> + mutex_unlock(&ir_raw_mutex);
> + synchronize_rcu();
>
> return 0;
>
> out_thread:
> - kthread_stop(dev->raw->thread);
> + kthread_stop(raw->thread);
> out:
> - kfree(dev->raw);
> + kfree(raw);
> dev->raw = NULL;
> return rc;
> }
> @@ -350,14 +326,14 @@ void rc_unregister_ir_raw_device(struct rc_dev *dev)
>
> kthread_stop(dev->raw->thread);
>
> - mutex_lock(&ir_raw_handler_lock);
> - list_del(&dev->raw->list);
> - list_for_each_entry(handler, &ir_raw_handler_list, list)
> + mutex_lock(&ir_raw_mutex);
> + list_del_rcu(&dev->raw->list);
> + list_for_each_entry_rcu(handler, &ir_raw_handler_list, list)
> if (handler->raw_unregister)
> handler->raw_unregister(dev);
> - mutex_unlock(&ir_raw_handler_lock);
> + mutex_unlock(&ir_raw_mutex);
> + synchronize_rcu();
>
> - kfifo_free(&dev->raw->kfifo);
> kfree(dev->raw);
> dev->raw = NULL;
> rc_unregister_device(dev);
> @@ -372,13 +348,14 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
> {
> struct ir_raw_event_ctrl *raw;
>
> - mutex_lock(&ir_raw_handler_lock);
> - list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
> + mutex_lock(&ir_raw_mutex);
> + list_add_tail_rcu(&ir_raw_handler->list, &ir_raw_handler_list);
> if (ir_raw_handler->raw_register)
> - list_for_each_entry(raw, &ir_raw_client_list, list)
> + list_for_each_entry_rcu(raw, &ir_raw_client_list, list)
> ir_raw_handler->raw_register(raw->dev);
> available_protocols |= ir_raw_handler->protocols;
> - mutex_unlock(&ir_raw_handler_lock);
> + mutex_unlock(&ir_raw_mutex);
> + synchronize_rcu();
>
> return 0;
> }
> @@ -388,13 +365,14 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
> {
> struct ir_raw_event_ctrl *raw;
>
> - mutex_lock(&ir_raw_handler_lock);
> - list_del(&ir_raw_handler->list);
> + mutex_lock(&ir_raw_mutex);
> + list_del_rcu(&ir_raw_handler->list);
> if (ir_raw_handler->raw_unregister)
> - list_for_each_entry(raw, &ir_raw_client_list, list)
> + list_for_each_entry_rcu(raw, &ir_raw_client_list, list)
> ir_raw_handler->raw_unregister(raw->dev);
> available_protocols &= ~ir_raw_handler->protocols;
> - mutex_unlock(&ir_raw_handler_lock);
> + mutex_unlock(&ir_raw_mutex);
> + synchronize_rcu();
> }
> EXPORT_SYMBOL(ir_raw_handler_unregister);
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2014-07-25 23:08 UTC|newest]
Thread overview: 68+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-03 23:31 [PATCH 00/49] rc-core: my current patch queue David Härdeman
2014-04-03 23:31 ` [PATCH 01/49] bt8xx: fixup RC5 decoding David Härdeman
2014-04-03 23:31 ` [PATCH 02/49] rc-core: improve ir-kbd-i2c get_key functions David Härdeman
2014-04-03 23:31 ` [PATCH 03/49] rc-core: document the protocol type David Härdeman
2014-04-03 23:31 ` [PATCH 04/49] rc-core: do not change 32bit NEC scancode format for now David Härdeman
2014-04-04 13:18 ` James Hogan
2014-04-03 23:31 ` [PATCH 05/49] rc-core: split dev->s_filter David Härdeman
2014-04-04 13:08 ` James Hogan
2014-04-03 23:31 ` [PATCH 06/49] rc-core: remove generic scancode filter David Härdeman
2014-04-04 13:30 ` James Hogan
2014-04-03 23:31 ` [PATCH 07/49] dib0700: NEC scancode cleanup David Härdeman
2014-04-03 23:31 ` [PATCH 08/49] lmedm04: " David Härdeman
2014-04-03 23:32 ` [PATCH 09/49] saa7134: NEC scancode fix David Härdeman
2014-04-03 23:32 ` [PATCH 10/49] [RFC] rc-core: use the full 32 bits for NEC scancodes David Härdeman
2014-04-03 23:32 ` [PATCH 11/49] [RFC] rc-core: don't throw away protocol information David Härdeman
2014-04-03 23:32 ` [PATCH 12/49] rc-core: simplify sysfs code David Härdeman
2014-04-03 23:32 ` [PATCH 13/49] rc-core: remove protocol arrays David Härdeman
2014-04-03 23:32 ` [PATCH 14/49] rc-core: rename dev->scanmask to dev->scancode_mask David Härdeman
2014-04-03 23:32 ` [PATCH 15/49] rc-core: merge rc5 and streamzap decoders David Härdeman
2014-04-03 23:32 ` [PATCH 16/49] rc-core: use an IDA rather than a bitmap David Härdeman
2014-07-25 22:39 ` Mauro Carvalho Chehab
2014-04-03 23:32 ` [PATCH 17/49] rc-core: add chardev David Härdeman
2014-04-03 23:32 ` [PATCH 18/49] rc-core: allow chardev to be read David Härdeman
2014-04-03 23:32 ` [PATCH 19/49] rc-core: use a kfifo for TX data David Härdeman
2014-04-03 23:32 ` [PATCH 20/49] rc-core: allow chardev to be written David Härdeman
2014-04-03 23:33 ` [PATCH 21/49] rc-core: add ioctl support to the rc chardev David Härdeman
2014-04-03 23:33 ` [PATCH 22/49] rc-core: add an ioctl for getting IR RX settings David Härdeman
2014-04-03 23:33 ` [PATCH 23/49] rc-loopback: add RCIOCGIRRX ioctl support David Härdeman
2014-04-03 23:33 ` [PATCH 24/49] rc-core: add an ioctl for setting IR RX settings David Härdeman
2014-04-03 23:33 ` [PATCH 25/49] rc-loopback: add RCIOCSIRRX ioctl support David Härdeman
2014-04-03 23:33 ` [PATCH 26/49] rc-core: add an ioctl for getting IR TX settings David Härdeman
2014-04-03 23:33 ` [PATCH 27/49] rc-loopback: add RCIOCGIRTX ioctl support David Härdeman
2014-04-03 23:33 ` [PATCH 28/49] rc-core: add an ioctl for setting IR TX settings David Härdeman
2014-04-03 23:33 ` [PATCH 29/49] rc-loopback: add RCIOCSIRTX ioctl support David Härdeman
2014-04-03 23:33 ` [PATCH 30/49] rc-core: leave the internals of rc_dev alone David Härdeman
2014-07-24 1:50 ` Mauro Carvalho Chehab
2014-04-03 23:33 ` [PATCH 31/49] rc-core: split rc-main.c into rc-main.c and rc-keytable.c David Härdeman
2014-07-25 22:44 ` Mauro Carvalho Chehab
2014-04-03 23:33 ` [PATCH 32/49] rc-core: prepare for multiple keytables David Härdeman
2014-07-25 22:52 ` Mauro Carvalho Chehab
2014-04-03 23:34 ` [PATCH 33/49] rc-core: make the keytable of rc_dev an array David Härdeman
2014-04-03 23:34 ` [PATCH 34/49] rc-core: add ioctls for adding/removing keytables from userspace David Härdeman
2014-04-03 23:34 ` [PATCH 35/49] rc-core: remove redundant spinlock David Härdeman
2014-04-03 23:34 ` [PATCH 36/49] rc-core: make keytable RCU-friendly David Härdeman
2014-04-03 23:34 ` [PATCH 37/49] rc-core: allow empty keymaps David Härdeman
2014-07-25 22:58 ` Mauro Carvalho Chehab
2014-04-03 23:34 ` [PATCH 38/49] rc-core: rename ir-raw.c David Härdeman
2014-04-03 23:34 ` [PATCH 39/49] rc-core: make IR raw handling a separate module David Härdeman
2014-07-25 23:04 ` Mauro Carvalho Chehab
2014-04-03 23:34 ` [PATCH 40/49] rc-ir-raw: simplify locking David Härdeman
2014-07-25 23:08 ` Mauro Carvalho Chehab [this message]
2014-04-03 23:34 ` [PATCH 41/49] rc-core: rename mutex David Härdeman
2014-04-10 21:28 ` James Hogan
2014-07-25 23:12 ` Mauro Carvalho Chehab
2014-04-03 23:34 ` [PATCH 42/49] rc-ir-raw: atomic reads of protocols David Härdeman
2014-07-25 23:13 ` Mauro Carvalho Chehab
2014-04-03 23:34 ` [PATCH 43/49] rc-core: fix various sparse warnings David Härdeman
2014-04-03 23:34 ` [PATCH 44/49] rc-core: don't report scancodes via input devices David Härdeman
2014-07-25 23:16 ` Mauro Carvalho Chehab
2014-04-03 23:35 ` [PATCH 45/49] rc-ir-raw: add various rc_events David Härdeman
2014-07-25 23:16 ` Mauro Carvalho Chehab
2014-04-03 23:35 ` [PATCH 46/49] rc-core: use struct rc_event for all rc communication David Härdeman
2014-07-25 23:19 ` Mauro Carvalho Chehab
2014-04-03 23:35 ` [PATCH 47/49] rc-core: add keytable events David Härdeman
2014-04-03 23:35 ` [PATCH 48/49] rc-core: move remaining keytable functions David Härdeman
2014-04-03 23:35 ` [PATCH 49/49] rc-core: make rc-core.h userspace friendly David Härdeman
2014-04-04 2:05 ` [PATCH 00/49] rc-core: my current patch queue Mauro Carvalho Chehab
2014-06-26 20:07 ` David Härdeman
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=20140725200852.1aa56c69.m.chehab@samsung.com \
--to=m.chehab@samsung.com \
--cc=david@hardeman.nu \
--cc=linux-media@vger.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