--- linux-2.6.15/kernel/rcupdate.c 2006-01-03 04:21:10.000000000 +0100 +++ linux-2.6.15-edum/kernel/rcupdate.c 2006-01-06 11:10:45.000000000 +0100 @@ -71,14 +71,14 @@ /* Fake initialization required by compiler */ static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL}; -static int maxbatch = 10000; +static int maxbatch = 100; #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 :( + * Can't help multiprocessors which dont have cmpxchg :( */ spinlock_t __rcuref_hash[RCUREF_HASH_SIZE] = { @@ -110,9 +110,17 @@ *rdp->nxttail = head; rdp->nxttail = &head->next; - if (unlikely(++rdp->count > 10000)) - set_need_resched(); - +/* + * OOM avoidance : If we queued too many items in this queue, + * free the oldest entry + */ + if (unlikely(++rdp->count > 10000)) { + rdp->count--; + head = rdp->donelist; + rdp->donelist = head->next; + local_irq_restore(flags); + return head->func(head); + } local_irq_restore(flags); } @@ -148,12 +156,17 @@ 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); + * OOM avoidance : If we queued too many items in this queue, + * free the oldest entry */ + if (unlikely(++rdp->count > 10000)) { + rdp->count--; + head = rdp->donelist; + rdp->donelist = head->next; + local_irq_restore(flags); + return head->func(head); + } local_irq_restore(flags); } @@ -209,7 +222,7 @@ static void rcu_do_batch(struct rcu_data *rdp) { struct rcu_head *next, *list; - int count = 0; + int count = maxbatch; list = rdp->donelist; while (list) { @@ -217,7 +230,7 @@ list->func(list); list = next; rdp->count--; - if (++count >= maxbatch) + if (--count <= 0) break; } if (!rdp->donelist)