diff options
| author | Steve French <sfrench@us.ibm.com> | 2006-03-20 16:58:09 +0000 | 
|---|---|---|
| committer | Steve French <sfrench@us.ibm.com> | 2006-03-20 16:58:09 +0000 | 
| commit | fd4a0b92db6a57cba8d03efbe1cebf91f9124ce0 (patch) | |
| tree | 5886a08bfa1132058b06074f4666a36dc5ddd2a1 /kernel/rcupdate.c | |
| parent | 88274815f7477dc7550439413ab87c5ce4c5a623 (diff) | |
| parent | 7705a8792b0fc82fd7d4dd923724606bbfd9fb20 (diff) | |
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'kernel/rcupdate.c')
| -rw-r--r-- | kernel/rcupdate.c | 76 | 
1 files changed, 58 insertions, 18 deletions
| diff --git a/kernel/rcupdate.c b/kernel/rcupdate.c index 0cf8146bd58..8cf15a569fc 100644 --- a/kernel/rcupdate.c +++ b/kernel/rcupdate.c @@ -67,7 +67,43 @@ DEFINE_PER_CPU(struct rcu_data, rcu_bh_data) = { 0L };  /* Fake initialization required by compiler */  static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL}; -static int maxbatch = 10000; +static int blimit = 10; +static int qhimark = 10000; +static int qlowmark = 100; +#ifdef CONFIG_SMP +static int rsinterval = 1000; +#endif + +static atomic_t rcu_barrier_cpu_count; +static struct semaphore rcu_barrier_sema; +static struct completion rcu_barrier_completion; + +#ifdef CONFIG_SMP +static void force_quiescent_state(struct rcu_data *rdp, +			struct rcu_ctrlblk *rcp) +{ +	int cpu; +	cpumask_t cpumask; +	set_need_resched(); +	if (unlikely(rdp->qlen - rdp->last_rs_qlen > rsinterval)) { +		rdp->last_rs_qlen = rdp->qlen; +		/* +		 * Don't send IPI to itself. With irqs disabled, +		 * rdp->cpu is the current cpu. +		 */ +		cpumask = rcp->cpumask; +		cpu_clear(rdp->cpu, cpumask); +		for_each_cpu_mask(cpu, cpumask) +			smp_send_reschedule(cpu); +	} +} +#else +static inline void force_quiescent_state(struct rcu_data *rdp, +			struct rcu_ctrlblk *rcp) +{ +	set_need_resched(); +} +#endif  /**   * call_rcu - Queue an RCU callback for invocation after a grace period. @@ -92,17 +128,13 @@ void fastcall call_rcu(struct rcu_head *head,  	rdp = &__get_cpu_var(rcu_data);  	*rdp->nxttail = head;  	rdp->nxttail = &head->next; - -	if (unlikely(++rdp->count > 10000)) -		set_need_resched(); - +	if (unlikely(++rdp->qlen > qhimark)) { +		rdp->blimit = INT_MAX; +		force_quiescent_state(rdp, &rcu_ctrlblk); +	}  	local_irq_restore(flags);  } -static atomic_t rcu_barrier_cpu_count; -static struct semaphore rcu_barrier_sema; -static struct completion rcu_barrier_completion; -  /**   * call_rcu_bh - Queue an RCU for invocation after a quicker grace period.   * @head: structure to be used for queueing the RCU updates. @@ -131,12 +163,12 @@ void fastcall call_rcu_bh(struct rcu_head *head,  	rdp = &__get_cpu_var(rcu_bh_data);  	*rdp->nxttail = head;  	rdp->nxttail = &head->next; -	rdp->count++; -/* - *  Should we directly call rcu_do_batch() here ? - *  if (unlikely(rdp->count > 10000)) - *      rcu_do_batch(rdp); - */ + +	if (unlikely(++rdp->qlen > qhimark)) { +		rdp->blimit = INT_MAX; +		force_quiescent_state(rdp, &rcu_bh_ctrlblk); +	} +  	local_irq_restore(flags);  } @@ -199,10 +231,12 @@ static void rcu_do_batch(struct rcu_data *rdp)  		next = rdp->donelist = list->next;  		list->func(list);  		list = next; -		rdp->count--; -		if (++count >= maxbatch) +		rdp->qlen--; +		if (++count >= rdp->blimit)  			break;  	} +	if (rdp->blimit == INT_MAX && rdp->qlen <= qlowmark) +		rdp->blimit = blimit;  	if (!rdp->donelist)  		rdp->donetail = &rdp->donelist;  	else @@ -473,6 +507,7 @@ static void rcu_init_percpu_data(int cpu, struct rcu_ctrlblk *rcp,  	rdp->quiescbatch = rcp->completed;  	rdp->qs_pending = 0;  	rdp->cpu = cpu; +	rdp->blimit = blimit;  }  static void __devinit rcu_online_cpu(int cpu) @@ -567,7 +602,12 @@ void synchronize_kernel(void)  	synchronize_rcu();  } -module_param(maxbatch, int, 0); +module_param(blimit, int, 0); +module_param(qhimark, int, 0); +module_param(qlowmark, int, 0); +#ifdef CONFIG_SMP +module_param(rsinterval, int, 0); +#endif  EXPORT_SYMBOL_GPL(rcu_batches_completed);  EXPORT_SYMBOL(call_rcu);  /* WARNING: GPL-only in April 2006. */  EXPORT_SYMBOL(call_rcu_bh);  /* WARNING: GPL-only in April 2006. */ | 
