linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
To: Sebastien Dugue <sebastien.dugue@bull.net>
Cc: dwalker@mvista.com, tinytim@us.ibm.com,
	linux-rt-users@vger.kernel.org, linux-kernel@vger.kernel.org,
	rostedt@goodmis.org, jean-pierre.dion@bull.net,
	linuxppc-dev@ozlabs.org, paulus@samba.org,
	gilles.carry@ext.bull.net, tglx@linutronix.de
Subject: Re: [PATCH 2/2] powerpc - Make the irq reverse mapping radix tree lockless
Date: Wed, 20 Aug 2008 15:22:06 +1000	[thread overview]
Message-ID: <1219209726.21386.23.camel@pasglop> (raw)
In-Reply-To: <1218029429-21114-3-git-send-email-sebastien.dugue@bull.net>

On Wed, 2008-08-06 at 15:30 +0200, Sebastien Dugue wrote:
> The radix trees used by interrupt controllers for their irq reverse mapping
> (currently only the XICS found on pSeries) have a complex locking scheme
> dating back to before the advent of the lockless radix tree.
> 
>   Take advantage of this and of the fact that the items of the tree are
> pointers to a static array (irq_map) elements which can never go under us
> to simplify the locking.
> 
>   Concurrency between readers and writers is handled by the intrinsic
> properties of the lockless radix tree. Concurrency between writers is handled
> with a spinlock added to the irq_host structure.

No need for a spinlock in the irq_host. Make it one global lock, it's
not like scalability of irq_create_mapping() was a big deal and there's
usually only one of those type of hosts anyway.

> 
> Signed-off-by: Sebastien Dugue <sebastien.dugue@bull.net>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Michael Ellerman <michael@ellerman.id.au>
> ---
>  arch/powerpc/include/asm/irq.h |    1 +
>  arch/powerpc/kernel/irq.c      |   74 ++++++----------------------------------
>  2 files changed, 12 insertions(+), 63 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h
> index 0a51376..72fd036 100644
> --- a/arch/powerpc/include/asm/irq.h
> +++ b/arch/powerpc/include/asm/irq.h
> @@ -119,6 +119,7 @@ struct irq_host {
>  		} linear;
>  		struct radix_tree_root tree;
>  	} revmap_data;
> +	spinlock_t		tree_lock;
>  	struct irq_host_ops	*ops;
>  	void			*host_data;
>  	irq_hw_number_t		inval_irq;
> diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
> index dc8663a..7a19103 100644
> --- a/arch/powerpc/kernel/irq.c
> +++ b/arch/powerpc/kernel/irq.c
> @@ -439,8 +439,6 @@ void do_softirq(void)
>  
>  static LIST_HEAD(irq_hosts);
>  static DEFINE_SPINLOCK(irq_big_lock);
> -static DEFINE_PER_CPU(unsigned int, irq_radix_reader);
> -static unsigned int irq_radix_writer;
>  static atomic_t revmap_trees_allocated = ATOMIC_INIT(0);
>  struct irq_map_entry irq_map[NR_IRQS];
>  static unsigned int irq_virq_count = NR_IRQS;
> @@ -584,57 +582,6 @@ void irq_set_virq_count(unsigned int count)
>  		irq_virq_count = count;
>  }
>  
> -/* radix tree not lockless safe ! we use a brlock-type mecanism
> - * for now, until we can use a lockless radix tree
> - */
> -static void irq_radix_wrlock(unsigned long *flags)
> -{
> -	unsigned int cpu, ok;
> -
> -	spin_lock_irqsave(&irq_big_lock, *flags);
> -	irq_radix_writer = 1;
> -	smp_mb();
> -	do {
> -		barrier();
> -		ok = 1;
> -		for_each_possible_cpu(cpu) {
> -			if (per_cpu(irq_radix_reader, cpu)) {
> -				ok = 0;
> -				break;
> -			}
> -		}
> -		if (!ok)
> -			cpu_relax();
> -	} while(!ok);
> -}
> -
> -static void irq_radix_wrunlock(unsigned long flags)
> -{
> -	smp_wmb();
> -	irq_radix_writer = 0;
> -	spin_unlock_irqrestore(&irq_big_lock, flags);
> -}
> -
> -static void irq_radix_rdlock(unsigned long *flags)
> -{
> -	local_irq_save(*flags);
> -	__get_cpu_var(irq_radix_reader) = 1;
> -	smp_mb();
> -	if (likely(irq_radix_writer == 0))
> -		return;
> -	__get_cpu_var(irq_radix_reader) = 0;
> -	smp_wmb();
> -	spin_lock(&irq_big_lock);
> -	__get_cpu_var(irq_radix_reader) = 1;
> -	spin_unlock(&irq_big_lock);
> -}
> -
> -static void irq_radix_rdunlock(unsigned long flags)
> -{
> -	__get_cpu_var(irq_radix_reader) = 0;
> -	local_irq_restore(flags);
> -}
> -
>  static int irq_setup_virq(struct irq_host *host, unsigned int virq,
>  			    irq_hw_number_t hwirq)
>  {
> @@ -789,7 +736,6 @@ void irq_dispose_mapping(unsigned int virq)
>  {
>  	struct irq_host *host;
>  	irq_hw_number_t hwirq;
> -	unsigned long flags;
>  
>  	if (virq == NO_IRQ)
>  		return;
> @@ -825,9 +771,9 @@ void irq_dispose_mapping(unsigned int virq)
>  		/* Check if radix tree allocated yet */
>  		if (atomic_read(&revmap_trees_allocated) == 0)
>  			break;
> -		irq_radix_wrlock(&flags);
> +		spin_lock(&host->tree_lock);
>  		radix_tree_delete(&host->revmap_data.tree, hwirq);
> -		irq_radix_wrunlock(flags);
> +		spin_unlock(&host->tree_lock);
>  		break;
>  	}
>  
> @@ -881,7 +827,6 @@ unsigned int irq_radix_revmap_lookup(struct irq_host *host,
>  {
>  	struct irq_map_entry *ptr;
>  	unsigned int virq = NO_IRQ;
> -	unsigned long flags;
>  
>  	WARN_ON(host->revmap_type != IRQ_HOST_MAP_TREE);
>  
> @@ -893,9 +838,11 @@ unsigned int irq_radix_revmap_lookup(struct irq_host *host,
>  		return irq_find_mapping(host, hwirq);
>  
>  	/* Now try to resolve */
> -	irq_radix_rdlock(&flags);
> +	/*
> +	 * No rcu_read_lock(ing) needed, the ptr returned can't go under us
> +	 * as it's referencing an entry in the static irq_map table.
> +	 */
>  	ptr = radix_tree_lookup(&host->revmap_data.tree, hwirq);
> -	irq_radix_rdunlock(flags);
>  
>  	/* Found it, return */
>  	if (ptr)
> @@ -907,7 +854,6 @@ unsigned int irq_radix_revmap_lookup(struct irq_host *host,
>  void irq_radix_revmap_insert(struct irq_host *host, unsigned int virq,
>  			     irq_hw_number_t hwirq)
>  {
> -	unsigned long flags;
>  
>  	WARN_ON(host->revmap_type != IRQ_HOST_MAP_TREE);
>  
> @@ -920,10 +866,10 @@ void irq_radix_revmap_insert(struct irq_host *host, unsigned int virq,
>  		return;
>  
>  	if (virq != NO_IRQ) {
> -		irq_radix_wrlock(&flags);
> +		spin_lock(&host->tree_lock);
>  		radix_tree_insert(&host->revmap_data.tree, hwirq,
>  				  &irq_map[virq]);
> -		irq_radix_wrunlock(flags);
> +		spin_unlock(&host->tree_lock);
>  	}
>  }
>  
> @@ -1041,8 +987,10 @@ static int irq_late_init(void)
>  	 * revmap_trees_allocated.
>  	 */
>  	list_for_each_entry(h, &irq_hosts, link) {
> -		if (h->revmap_type == IRQ_HOST_MAP_TREE)
> +		if (h->revmap_type == IRQ_HOST_MAP_TREE) {
>  			INIT_RADIX_TREE(&h->revmap_data.tree, GFP_ATOMIC);
> +			spin_lock_init(&h->tree_lock);
> +		}
>  	}
>  
>  	/*

  reply	other threads:[~2008-08-20  5:25 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-06 13:30 [PATCH 0/2 V3] powerpc - Make the irq reverse mapping tree lockless Sebastien Dugue
2008-08-06 13:30 ` [PATCH 1/2] powerpc - Separate the irq radix tree insertion and lookup Sebastien Dugue
2008-08-20  5:21   ` Benjamin Herrenschmidt
2008-09-03 13:34     ` Sebastien Dugue
2008-08-06 13:30 ` [PATCH 2/2] powerpc - Make the irq reverse mapping radix tree lockless Sebastien Dugue
2008-08-20  5:22   ` Benjamin Herrenschmidt [this message]
2008-09-03 13:34     ` Sebastien Dugue
2008-08-20  5:23   ` Benjamin Herrenschmidt
2008-09-03 13:41     ` Sebastien Dugue
2008-09-04  2:52       ` Benjamin Herrenschmidt
2008-09-04  7:22         ` Sebastien Dugue
2008-09-04  7:34           ` Benjamin Herrenschmidt
2008-09-04  7:55             ` Sebastien Dugue
2008-09-04  7:58               ` Benjamin Herrenschmidt
2008-09-04  8:04                 ` Sebastien Dugue
  -- strict thread matches above, loose matches on Subject: below --
2008-09-04 12:37 [PATCH 0/2 V4] powerpc - Make the irq reverse mapping " Sebastien Dugue
2008-09-04 12:37 ` [PATCH 2/2] powerpc - Make the irq reverse mapping radix " Sebastien Dugue

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=1219209726.21386.23.camel@pasglop \
    --to=benh@kernel.crashing.org \
    --cc=dwalker@mvista.com \
    --cc=gilles.carry@ext.bull.net \
    --cc=jean-pierre.dion@bull.net \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-rt-users@vger.kernel.org \
    --cc=linuxppc-dev@ozlabs.org \
    --cc=paulus@samba.org \
    --cc=rostedt@goodmis.org \
    --cc=sebastien.dugue@bull.net \
    --cc=tglx@linutronix.de \
    --cc=tinytim@us.ibm.com \
    /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).