linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH RT] add missing local serialization in ip_output.c
@ 2013-12-29 17:11 Nicholas Mc Guire
  2013-12-31  7:36 ` Jouko Haapaluoma
  2014-01-17 14:47 ` Sebastian Andrzej Siewior
  0 siblings, 2 replies; 13+ messages in thread
From: Nicholas Mc Guire @ 2013-12-29 17:11 UTC (permalink / raw)
  To: linux-rt-users
  Cc: Sami Pietikainen, Jouko Haapaluoma, Sebastian Andrzej Siewior,
	LKML, Thomas Gleixner, Steven Rostedt


in response to the oops in ip_output.c:ip_send_unicast_reply under high 
network load with CONFIG_PREEMPT_RT_FULL=y, reported by Sami Pietikainen 
<Sami.Pietikainen@wapice.com>, this patch adds local serialization in 
ip_send_unicast_reply.

from ip_output.c:
/*
 *      Generic function to send a packet as reply to another packet.
 *      Used to send some TCP resets/acks so far.
 *
 *      Use a fake percpu inet socket to avoid false sharing and contention.
 */
static DEFINE_PER_CPU(struct inet_sock, unicast_sock) = {
...

which was added in commit be9f4a44 in linux-stable. The git log, wich
introduced the PER_CPU unicast_sock, states:
<snip>
commit be9f4a44e7d41cee50ddb5f038fc2391cbbb4046
Author: Eric Dumazet <edumazet@google.com>
Date:   Thu Jul 19 07:34:03 2012 +0000

    ipv4: tcp: remove per net tcp_sock
    
    tcp_v4_send_reset() and tcp_v4_send_ack() use a single socket
    per network namespace.
    
    This leads to bad behavior on multiqueue NICS, because many cpus
    contend for the socket lock and once socket lock is acquired, extra
    false sharing on various socket fields slow down the operations.
    
    To better resist to attacks, we use a percpu socket. Each cpu can
    run without contention, using appropriate memory (local node)
<snip>

The per-cpu here thus is assuming exclusivity serializing per cpu - so 
the use of get_cpu_ligh introduced in 
net-use-cpu-light-in-ip-send-unicast-reply.patch, which droped the 
preempt_disable in favor of a migrate_disable is probably wrong as this 
only handles the referencial consistency but not the serialization. To
evade a preempt_disable here a local lock would be needed.

Therapie: 
 * add local lock: 
 * and re-introduce local serialization:
 
Tested on x86 with high network load using the testcase from Sami Pietikainen
  while : ; do wget -O - ftp://LOCAL_SERVER/empty_file > /dev/null 2>&1; done

Link: http://www.spinics.net/lists/linux-rt-users/msg11007.html
Signed-off-by: Nicholas Mc Guire <der.herr@hofr.at>
---
 net/ipv4/ip_output.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index e9fa68c..1e68f65 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -79,6 +79,7 @@
 #include <linux/mroute.h>
 #include <linux/netlink.h>
 #include <linux/tcp.h>
+#include <linux/locallock.h>
 
 int sysctl_ip_default_ttl __read_mostly = IPDEFTTL;
 EXPORT_SYMBOL(sysctl_ip_default_ttl);
@@ -1468,6 +1469,9 @@ static DEFINE_PER_CPU(struct inet_sock, unicast_sock) = {
 	.uc_ttl		= -1,
 };
 
+/* serialize concurrent calls on the same CPU to ip_send_unicast_reply */
+static DEFINE_LOCAL_IRQ_LOCK(unicast_lock);
+
 void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
 			   __be32 saddr, const struct ip_reply_arg *arg,
 			   unsigned int len)
@@ -1506,7 +1510,7 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
 		return;
 
 	get_cpu_light();
-	inet = &__get_cpu_var(unicast_sock);
+	inet = &get_locked_var(unicast_lock, unicast_sock);
 
 	inet->tos = arg->tos;
 	sk = &inet->sk;
@@ -1530,6 +1534,7 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
 		ip_push_pending_frames(sk, &fl4);
 	}
 
+	put_locked_var(unicast_lock, unicast_sock);
 	put_cpu_light();
 
 	ip_rt_put(rt);
-- 
1.7.2.5


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

* RE: [PATCH RT] add missing local serialization in ip_output.c
  2013-12-29 17:11 [PATCH RT] add missing local serialization in ip_output.c Nicholas Mc Guire
@ 2013-12-31  7:36 ` Jouko Haapaluoma
  2014-01-08  7:11   ` Sami Pietikäinen
  2014-01-17 14:47 ` Sebastian Andrzej Siewior
  1 sibling, 1 reply; 13+ messages in thread
From: Jouko Haapaluoma @ 2013-12-31  7:36 UTC (permalink / raw)
  To: Nicholas Mc Guire, linux-rt-users
  Cc: Sami Pietikäinen, Sebastian Andrzej Siewior, LKML,
	Thomas Gleixner, Steven Rostedt

Hi

I confirm that this patch works. Tested it overnight with Zedboard (Cortex A9). Thanks again!

BR,
Jouko

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

* RE: [PATCH RT] add missing local serialization in ip_output.c
  2013-12-31  7:36 ` Jouko Haapaluoma
@ 2014-01-08  7:11   ` Sami Pietikäinen
  0 siblings, 0 replies; 13+ messages in thread
From: Sami Pietikäinen @ 2014-01-08  7:11 UTC (permalink / raw)
  To: Jouko Haapaluoma, Nicholas Mc Guire, linux-rt-users
  Cc: Sebastian Andrzej Siewior, LKML, Thomas Gleixner, Steven Rostedt

Hello,

Patch also tested overnight with the Atmel SAMA5D35 evaluation board using
the same setup that originally produced the oops. No problems whatsoever.

BR,
Sami

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

* Re: [PATCH RT] add missing local serialization in ip_output.c
  2013-12-29 17:11 [PATCH RT] add missing local serialization in ip_output.c Nicholas Mc Guire
  2013-12-31  7:36 ` Jouko Haapaluoma
@ 2014-01-17 14:47 ` Sebastian Andrzej Siewior
  2014-01-17 14:59   ` Nicholas Mc Guire
  1 sibling, 1 reply; 13+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-01-17 14:47 UTC (permalink / raw)
  To: Nicholas Mc Guire
  Cc: linux-rt-users, Sami Pietikainen, Jouko Haapaluoma, LKML,
	Thomas Gleixner, Steven Rostedt

This is what I am going to apply. It also dropped the get_cpu_light()
call which was added in a patch to remove the get_cpu_var() and is now
no longer required since we have the get_locked_var() thingy now.

From: Nicholas Mc Guire <der.herr@hofr.at>
Date: Sun, 29 Dec 2013 18:11:54 +0100
Subject: [PATCH] net: ip_send_unicast_reply: add missing local serialization

in response to the oops in ip_output.c:ip_send_unicast_reply under high
network load with CONFIG_PREEMPT_RT_FULL=y, reported by Sami Pietikainen
<Sami.Pietikainen@wapice.com>, this patch adds local serialization in
ip_send_unicast_reply.

from ip_output.c:
/*
 *      Generic function to send a packet as reply to another packet.
 *      Used to send some TCP resets/acks so far.
 *
 *      Use a fake percpu inet socket to avoid false sharing and contention.
 */
static DEFINE_PER_CPU(struct inet_sock, unicast_sock) = {
...

which was added in commit be9f4a44 in linux-stable. The git log, wich
introduced the PER_CPU unicast_sock, states:
<snip>
commit be9f4a44e7d41cee50ddb5f038fc2391cbbb4046
Author: Eric Dumazet <edumazet@google.com>
Date:   Thu Jul 19 07:34:03 2012 +0000

    ipv4: tcp: remove per net tcp_sock

    tcp_v4_send_reset() and tcp_v4_send_ack() use a single socket
    per network namespace.

    This leads to bad behavior on multiqueue NICS, because many cpus
    contend for the socket lock and once socket lock is acquired, extra
    false sharing on various socket fields slow down the operations.

    To better resist to attacks, we use a percpu socket. Each cpu can
    run without contention, using appropriate memory (local node)
<snip>

The per-cpu here thus is assuming exclusivity serializing per cpu - so
the use of get_cpu_ligh introduced in
net-use-cpu-light-in-ip-send-unicast-reply.patch, which droped the
preempt_disable in favor of a migrate_disable is probably wrong as this
only handles the referencial consistency but not the serialization. To
evade a preempt_disable here a local lock would be needed.

Therapie:
 * add local lock:
 * and re-introduce local serialization:

Tested on x86 with high network load using the testcase from Sami Pietikainen
  while : ; do wget -O - ftp://LOCAL_SERVER/empty_file > /dev/null 2>&1; done

Link: http://www.spinics.net/lists/linux-rt-users/msg11007.html
Cc: stable-rt@vger.kernel.org
Signed-off-by: Nicholas Mc Guire <der.herr@hofr.at>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 net/ipv4/ip_output.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index e9fa68c..8bb3b4a 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -79,6 +79,7 @@
 #include <linux/mroute.h>
 #include <linux/netlink.h>
 #include <linux/tcp.h>
+#include <linux/locallock.h>
 
 int sysctl_ip_default_ttl __read_mostly = IPDEFTTL;
 EXPORT_SYMBOL(sysctl_ip_default_ttl);
@@ -1468,6 +1469,9 @@ static DEFINE_PER_CPU(struct inet_sock, unicast_sock) = {
 	.uc_ttl		= -1,
 };
 
+/* serialize concurrent calls on the same CPU to ip_send_unicast_reply */
+static DEFINE_LOCAL_IRQ_LOCK(unicast_lock);
+
 void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
 			   __be32 saddr, const struct ip_reply_arg *arg,
 			   unsigned int len)
@@ -1505,8 +1509,7 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
 	if (IS_ERR(rt))
 		return;
 
-	get_cpu_light();
-	inet = &__get_cpu_var(unicast_sock);
+	inet = &get_locked_var(unicast_lock, unicast_sock);
 
 	inet->tos = arg->tos;
 	sk = &inet->sk;
@@ -1530,7 +1533,7 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
 		ip_push_pending_frames(sk, &fl4);
 	}
 
-	put_cpu_light();
+	put_locked_var(unicast_lock, unicast_sock);
 
 	ip_rt_put(rt);
 }
-- 
1.8.5.2


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

* Re: [PATCH RT] add missing local serialization in ip_output.c
  2014-01-17 14:47 ` Sebastian Andrzej Siewior
@ 2014-01-17 14:59   ` Nicholas Mc Guire
  2014-01-17 15:13     ` Sebastian Andrzej Siewior
  0 siblings, 1 reply; 13+ messages in thread
From: Nicholas Mc Guire @ 2014-01-17 14:59 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-rt-users, Sami Pietikainen, Jouko Haapaluoma, LKML,
	Thomas Gleixner, Steven Rostedt

On Fri, 17 Jan 2014, Sebastian Andrzej Siewior wrote:

> This is what I am going to apply. It also dropped the get_cpu_light()
> call which was added in a patch to remove the get_cpu_var() and is now
> no longer required since we have the get_locked_var() thingy now.
>

I do not think you can drop that - what is preventing migration now ?

#define get_locked_var(lvar, var)                                       \
        (*({                                                            \
                local_lock(lvar);                                       \
                &__get_cpu_var(var);                                    \
        }))

No migrate_disable here - so how is this protected against migration ?
Note that I did send out mail on this because I believe get_locked_var
should actually be doing a a migrate_disable/enable but got no feedback on that
yet.

So for now I think you need to retain the get_cpu_light/put_cpu_light
   
thx!
hofrat
 
> From: Nicholas Mc Guire <der.herr@hofr.at>
> Date: Sun, 29 Dec 2013 18:11:54 +0100
> Subject: [PATCH] net: ip_send_unicast_reply: add missing local serialization
> 
> in response to the oops in ip_output.c:ip_send_unicast_reply under high
> network load with CONFIG_PREEMPT_RT_FULL=y, reported by Sami Pietikainen
> <Sami.Pietikainen@wapice.com>, this patch adds local serialization in
> ip_send_unicast_reply.
> 
> from ip_output.c:
> /*
>  *      Generic function to send a packet as reply to another packet.
>  *      Used to send some TCP resets/acks so far.
>  *
>  *      Use a fake percpu inet socket to avoid false sharing and contention.
>  */
> static DEFINE_PER_CPU(struct inet_sock, unicast_sock) = {
> ...
> 
> which was added in commit be9f4a44 in linux-stable. The git log, wich
> introduced the PER_CPU unicast_sock, states:
> <snip>
> commit be9f4a44e7d41cee50ddb5f038fc2391cbbb4046
> Author: Eric Dumazet <edumazet@google.com>
> Date:   Thu Jul 19 07:34:03 2012 +0000
> 
>     ipv4: tcp: remove per net tcp_sock
> 
>     tcp_v4_send_reset() and tcp_v4_send_ack() use a single socket
>     per network namespace.
> 
>     This leads to bad behavior on multiqueue NICS, because many cpus
>     contend for the socket lock and once socket lock is acquired, extra
>     false sharing on various socket fields slow down the operations.
> 
>     To better resist to attacks, we use a percpu socket. Each cpu can
>     run without contention, using appropriate memory (local node)
> <snip>
> 
> The per-cpu here thus is assuming exclusivity serializing per cpu - so
> the use of get_cpu_ligh introduced in
> net-use-cpu-light-in-ip-send-unicast-reply.patch, which droped the
> preempt_disable in favor of a migrate_disable is probably wrong as this
> only handles the referencial consistency but not the serialization. To
> evade a preempt_disable here a local lock would be needed.
> 
> Therapie:
>  * add local lock:
>  * and re-introduce local serialization:
> 
> Tested on x86 with high network load using the testcase from Sami Pietikainen
>   while : ; do wget -O - ftp://LOCAL_SERVER/empty_file > /dev/null 2>&1; done
> 
> Link: http://www.spinics.net/lists/linux-rt-users/msg11007.html
> Cc: stable-rt@vger.kernel.org
> Signed-off-by: Nicholas Mc Guire <der.herr@hofr.at>
> Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
> ---
>  net/ipv4/ip_output.c | 9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
> index e9fa68c..8bb3b4a 100644
> --- a/net/ipv4/ip_output.c
> +++ b/net/ipv4/ip_output.c
> @@ -79,6 +79,7 @@
>  #include <linux/mroute.h>
>  #include <linux/netlink.h>
>  #include <linux/tcp.h>
> +#include <linux/locallock.h>
>  
>  int sysctl_ip_default_ttl __read_mostly = IPDEFTTL;
>  EXPORT_SYMBOL(sysctl_ip_default_ttl);
> @@ -1468,6 +1469,9 @@ static DEFINE_PER_CPU(struct inet_sock, unicast_sock) = {
>  	.uc_ttl		= -1,
>  };
>  
> +/* serialize concurrent calls on the same CPU to ip_send_unicast_reply */
> +static DEFINE_LOCAL_IRQ_LOCK(unicast_lock);
> +
>  void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
>  			   __be32 saddr, const struct ip_reply_arg *arg,
>  			   unsigned int len)
> @@ -1505,8 +1509,7 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
>  	if (IS_ERR(rt))
>  		return;
>  
> -	get_cpu_light();
> -	inet = &__get_cpu_var(unicast_sock);
> +	inet = &get_locked_var(unicast_lock, unicast_sock);
>  
>  	inet->tos = arg->tos;
>  	sk = &inet->sk;
> @@ -1530,7 +1533,7 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr,
>  		ip_push_pending_frames(sk, &fl4);
>  	}
>  
> -	put_cpu_light();
> +	put_locked_var(unicast_lock, unicast_sock);
>  
>  	ip_rt_put(rt);
>  }
> -- 
> 1.8.5.2
> 

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

* Re: [PATCH RT] add missing local serialization in ip_output.c
  2014-01-17 14:59   ` Nicholas Mc Guire
@ 2014-01-17 15:13     ` Sebastian Andrzej Siewior
  2014-01-17 15:33       ` Nicholas Mc Guire
  0 siblings, 1 reply; 13+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-01-17 15:13 UTC (permalink / raw)
  To: Nicholas Mc Guire
  Cc: linux-rt-users, Sami Pietikainen, Jouko Haapaluoma, LKML,
	Thomas Gleixner, Steven Rostedt

On 01/17/2014 03:59 PM, Nicholas Mc Guire wrote:
> On Fri, 17 Jan 2014, Sebastian Andrzej Siewior wrote:
> 
>> This is what I am going to apply. It also dropped the get_cpu_light()
>> call which was added in a patch to remove the get_cpu_var() and is now
>> no longer required since we have the get_locked_var() thingy now.
>>
> 
> I do not think you can drop that - what is preventing migration now ?

Nothing but I do not see the need for it.

> 
> #define get_locked_var(lvar, var)                                       \
>         (*({                                                            \
>                 local_lock(lvar);                                       \
>                 &__get_cpu_var(var);                                    \
>         }))
> 
> No migrate_disable here - so how is this protected against migration ?

It does not. If you get here on CPU0, you the variable from CPU0. If
you get migrated to CPU1 you still use the variable from CPU0. If
another task is active on CPU0 then it will be blocked until the other
now running on CPU1 completes and releases the lock.

> Note that I did send out mail on this because I believe get_locked_var
> should actually be doing a a migrate_disable/enable but got no feedback on that
> yet.

I don't see a reason why you should not leave the CPU on which you got
access to the variable as long as you do not do any further assumption
regarding the CPU number. I don't see that this happens here.

> So for now I think you need to retain the get_cpu_light/put_cpu_light

Are you still sure?

>    
> thx!
> hofrat

Sebastian

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

* Re: [PATCH RT] add missing local serialization in ip_output.c
  2014-01-17 15:13     ` Sebastian Andrzej Siewior
@ 2014-01-17 15:33       ` Nicholas Mc Guire
  2014-01-17 16:32         ` Steven Rostedt
  0 siblings, 1 reply; 13+ messages in thread
From: Nicholas Mc Guire @ 2014-01-17 15:33 UTC (permalink / raw)
  To: Sebastian Andrzej Siewior
  Cc: linux-rt-users, Sami Pietikainen, Jouko Haapaluoma, LKML,
	Thomas Gleixner, Steven Rostedt

On Fri, 17 Jan 2014, Sebastian Andrzej Siewior wrote:

> On 01/17/2014 03:59 PM, Nicholas Mc Guire wrote:
> > On Fri, 17 Jan 2014, Sebastian Andrzej Siewior wrote:
> > 
> >> This is what I am going to apply. It also dropped the get_cpu_light()
> >> call which was added in a patch to remove the get_cpu_var() and is now
> >> no longer required since we have the get_locked_var() thingy now.
> >>
> > 
> > I do not think you can drop that - what is preventing migration now ?
> 
> Nothing but I do not see the need for it.
> 
> > 
> > #define get_locked_var(lvar, var)                                       \
> >         (*({                                                            \
> >                 local_lock(lvar);                                       \
> >                 &__get_cpu_var(var);                                    \
> >         }))
> > 
q> > No migrate_disable here - so how is this protected against migration ?
> 
> It does not. If you get here on CPU0, you the variable from CPU0. If
> you get migrated to CPU1 you still use the variable from CPU0. If
> another task is active on CPU0 then it will be blocked until the other
> now running on CPU1 completes and releases the lock.
> 
> > Note that I did send out mail on this because I believe get_locked_var
> > should actually be doing a a migrate_disable/enable but got no feedback on that
> > yet.
> 
> I don't see a reason why you should not leave the CPU on which you got
> access to the variable as long as you do not do any further assumption
> regarding the CPU number. I don't see that this happens here.
> 
> > So for now I think you need to retain the get_cpu_light/put_cpu_light
> 
> Are you still sure?
>
yes and no - it is needed I believe but it is actually already provided.
what I overlooked is that (actually my path-diagram was wrong - so
thanks for the catch):

#define get_locked_var(lvar, var)                                       \
        (*({                                                            \
                local_lock(lvar);                                       \
                &__get_cpu_var(var);                                    \
        }))
      ->#define local_lock(lvar)                                        \
        	do { __local_lock(&get_local_var(lvar)); } while (0)

                -> # define get_local_var(var) (*({                        \
        	       migrate_disable();                              \
        	       &__get_cpu_var(var); }))
                       -> #define __get_cpu_var(var) (*this_cpu_ptr(&(var)))

so its fine to drop the get_cpu_light/put_cpu_light as migration is
in fact already disabled at this point. the access to the local spinlock
object here is via this_cpu_ptr so if we would allow migration I think
you would end up unlocking the wrong lock.

thx!
hofrat

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

* Re: [PATCH RT] add missing local serialization in ip_output.c
  2014-01-17 15:33       ` Nicholas Mc Guire
@ 2014-01-17 16:32         ` Steven Rostedt
  2014-01-17 19:40           ` Nicholas Mc Guire
                             ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Steven Rostedt @ 2014-01-17 16:32 UTC (permalink / raw)
  To: Nicholas Mc Guire
  Cc: Sebastian Andrzej Siewior, linux-rt-users, Sami Pietikainen,
	Jouko Haapaluoma, LKML, Thomas Gleixner

On Fri, 17 Jan 2014 16:33:23 +0100
Nicholas Mc Guire <der.herr@hofr.at> wrote:

> On Fri, 17 Jan 2014, Sebastian Andrzej Siewior wrote:
> 
> > On 01/17/2014 03:59 PM, Nicholas Mc Guire wrote:
> > > On Fri, 17 Jan 2014, Sebastian Andrzej Siewior wrote:
> > > 
> > >> This is what I am going to apply. It also dropped the get_cpu_light()
> > >> call which was added in a patch to remove the get_cpu_var() and is now
> > >> no longer required since we have the get_locked_var() thingy now.
> > >>
> > > 
> > > I do not think you can drop that - what is preventing migration now ?
> > 
> > Nothing but I do not see the need for it.
> > 
> > > 
> > > #define get_locked_var(lvar, var)                                       \
> > >         (*({                                                            \
> > >                 local_lock(lvar);                                       \
> > >                 &__get_cpu_var(var);                                    \
> > >         }))
> > > 
> q> > No migrate_disable here - so how is this protected against migration ?

I was just about to reply to this, that local_lock() grabs a spinlock
which does do a migrate disable. But you also noticed that the
get_local_var() does a migrate disable too. We now have double the
protection, so we are safe as Sebastion has done it.

-- Steve

> > 
> > It does not. If you get here on CPU0, you the variable from CPU0. If
> > you get migrated to CPU1 you still use the variable from CPU0. If
> > another task is active on CPU0 then it will be blocked until the other
> > now running on CPU1 completes and releases the lock.
> > 
> > > Note that I did send out mail on this because I believe get_locked_var
> > > should actually be doing a a migrate_disable/enable but got no feedback on that
> > > yet.
> > 
> > I don't see a reason why you should not leave the CPU on which you got
> > access to the variable as long as you do not do any further assumption
> > regarding the CPU number. I don't see that this happens here.
> > 
> > > So for now I think you need to retain the get_cpu_light/put_cpu_light
> > 
> > Are you still sure?
> >
> yes and no - it is needed I believe but it is actually already provided.
> what I overlooked is that (actually my path-diagram was wrong - so
> thanks for the catch):
> 
> #define get_locked_var(lvar, var)                                       \
>         (*({                                                            \
>                 local_lock(lvar);                                       \
>                 &__get_cpu_var(var);                                    \
>         }))
>       ->#define local_lock(lvar)                                        \
>         	do { __local_lock(&get_local_var(lvar)); } while (0)
> 
>                 -> # define get_local_var(var) (*({                        \
>         	       migrate_disable();                              \
>         	       &__get_cpu_var(var); }))
>                        -> #define __get_cpu_var(var) (*this_cpu_ptr(&(var)))
> 
> so its fine to drop the get_cpu_light/put_cpu_light as migration is
> in fact already disabled at this point. the access to the local spinlock
> object here is via this_cpu_ptr so if we would allow migration I think
> you would end up unlocking the wrong lock.
> 
> thx!
> hofrat


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

* Re: [PATCH RT] add missing local serialization in ip_output.c
  2014-01-17 16:32         ` Steven Rostedt
@ 2014-01-17 19:40           ` Nicholas Mc Guire
  2014-01-17 19:41           ` [PATCH RT] use local spin_locks in local_lock Nicholas Mc Guire
  2014-01-17 19:44           ` [PATCH] API cleanup - use local_lock not __local_lock for soft Nicholas Mc Guire
  2 siblings, 0 replies; 13+ messages in thread
From: Nicholas Mc Guire @ 2014-01-17 19:40 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Sebastian Andrzej Siewior, linux-rt-users, Sami Pietikainen,
	Jouko Haapaluoma, LKML, Thomas Gleixner

On Fri, 17 Jan 2014, Steven Rostedt wrote:

> On Fri, 17 Jan 2014 16:33:23 +0100
> Nicholas Mc Guire <der.herr@hofr.at> wrote:
> 
> > On Fri, 17 Jan 2014, Sebastian Andrzej Siewior wrote:
> > 
> > > On 01/17/2014 03:59 PM, Nicholas Mc Guire wrote:
> > > > On Fri, 17 Jan 2014, Sebastian Andrzej Siewior wrote:
> > > > 
> > > >> This is what I am going to apply. It also dropped the get_cpu_light()
> > > >> call which was added in a patch to remove the get_cpu_var() and is now
> > > >> no longer required since we have the get_locked_var() thingy now.
> > > >>
> > > > 
> > > > I do not think you can drop that - what is preventing migration now ?
> > > 
> > > Nothing but I do not see the need for it.
> > > 
> > > > 
> > > > #define get_locked_var(lvar, var)                                       \
> > > >         (*({                                                            \
> > > >                 local_lock(lvar);                                       \
> > > >                 &__get_cpu_var(var);                                    \
> > > >         }))
> > > > 
> > q> > No migrate_disable here - so how is this protected against migration ?
> 
> I was just about to reply to this, that local_lock() grabs a spinlock
> which does do a migrate disable. But you also noticed that the
> get_local_var() does a migrate disable too. We now have double the
> protection, so we are safe as Sebastion has done it.
>
...well that motivates a further migration cleanup patch replacing
the spin_*lock* by spin_*lock*_local variants to drop that recursive call
and while checking call paths - do a little API cleanup for softirq_lock

thx!
hofrat

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

* [PATCH RT] use local spin_locks in local_lock
  2014-01-17 16:32         ` Steven Rostedt
  2014-01-17 19:40           ` Nicholas Mc Guire
@ 2014-01-17 19:41           ` Nicholas Mc Guire
  2014-01-31 20:24             ` Sebastian Andrzej Siewior
  2014-01-17 19:44           ` [PATCH] API cleanup - use local_lock not __local_lock for soft Nicholas Mc Guire
  2 siblings, 1 reply; 13+ messages in thread
From: Nicholas Mc Guire @ 2014-01-17 19:41 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Sebastian Andrzej Siewior, linux-rt-users, Sami Pietikainen,
	Jouko Haapaluoma, LKML, Thomas Gleixner


Drop recursive call to migrate_disabel/enable for local_*lock* api
reported by Steven Rostedt.

local_lock will call migrate_disable via get_local_var - call tree is

get_locked_var
 `-> local_lock(lvar)
       `-> __local_lock(&get_local_var(lvar));
                          `--> # define get_local_var(var) (*({     
                                    migrate_disable();              
                                    &__get_cpu_var(var); }))       \

thus there should be no need to call migrate_disable/enable recursively in 
spin_try/lock/unlock. This patch addes a spin_trylock_local and replaces
the migration disabling calls by the local calls.

This patch is incomplete as it does not yet cover the _irq/_irqsave variants
by local locks. This patch requires the API cleanup in kernel/softirq.c or
it would break softirq_lock/unlock with respect to migration.

on top of -rt9 with timers-do-not-raise-softirq-unconditionally.patch removed
and API-cleanup-use-local_lock-not-__local_lock-for-soft.patch applied.

Signed-off-by: Nicholas Mc Guire <der.herr@hofr.at>
---
 include/linux/locallock.h   |    8 ++++----
 include/linux/spinlock_rt.h |    1 +
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/include/linux/locallock.h b/include/linux/locallock.h
index e7bd8be..32c684b 100644
--- a/include/linux/locallock.h
+++ b/include/linux/locallock.h
@@ -39,7 +39,7 @@ struct local_irq_lock {
 static inline void __local_lock(struct local_irq_lock *lv)
 {
 	if (lv->owner != current) {
-		spin_lock(&lv->lock);
+		spin_lock_local(&lv->lock);
 		LL_WARN(lv->owner);
 		LL_WARN(lv->nestcnt);
 		lv->owner = current;
@@ -52,7 +52,7 @@ static inline void __local_lock(struct local_irq_lock *lv)
 
 static inline int __local_trylock(struct local_irq_lock *lv)
 {
-	if (lv->owner != current && spin_trylock(&lv->lock)) {
+	if (lv->owner != current && spin_trylock_local(&lv->lock)) {
 		LL_WARN(lv->owner);
 		LL_WARN(lv->nestcnt);
 		lv->owner = current;
@@ -79,7 +79,7 @@ static inline void __local_unlock(struct local_irq_lock *lv)
 		return;
 
 	lv->owner = NULL;
-	spin_unlock(&lv->lock);
+	spin_unlock_local(&lv->lock);
 }
 
 #define local_unlock(lvar)					\
@@ -211,7 +211,7 @@ static inline int __local_unlock_irqrestore(struct local_irq_lock *lv,
 		&__get_cpu_var(var);					\
 	}))
 
-#define put_locked_var(lvar, var)		local_unlock(lvar)
+#define put_locked_var(lvar, var)	local_unlock(lvar);
 
 #define local_lock_cpu(lvar)						\
 	({								\
diff --git a/include/linux/spinlock_rt.h b/include/linux/spinlock_rt.h
index b3c504b..4f91114 100644
--- a/include/linux/spinlock_rt.h
+++ b/include/linux/spinlock_rt.h
@@ -37,6 +37,7 @@ extern void __lockfunc __rt_spin_lock(struct rt_mutex *lock);
 extern void __lockfunc __rt_spin_unlock(struct rt_mutex *lock);
 
 #define spin_lock_local(lock)			rt_spin_lock(lock)
+#define spin_trylock_local(lock)		rt_spin_trylock(lock)
 #define spin_unlock_local(lock)			rt_spin_unlock(lock)
 
 #define spin_lock(lock)				\
-- 
1.7.2.5


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

* [PATCH] API cleanup - use local_lock not __local_lock for soft
  2014-01-17 16:32         ` Steven Rostedt
  2014-01-17 19:40           ` Nicholas Mc Guire
  2014-01-17 19:41           ` [PATCH RT] use local spin_locks in local_lock Nicholas Mc Guire
@ 2014-01-17 19:44           ` Nicholas Mc Guire
  2014-01-31 20:28             ` Sebastian Andrzej Siewior
  2 siblings, 1 reply; 13+ messages in thread
From: Nicholas Mc Guire @ 2014-01-17 19:44 UTC (permalink / raw)
  To: Steven Rostedt
  Cc: Sebastian Andrzej Siewior, linux-rt-users, Sami Pietikainen,
	Jouko Haapaluoma, LKML, Thomas Gleixner


trivial API cleanup - kernel/softirq.c was mimiking local_lock. 

No change of functional behavior

Signed-off-by: Nicholas Mc Guire <der.herr@hofr.at>
---
 kernel/softirq.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/softirq.c b/kernel/softirq.c
index 2da729b..15ad603 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -505,12 +505,12 @@ void __init softirq_early_init(void)
 
 static void lock_softirq(int which)
 {
-	__local_lock(&__get_cpu_var(local_softirq_locks[which]));
+	local_lock(local_softirq_locks[which]);
 }
 
 static void unlock_softirq(int which)
 {
-	__local_unlock(&__get_cpu_var(local_softirq_locks[which]));
+	local_unlock(local_softirq_locks[which]);
 }
 
 static void do_single_softirq(int which, int need_rcu_bh_qs)
-- 
1.7.2.5


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

* Re: [PATCH RT] use local spin_locks in local_lock
  2014-01-17 19:41           ` [PATCH RT] use local spin_locks in local_lock Nicholas Mc Guire
@ 2014-01-31 20:24             ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 13+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-01-31 20:24 UTC (permalink / raw)
  To: Nicholas Mc Guire
  Cc: Steven Rostedt, linux-rt-users, Sami Pietikainen,
	Jouko Haapaluoma, LKML, Thomas Gleixner

* Nicholas Mc Guire | 2014-01-17 20:41:58 [+0100]:

>
>Drop recursive call to migrate_disabel/enable for local_*lock* api
>reported by Steven Rostedt.

Applied.

Sebastian

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

* Re: [PATCH] API cleanup - use local_lock not __local_lock for soft
  2014-01-17 19:44           ` [PATCH] API cleanup - use local_lock not __local_lock for soft Nicholas Mc Guire
@ 2014-01-31 20:28             ` Sebastian Andrzej Siewior
  0 siblings, 0 replies; 13+ messages in thread
From: Sebastian Andrzej Siewior @ 2014-01-31 20:28 UTC (permalink / raw)
  To: Nicholas Mc Guire
  Cc: Steven Rostedt, linux-rt-users, Sami Pietikainen,
	Jouko Haapaluoma, LKML, Thomas Gleixner

* Nicholas Mc Guire | 2014-01-17 20:44:03 [+0100]:

>
>trivial API cleanup - kernel/softirq.c was mimiking local_lock. 

Applied

Sebastian

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

end of thread, other threads:[~2014-01-31 20:28 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-29 17:11 [PATCH RT] add missing local serialization in ip_output.c Nicholas Mc Guire
2013-12-31  7:36 ` Jouko Haapaluoma
2014-01-08  7:11   ` Sami Pietikäinen
2014-01-17 14:47 ` Sebastian Andrzej Siewior
2014-01-17 14:59   ` Nicholas Mc Guire
2014-01-17 15:13     ` Sebastian Andrzej Siewior
2014-01-17 15:33       ` Nicholas Mc Guire
2014-01-17 16:32         ` Steven Rostedt
2014-01-17 19:40           ` Nicholas Mc Guire
2014-01-17 19:41           ` [PATCH RT] use local spin_locks in local_lock Nicholas Mc Guire
2014-01-31 20:24             ` Sebastian Andrzej Siewior
2014-01-17 19:44           ` [PATCH] API cleanup - use local_lock not __local_lock for soft Nicholas Mc Guire
2014-01-31 20:28             ` Sebastian Andrzej Siewior

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