linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Input:Flush client events on clk_type change
@ 2015-01-07 18:26 Anshul Garg
  0 siblings, 0 replies; 5+ messages in thread
From: Anshul Garg @ 2015-01-07 18:26 UTC (permalink / raw)
  To: dmitry.torokhov, dtor, linux-input; +Cc: aksgarg1989, anshul.g

From: Anshul Garg <aksgarg1989@gmail.com>

Since the client clk_type is changed , flush pending
events from client buffer and queue SYN_DROPPED event.
Added check for duplicate clk_type change request.

Signed-off-by: Anshul Garg <anshul.g@samsung.com>
---
 drivers/input/evdev.c |   18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index b1a52ab..d024fc6 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -62,8 +62,12 @@ struct evdev_client {
 	struct input_event buffer[];
 };
 
-static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
+static int evdev_set_clk_type(struct evdev_client *client,
+			struct input_dev *dev, unsigned int clkid)
 {
+	if (client->clk_type == clkid)
+		return 0;
+
 	switch (clkid) {
 
 	case CLOCK_REALTIME:
@@ -78,7 +82,17 @@ static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
 	default:
 		return -EINVAL;
 	}
+
+	spin_lock_irq(&dev->event_lock);
+	spin_lock(&client->buffer_lock);
+	spin_unlock(&dev->event_lock);
 
+	/* Flush clients events after clk_type is changed
+	 * and queue SYN_DROPPED event.*/
+	client->packet_head = client->head = client->tail;
+	spin_unlock_irq(&client->buffer_lock);
+
+	evdev_queue_syn_dropped(client);
 	return 0;
 }
 
@@ -908,7 +922,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 		if (copy_from_user(&i, p, sizeof(unsigned int)))
 			return -EFAULT;
 
-		return evdev_set_clk_type(client, i);
+		return evdev_set_clk_type(client, dev, i);
 
 	case EVIOCGKEYCODE:
 		return evdev_handle_get_keycode(dev, p);
-- 
1.7.9.5


---
This email has been checked for viruses by Avast antivirus software.
http://www.avast.com


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

* [PATCH] Input:Flush client events on clk_type change
@ 2015-01-07 18:56 Anshul Garg
  2015-01-07 19:32 ` Dmitry Torokhov
  0 siblings, 1 reply; 5+ messages in thread
From: Anshul Garg @ 2015-01-07 18:56 UTC (permalink / raw)
  To: dmitry.torokhov, dtor, linux-input; +Cc: aksgarg1989, anshul.g

From: Anshul Garg <aksgarg1989@gmail.com>

Since the client clk_type is changed , flush pending
events from client buffer and queue SYN_DROPPED event.
Added check for duplicate clk_type change request.

Signed-off-by: Anshul Garg <anshul.g@samsung.com>
---
 drivers/input/evdev.c |   58 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 36 insertions(+), 22 deletions(-)

diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index b1a52ab..223367e 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -62,27 +62,6 @@ struct evdev_client {
 	struct input_event buffer[];
 };
 
-static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
-{
-	switch (clkid) {
-
-	case CLOCK_REALTIME:
-		client->clk_type = EV_CLK_REAL;
-		break;
-	case CLOCK_MONOTONIC:
-		client->clk_type = EV_CLK_MONO;
-		break;
-	case CLOCK_BOOTTIME:
-		client->clk_type = EV_CLK_BOOT;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-/* flush queued events of type @type, caller must hold client->buffer_lock */
 static void __evdev_flush_queue(struct evdev_client *client, unsigned int type)
 {
 	unsigned int i, head, num;
@@ -160,6 +139,41 @@ static void evdev_queue_syn_dropped(struct evdev_client *client)
 	spin_unlock_irqrestore(&client->buffer_lock, flags);
 }
 
+static int evdev_set_clk_type(struct evdev_client *client,
+			struct input_dev *dev, unsigned int clkid)
+{
+	if (client->clk_type == clkid)
+		return 0;
+
+	switch (clkid) {
+
+	case CLOCK_REALTIME:
+		client->clk_type = EV_CLK_REAL;
+		break;
+	case CLOCK_MONOTONIC:
+		client->clk_type = EV_CLK_MONO;
+		break;
+	case CLOCK_BOOTTIME:
+		client->clk_type = EV_CLK_BOOT;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	spin_lock_irq(&dev->event_lock);
+	spin_lock(&client->buffer_lock);
+	spin_unlock(&dev->event_lock);
+
+	/* Flush clients events after clk_type is changed
+	 * and queue SYN_DROPPED event.*/
+	client->packet_head = client->head = client->tail;
+	spin_unlock_irq(&client->buffer_lock);
+
+	evdev_queue_syn_dropped(client);
+	return 0;
+}
+
+/* flush queued events of type @type, caller must hold client->buffer_lock */
 static void __pass_event(struct evdev_client *client,
 			 const struct input_event *event)
 {
@@ -908,7 +922,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd,
 		if (copy_from_user(&i, p, sizeof(unsigned int)))
 			return -EFAULT;
 
-		return evdev_set_clk_type(client, i);
+		return evdev_set_clk_type(client, dev, i);
 
 	case EVIOCGKEYCODE:
 		return evdev_handle_get_keycode(dev, p);
-- 
1.7.9.5


---
This email has been checked for viruses by Avast antivirus software.
http://www.avast.com


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

* Re: [PATCH] Input:Flush client events on clk_type change
  2015-01-07 18:56 [PATCH] Input:Flush client events on clk_type change Anshul Garg
@ 2015-01-07 19:32 ` Dmitry Torokhov
  2015-01-08 13:57   ` Anshul Garg
  0 siblings, 1 reply; 5+ messages in thread
From: Dmitry Torokhov @ 2015-01-07 19:32 UTC (permalink / raw)
  To: Anshul Garg; +Cc: linux-input, anshul.g

On Wed, Jan 07, 2015 at 10:56:03AM -0800, Anshul Garg wrote:
> From: Anshul Garg <aksgarg1989@gmail.com>
> 
> Since the client clk_type is changed , flush pending
> events from client buffer and queue SYN_DROPPED event.
> Added check for duplicate clk_type change request.
> 
> Signed-off-by: Anshul Garg <anshul.g@samsung.com>
> ---
>  drivers/input/evdev.c |   58 ++++++++++++++++++++++++++++++-------------------
>  1 file changed, 36 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
> index b1a52ab..223367e 100644
> --- a/drivers/input/evdev.c
> +++ b/drivers/input/evdev.c
> @@ -62,27 +62,6 @@ struct evdev_client {
>  	struct input_event buffer[];
>  };
>  
> -static int evdev_set_clk_type(struct evdev_client *client, unsigned int clkid)
> -{
> -	switch (clkid) {
> -
> -	case CLOCK_REALTIME:
> -		client->clk_type = EV_CLK_REAL;
> -		break;
> -	case CLOCK_MONOTONIC:
> -		client->clk_type = EV_CLK_MONO;
> -		break;
> -	case CLOCK_BOOTTIME:
> -		client->clk_type = EV_CLK_BOOT;
> -		break;
> -	default:
> -		return -EINVAL;
> -	}
> -
> -	return 0;
> -}
> -
> -/* flush queued events of type @type, caller must hold client->buffer_lock */
>  static void __evdev_flush_queue(struct evdev_client *client, unsigned int type)
>  {
>  	unsigned int i, head, num;
> @@ -160,6 +139,41 @@ static void evdev_queue_syn_dropped(struct evdev_client *client)
>  	spin_unlock_irqrestore(&client->buffer_lock, flags);
>  }
>  
> +static int evdev_set_clk_type(struct evdev_client *client,
> +			struct input_dev *dev, unsigned int clkid)
> +{
> +	if (client->clk_type == clkid)
> +		return 0;
> +
> +	switch (clkid) {
> +
> +	case CLOCK_REALTIME:
> +		client->clk_type = EV_CLK_REAL;
> +		break;
> +	case CLOCK_MONOTONIC:
> +		client->clk_type = EV_CLK_MONO;
> +		break;
> +	case CLOCK_BOOTTIME:
> +		client->clk_type = EV_CLK_BOOT;
> +		break;
> +	default:
> +		return -EINVAL;
> +	}
> +
> +	spin_lock_irq(&dev->event_lock);
> +	spin_lock(&client->buffer_lock);
> +	spin_unlock(&dev->event_lock);

Umm, why?

> +
> +	/* Flush clients events after clk_type is changed
> +	 * and queue SYN_DROPPED event.*/
> +	client->packet_head = client->head = client->tail;
> +	spin_unlock_irq(&client->buffer_lock);
> +
> +	evdev_queue_syn_dropped(client);

This is still racy. I'd rather we passed a flag to
evdev_queue_syn_dropped() to indicate it should also clear queue.

Thanks.

-- 
Dmitry

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

* Re: [PATCH] Input:Flush client events on clk_type change
  2015-01-07 19:32 ` Dmitry Torokhov
@ 2015-01-08 13:57   ` Anshul Garg
  2015-01-08 21:41     ` Dmitry Torokhov
  0 siblings, 1 reply; 5+ messages in thread
From: Anshul Garg @ 2015-01-08 13:57 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input, anshul.g@samsung.com

Dear Mr. Dmitry ,

Thanks a lot for your suggestions.

> + spin_lock_irq(&dev->event_lock);
> + spin_lock(&client->buffer_lock);
> + spin_unlock(&dev->event_lock);

Umm, why?

Yes, there is no need of event_lock as we are modifying client
specific data structure only.

Hence only buffer_lock will guarantee atomicity for flushing of client
pending events buffer.

So i will modify locking mechanism to use buffer_lock only.

> +
> + /* Flush clients events after clk_type is changed
> + * and queue SYN_DROPPED event.*/
> + client->packet_head = client->head = client->tail;
> + spin_unlock_irq(&client->buffer_lock);
> +
> + evdev_queue_syn_dropped(client);

This is still racy. I'd rather we passed a flag to
evdev_queue_syn_dropped() to indicate it should also clear queue.

Can you please tell me in which scenario's this patch is prone to race
condition's?
As i think we are modifying the client's buffer indexes so buffer_lock
would be sufficient.


Yes by adding one more parameter in evdev_queue_syn_dropped function
on the basis
of which we can flush the buffer.

Example ::

static void evdev_queue_syn_dropped(struct evdev_client *client)

It can be changed to

static void evdev_queue_syn_dropped(struct evdev_client *client , bool flush)
{
spin_lock(buffer_lock);

if(flush)
    client->packet_head = client->head = client->tail;


.........

spin_unlock(buffer_lock);
}

OR
Similarly we can extend__evdev_flush_queue function to support
flushing of client event queue.
As currently this function flushes single type of events only.

I think 2nd way is better.

Please give your insignt on above suggested changes.

Thanks
Anshul Garg

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

* Re: [PATCH] Input:Flush client events on clk_type change
  2015-01-08 13:57   ` Anshul Garg
@ 2015-01-08 21:41     ` Dmitry Torokhov
  0 siblings, 0 replies; 5+ messages in thread
From: Dmitry Torokhov @ 2015-01-08 21:41 UTC (permalink / raw)
  To: Anshul Garg; +Cc: linux-input, anshul.g@samsung.com

On Thu, Jan 08, 2015 at 07:27:59PM +0530, Anshul Garg wrote:
> Dear Mr. Dmitry ,
> 
> Thanks a lot for your suggestions.
> 
> > + spin_lock_irq(&dev->event_lock);
> > + spin_lock(&client->buffer_lock);
> > + spin_unlock(&dev->event_lock);
> 
> Umm, why?
> 
> Yes, there is no need of event_lock as we are modifying client
> specific data structure only.
> 
> Hence only buffer_lock will guarantee atomicity for flushing of client
> pending events buffer.
> 
> So i will modify locking mechanism to use buffer_lock only.
> 
> > +
> > + /* Flush clients events after clk_type is changed
> > + * and queue SYN_DROPPED event.*/
> > + client->packet_head = client->head = client->tail;
> > + spin_unlock_irq(&client->buffer_lock);
> > +
> > + evdev_queue_syn_dropped(client);
> 
> This is still racy. I'd rather we passed a flag to
> evdev_queue_syn_dropped() to indicate it should also clear queue.
> 
> Can you please tell me in which scenario's this patch is prone to race
> condition's?
> As i think we are modifying the client's buffer indexes so buffer_lock
> would be sufficient.

New events may come up between resetting the queue and queuing EV_SYN
and client would not really know if they contain valid time or not.

> 
> 
> Yes by adding one more parameter in evdev_queue_syn_dropped function
> on the basis
> of which we can flush the buffer.
> 
> Example ::
> 
> static void evdev_queue_syn_dropped(struct evdev_client *client)
> 
> It can be changed to
> 
> static void evdev_queue_syn_dropped(struct evdev_client *client , bool flush)
> {
> spin_lock(buffer_lock);
> 
> if(flush)
>     client->packet_head = client->head = client->tail;
> 
> 
> .........
> 
> spin_unlock(buffer_lock);
> }
> 
> OR
> Similarly we can extend__evdev_flush_queue function to support
> flushing of client event queue.
> As currently this function flushes single type of events only.
> 
> I think 2nd way is better.
> 
> Please give your insignt on above suggested changes.

I do not see how make evdev_flush_queue() to flush all types of events
without adding another parameter that would "override" type, which is
ugly.

It looks like we can make evdev_queue_syn_dropped() zap the old events
unconditionally, so I'd rather do that.

Thanks.

-- 
Dmitry

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

end of thread, other threads:[~2015-01-08 21:41 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-01-07 18:56 [PATCH] Input:Flush client events on clk_type change Anshul Garg
2015-01-07 19:32 ` Dmitry Torokhov
2015-01-08 13:57   ` Anshul Garg
2015-01-08 21:41     ` Dmitry Torokhov
  -- strict thread matches above, loose matches on Subject: below --
2015-01-07 18:26 Anshul Garg

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