]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/rcupdate.c
[PATCH] fbdev: nvidiafb: Driver cleanup
[linux-2.6-omap-h63xx.git] / kernel / rcupdate.c
index 48d3bce465b88e38b0715a46a5b7fe8c95820c2d..05ee48316f70097f386e9edefe9962a5d66ec51c 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/smp.h>
+#include <linux/rcupdate.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
 #include <asm/atomic.h>
@@ -45,7 +46,6 @@
 #include <linux/percpu.h>
 #include <linux/notifier.h>
 #include <linux/rcupdate.h>
-#include <linux/rcuref.h>
 #include <linux/cpu.h>
 
 /* Definition for rcupdate control block. */
@@ -61,9 +61,9 @@ struct rcu_state {
                                      /* for current batch to proceed.        */
 };
 
-static struct rcu_state rcu_state ____cacheline_maxaligned_in_smp =
+static struct rcu_state rcu_state ____cacheline_internodealigned_in_smp =
          {.lock = SPIN_LOCK_UNLOCKED, .cpumask = CPU_MASK_NONE };
-static struct rcu_state rcu_bh_state ____cacheline_maxaligned_in_smp =
+static struct rcu_state rcu_bh_state ____cacheline_internodealigned_in_smp =
          {.lock = SPIN_LOCK_UNLOCKED, .cpumask = CPU_MASK_NONE };
 
 DEFINE_PER_CPU(struct rcu_data, rcu_data) = { 0L };
@@ -73,19 +73,6 @@ DEFINE_PER_CPU(struct rcu_data, rcu_bh_data) = { 0L };
 static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL};
 static int maxbatch = 10000;
 
-#ifndef __HAVE_ARCH_CMPXCHG
-/*
- * We use an array of spinlocks for the rcurefs -- similar to ones in sparc
- * 32 bit atomic_t implementations, and a hash function similar to that
- * for our refcounting needs.
- * Can't help multiprocessors which donot have cmpxchg :(
- */
-
-spinlock_t __rcuref_hash[RCUREF_HASH_SIZE] = {
-       [0 ... (RCUREF_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED
-};
-#endif
-
 /**
  * call_rcu - Queue an RCU callback for invocation after a grace period.
  * @head: structure to be used for queueing the RCU updates.
@@ -249,12 +236,8 @@ static void rcu_do_batch(struct rcu_data *rdp)
  * active batch and the batch to be registered has not already occurred.
  * Caller must hold rcu_state.lock.
  */
-static void rcu_start_batch(struct rcu_ctrlblk *rcp, struct rcu_state *rsp,
-                               int next_pending)
+static void rcu_start_batch(struct rcu_ctrlblk *rcp, struct rcu_state *rsp)
 {
-       if (next_pending)
-               rcp->next_pending = 1;
-
        if (rcp->next_pending &&
                        rcp->completed == rcp->cur) {
                rcp->next_pending = 0;
@@ -288,7 +271,7 @@ static void cpu_quiet(int cpu, struct rcu_ctrlblk *rcp, struct rcu_state *rsp)
        if (cpus_empty(rsp->cpumask)) {
                /* batch completed ! */
                rcp->completed = rcp->cur;
-               rcu_start_batch(rcp, rsp, 0);
+               rcu_start_batch(rcp, rsp);
        }
 }
 
@@ -423,7 +406,8 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp,
                if (!rcp->next_pending) {
                        /* and start it/schedule start if it's a new batch */
                        spin_lock(&rsp->lock);
-                       rcu_start_batch(rcp, rsp, 1);
+                       rcp->next_pending = 1;
+                       rcu_start_batch(rcp, rsp);
                        spin_unlock(&rsp->lock);
                }
        } else {
@@ -442,6 +426,36 @@ static void rcu_process_callbacks(unsigned long unused)
                                &__get_cpu_var(rcu_bh_data));
 }
 
+static int __rcu_pending(struct rcu_ctrlblk *rcp, struct rcu_data *rdp)
+{
+       /* This cpu has pending rcu entries and the grace period
+        * for them has completed.
+        */
+       if (rdp->curlist && !rcu_batch_before(rcp->completed, rdp->batch))
+               return 1;
+
+       /* This cpu has no pending entries, but there are new entries */
+       if (!rdp->curlist && rdp->nxtlist)
+               return 1;
+
+       /* This cpu has finished callbacks to invoke */
+       if (rdp->donelist)
+               return 1;
+
+       /* The rcu core waits for a quiescent state from the cpu */
+       if (rdp->quiescbatch != rcp->cur || rdp->qs_pending)
+               return 1;
+
+       /* nothing to do */
+       return 0;
+}
+
+int rcu_pending(int cpu)
+{
+       return __rcu_pending(&rcu_ctrlblk, &per_cpu(rcu_data, cpu)) ||
+               __rcu_pending(&rcu_bh_ctrlblk, &per_cpu(rcu_bh_data, cpu));
+}
+
 void rcu_check_callbacks(int cpu, int user)
 {
        if (user ||