[PATCH] rcu: keep rcu callback event counter
authorEric Dumazet <dada1@cosmosbay.com>
Mon, 17 Oct 2005 18:01:21 +0000 (20:01 +0200)
committerLinus Torvalds <torvalds@g5.osdl.org>
Mon, 17 Oct 2005 22:27:58 +0000 (15:27 -0700)
This makes call_rcu() keep track of how many events there are on the RCU
list, and cause a reschedule event when the list gets too long.

This helps keep RCU event lists down.

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
include/linux/rcupdate.h
kernel/rcupdate.c

index 4e65eb44adfd0914e66b461cceea6356eeb2458f..70191a5a148f560caf5ba08d4fcb7109ea6fb860 100644 (file)
@@ -94,6 +94,7 @@ struct rcu_data {
        long            batch;           /* Batch # for current RCU batch */
        struct rcu_head *nxtlist;
        struct rcu_head **nxttail;
        long            batch;           /* Batch # for current RCU batch */
        struct rcu_head *nxtlist;
        struct rcu_head **nxttail;
+       long            count; /* # of queued items */
        struct rcu_head *curlist;
        struct rcu_head **curtail;
        struct rcu_head *donelist;
        struct rcu_head *curlist;
        struct rcu_head **curtail;
        struct rcu_head *donelist;
index dd99415b1551b12d9421e7bdf738bbb7ae74002e..2559d4b8f23f6ef005db9825952afa0936d22951 100644 (file)
@@ -109,6 +109,10 @@ void fastcall call_rcu(struct rcu_head *head,
        rdp = &__get_cpu_var(rcu_data);
        *rdp->nxttail = head;
        rdp->nxttail = &head->next;
        rdp = &__get_cpu_var(rcu_data);
        *rdp->nxttail = head;
        rdp->nxttail = &head->next;
+
+       if (unlikely(++rdp->count > 10000))
+               set_need_resched();
+
        local_irq_restore(flags);
 }
 
        local_irq_restore(flags);
 }
 
@@ -140,6 +144,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 = &__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);
+ */
        local_irq_restore(flags);
 }
 
        local_irq_restore(flags);
 }
 
@@ -157,6 +167,7 @@ static void rcu_do_batch(struct rcu_data *rdp)
                next = rdp->donelist = list->next;
                list->func(list);
                list = next;
                next = rdp->donelist = list->next;
                list->func(list);
                list = next;
+               rdp->count--;
                if (++count >= maxbatch)
                        break;
        }
                if (++count >= maxbatch)
                        break;
        }