Skip to contentSkip to conversation

RCU for low latency (experimental)

PATCH In review Dipankar Sarma 6 participants 28 messages Mar 23, 2004 – Mar 29, 2004

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 RCU for low latency (experimental)

Here is the RCU patch for low scheduling latency Andrew was talking about in the other thread. I had done some measurements with amlat on a 2.4 GHz P4 xeon box with 256MB memory running dbench and it reduced worst case scheduling latencies from 800 microseconds to about 400 microseconds.

It uses per-cpu kernel threads to execute excess callbacks and pretty much relies on preemption. I added a CONFIG_LOW_LATENCY option to make this conditional. The amount of callbacks to invoke in softirq before punting to krcud can be set at boot time using rcupdate.bhlimit parameter. The whole thing is meant for experimenting only. The negative side of doing RCU this way is that we may further delay the grace period with the RCU kernel thread and thus there can be OOM situations.

I would be interested in all issues with this patch including latencies and OOM situations.

Dipankar

Reduce bh processing time of rcu callbacks by using tunable per-cpu krcud daemeons.

 include/linux/rcupdate.h |    4 ++
 include/linux/sched.h    |    1 
 init/Kconfig             |    9 ++++
 kernel/rcupdate.c        |   91 +++++++++++++++++++++++++++++++++++++++++++++--
 kernel/sched.c           |    6 +++
 5 files changed, 108 insertions(+), 3 deletions(-)
include/linux/rcupdate.h renamed from include/linux/rcupdate.h~rcu-low-lat +4 -0
diff -puN include/linux/rcupdate.h~rcu-low-lat include/linux/rcupdate.h
@@ -93,9 +93,11 @@ struct rcu_data {
 	long		qsctr;		 /* User-mode/idle loop etc. */
         long            last_qsctr;	 /* value of qsctr at beginning */
                                          /* of rcu grace period */
+	struct task_struct *krcud;
         long  	       	batch;           /* Batch # for current RCU batch */
         struct list_head  nxtlist;
         struct list_head  curlist;
+        struct list_head  rcudlist;
 };
 
 DECLARE_PER_CPU(struct rcu_data, rcu_data);
@@ -103,9 +105,11 @@ extern struct rcu_ctrlblk rcu_ctrlblk;
 
 #define RCU_qsctr(cpu) 		(per_cpu(rcu_data, (cpu)).qsctr)
 #define RCU_last_qsctr(cpu) 	(per_cpu(rcu_data, (cpu)).last_qsctr)
+#define RCU_krcud(cpu) 		(per_cpu(rcu_data, (cpu)).krcud)
 #define RCU_batch(cpu) 		(per_cpu(rcu_data, (cpu)).batch)
 #define RCU_nxtlist(cpu) 	(per_cpu(rcu_data, (cpu)).nxtlist)
 #define RCU_curlist(cpu) 	(per_cpu(rcu_data, (cpu)).curlist)
+#define RCU_rcudlist(cpu) 	(per_cpu(rcu_data, (cpu)).rcudlist)
 
 #define RCU_QSCTR_INVALID	0
 
include/linux/sched.h renamed from include/linux/sched.h~rcu-low-lat +1 -0
diff -puN include/linux/sched.h~rcu-low-lat include/linux/sched.h
@@ -552,6 +552,7 @@ extern int task_prio(task_t *p);
 extern int task_nice(task_t *p);
 extern int task_curr(task_t *p);
 extern int idle_cpu(int cpu);
+extern int rq_has_rt_task(int cpu);
 
 void yield(void);
 
init/Kconfig renamed from init/Kconfig~rcu-low-lat +8 -1
diff -puN init/Kconfig~rcu-low-lat init/Kconfig
@@ -156,6 +156,14 @@ config HOTPLUG
 	  agent" (/sbin/hotplug) to load modules and set up software needed
 	  to use devices as you hotplug them.
 
+config LOW_LATENCY
+	 bool "Enable kernel features for low scheduling latency" if EXPERIMENTAL
+	 default n
+	---help---
+	   This option enables various features in the kernel that
+	   help reduce scheduling latency while potentially sacrificing
+	   throughput.
+
 config IKCONFIG
 	bool "Kernel .config support"
 	---help---
@@ -181,7 +189,6 @@ config IKCONFIG_PROC
 	  This option enables access to kernel configuration file and build
 	  information through /proc/config.gz.
 
-
 menuconfig EMBEDDED
 	bool "Remove kernel features (for embedded systems)"
 	help
kernel/rcupdate.c renamed from kernel/rcupdate.c~rcu-low-lat +89 -2

156 lines not on this page · raw message

kernel/sched.c renamed from kernel/sched.c~rcu-low-lat +6 -0
diff -puN kernel/sched.c~rcu-low-lat kernel/sched.c
@@ -341,6 +341,12 @@ static inline void enqueue_task(struct t
 	p->array = array;
 }
 
+int rq_has_rt_task(int cpu)
+{
+        runqueue_t *rq = cpu_rq(cpu);
+        return (sched_find_first_bit(rq->active->bitmap) < MAX_RT_PRIO);
+}
+
 /*
  * effective_prio - return the priority that is based on the static
  * priority but is modified by bonuses/penalties.

_

#1 lore raw
Quoted 9 lines · Dipankar Sarma

Here is the RCU patch for low scheduling latency Andrew was talking about in the other thread. I had done some measurements with amlat on a 2.4 GHz P4 xeon box with 256MB memory running dbench and it reduced worst case scheduling latencies from 800 microseconds to about 400 microseconds.

It uses per-cpu kernel threads to execute excess callbacks and pretty much relies on preemption.

Is simple enough. Do you expect this will help with the route cache reaping problem? I do think it's a bit hard to justify purely on the basis of the scheduling latency goodness.

Review

Quoted 2 lines
(quoted diff) +2 -0
+			list_splice(&RCU_rcudlist(cpu), &list);
+			INIT_LIST_HEAD(&RCU_rcudlist(cpu));

We have list_splice_init().

#2 lore raw
In reply to Andrew Morton
Quoted 8 lines · Andrew Morton
Quoted 7 lines · Dipankar Sarma

Here is the RCU patch for low scheduling latency Andrew was talking about in the other thread. I had done some measurements with amlat on a 2.4 GHz P4 xeon box with 256MB memory running dbench and it reduced worst case scheduling latencies from 800 microseconds to about 400 microseconds.

Quoted 6 lines
Quoted 2 lines

It uses per-cpu kernel threads to execute excess callbacks and pretty much relies on preemption.

Is simple enough. Do you expect this will help with the route cache reaping problem? I do think it's a bit hard to justify purely on the basis of the scheduling latency goodness.

We have two somewhat overlapping problems to solve in our hands. Latencies impeded by long running rcu softirqs and RCU itself impeded by long running softirqs.

In the route cache DoS case, I have been experimenting with various throttling mechanism and I consistently see 350ms odd grace period irrespective of whether I have long running RCU batches in softirq or not. I checked that by batching RCUs and putting an interval of a few ticks between batches.
This leads me to believe that the only way to avoid the route cache DoS is to reduce softirq load given a period in time and have more balance in the system. I am working on some experimental code to throttle softirqs and have some more fair use of CPU between softirqs and process context code. To answer your question, I don't think handing over to krcud will help, but it is definitely in my list of things to experiment under DoS.

Anyway, I will mail out the results/experiments so far to lkml and netdev.

Thanks
Dipankar

#4 lore raw
In reply to Arjan van de Ven
Quoted 5 lines · Arjan van de Ven
Quoted 3 lines

Reduce bh processing time of rcu callbacks by using tunable per-cpu krcud daemeons.

why not just use work queues ?

No particular reason other than that I wanted to experiment with the priority of the kernel threads when we test it under heavy load. If all these are deemed necessary, I will clean it up.

There is one minor irritant - I need to check if the worker thread for my cpu is running or not. I will have to add something to do that since this whole thing is conditional and also RCU is initialized before workqueues.

Thanks
Dipankar

#25 lore raw
In reply to Dipankar Sarma
Quoted 2 lines · Dipankar Sarma

Here is the RCU patch for low scheduling latency Andrew was talking about in the other thread. I had done some measurements with

I don't see why you're using an additional kernel thread. I told you one way to implement it via softirq taking advantage of the scheduler-friendy re-arming tasklets.

#5 lore raw
In reply to Arjan van de Ven
Quoted 5 lines · Arjan van de Ven
Quoted 3 lines

Reduce bh processing time of rcu callbacks by using tunable per-cpu krcud daemeons.

why not just use work queues ?

I don't know if work queues are scheduler friendly, but definitely the rearming tasklets are. Running a dozen callbacks per pass and queueing any remining work to a rearming tasklet should fix it.

#26 lore raw
In reply to Andrea Arcangeli
Quoted 7 lines · Andrea Arcangeli
Quoted 2 lines · Dipankar Sarma

Here is the RCU patch for low scheduling latency Andrew was talking about in the other thread. I had done some measurements with

I don't see why you're using an additional kernel thread. I told you one way to implement it via softirq taking advantage of the scheduler-friendy re-arming tasklets.

I have a patch for that too which I have been testing for DoS in route cache, not latency. It is worth testing it here, however I think re-arming tasklets is not as friendly to latency as executing the rcu callbacks from process context. One thing I have noticed is that more softirqs worsen latency irrespective of the worst-case softirq length.

Thanks
Dipankar

#6 lore raw
In reply to Andrea Arcangeli
Quoted 10 lines · Andrea Arcangeli
Quoted 5 lines · Arjan van de Ven
Quoted 3 lines

Reduce bh processing time of rcu callbacks by using tunable per-cpu krcud daemeons.

why not just use work queues ?

I don't know if work queues are scheduler friendly, but definitely the rearming tasklets are. Running a dozen callbacks per pass and queueing any remining work to a rearming tasklet should fix it.

One problem that likely happen here is that under heavy interrupt load, large number of softirqs still starve out user processes. In my DoS testing setup, I see that limiting RCU softirqs and re-arming tasklets has no effect on user process starvation.

Thanks
Dipankar

#24 lore raw
In reply to Andrea Arcangeli
Quoted 10 lines · Andrea Arcangeli
Quoted 5 lines · Arjan van de Ven
Quoted 3 lines

Reduce bh processing time of rcu callbacks by using tunable per-cpu krcud daemeons.

why not just use work queues ?

I don't know if work queues are scheduler friendly, but definitely the rearming tasklets are. Running a dozen callbacks per pass and queueing any remining work to a rearming tasklet should fix it.

yeah ksoftirqd will work too indeed.

#27 lore raw
In reply to Dipankar Sarma
Quoted 6 lines · Dipankar Sarma

I have a patch for that too which I have been testing for DoS in route cache, not latency. It is worth testing it here, however I think re-arming tasklets is not as friendly to latency as executing the rcu callbacks from process context. One thing I have noticed is that more softirqs worsen latency irrespective of the worst-case softirq length.

if we keep getting new interrupts in a flood, we'll also execute those callbacks in a flood, that's why the number of callbacks executed must be very small for every tasklet, the cost of the tasklet should be small compared to the whole cost of the irq taking to hardware too, so I don't see much problems with softirqs, if you don't get a flood of hw-irqs, the callback load will be offloaded to ksoftirqd etc... softirqs are also guaranteed to make progress despite not running RT. That's the best for you. eventd must run RT. And if you don't make your userspace krcud RT you can run a box out of memory with a RT application, while if you make it RT you'll again generate the latencies making krcud useless.

this is btw, why I implemented rcu_poll using softirqs, problem is that softirqs are so low latency that we couldn't coalesce many callbacks together to maximze icache and so we've to reach less quiescient points per second to do the same work etc... so we delay it at the next irq, that's fine, but if there's too much work to do, going back to the softirq model like in rcu_poll sounds the natural way to go.

#7 lore raw
In reply to Dipankar Sarma
Quoted 6 lines · Dipankar Sarma
Quoted 5 lines · Andrea Arcangeli
Quoted 4 lines · Arjan van de Ven
Quoted 3 lines

Reduce bh processing time of rcu callbacks by using tunable per-cpu krcud daemeons.

Quoted 8 lines
Quoted 5 lines
Quoted 1 line

why not just use work queues ?

I don't know if work queues are scheduler friendly, but definitely the rearming tasklets are. Running a dozen callbacks per pass and queueing any remining work to a rearming tasklet should fix it.

One problem that likely happen here is that under heavy interrupt load, large number of softirqs still starve out user processes.

Disagree, run 1 callback per tasklet and then you will not measure the cost of this callback compared to the cost of talking to the hardware entering/exiting kernel etc...

Quoted 2 lines

In my DoS testing setup, I see that limiting RCU softirqs and re-arming tasklets has no effect on user process starvation.

in an irq flood load that stalls userspace anyways it's ok to spread the callback load into the irqs, 10 tasklets and in turn 10 callbacks per irqs or so. That load isn't scheduler friendly anyways.

the one property you need is not to be RT like eventd, to be scheduler friendly, but guaranteed to make progress too and that's what softirqs can give you and that's why I used only softirqs in my rcu_poll patches too ;).

#8 lore raw
Quoted 6 lines
Quoted 2 lines

One problem that likely happen here is that under heavy interrupt load, large number of softirqs still starve out user processes.

Disagree, run 1 callback per tasklet and then you will not measure the cost of this callback compared to the cost of talking to the hardware entering/exiting kernel etc...

The difficult situation is when the workload generates -lots- of RCU callbacks, such as the tiny-files workload that Andrew pointed Dipankar at. In this case, if we rely only on softirq, we are between a rock and a hard place. The rock is that if we run too many softirq handlers processing all the RCU callbacks, we will degrade realtime response. The hard place is that if we delay softirq processing in order to avoid degrading realtime response, we risk having RCU callbacks piling up, exhausting memory.

This situation is what motivated using a per-CPU kernel daemon to handle the "overflow" callbacks that could not handled by softirq without degrading realtime response. Since the kernel daemon is preemptible, it can run continuously without degrading realtime response -- it will be preempted whenever a realtime task needs to run. Therefore, the kernel-daemon approach permits safely processing RCU callbacks up to the full capacity of the CPU. My guess is that the small-file creation/deletion workload can generate on the order of 100K RCU callbacks per second, and perhaps as many as 1M RCU callbacks per second on a fast CPU. The kernel daemon approach should be able to handle this load gracefully.

Of course, it would be possible to insert preemption points in the kernel daemon should we choose to support realtime response in absence of CONFIG_PREEMPT.

That said, it may well be necessary to use IPIs in some cases, as rcu-poll does, to accelerate RCU grace periods. For example, if low on memory or if too many callbacks have accumulated. If this ends up being necessary, it might get the best of both worlds, since one would shorten grace periods only when there are already a lot of callbacks, so that the overhead would be nicely amortized. It will be interesting to see how this goes!

Quoted 6 lines
Quoted 2 lines

In my DoS testing setup, I see that limiting RCU softirqs and re-arming tasklets has no effect on user process starvation.

in an irq flood load that stalls userspace anyways it's ok to spread the callback load into the irqs, 10 tasklets and in turn 10 callbacks per irqs or so. That load isn't scheduler friendly anyways.

The goal is to run reasonably, even under this workload, which, as you say is not scheduler friendly. Scheduler hostile, in fact. ;-)

Quoted 4 lines

the one property you need is not to be RT like eventd, to be scheduler friendly, but guaranteed to make progress too and that's what softirqs can give you and that's why I used only softirqs in my rcu_poll patches too ;).

The problem is that some of the workloads generate thousands of RCU callbacks per grace period. If we are going to provide realtime scheduling latencies in the hundreds of microseconds, we probably aren't going to get away with executing all of these callbacks in softirq context.

Thanx, Paul

#9 lore raw
Quoted 16 lines · Paul E. McKenney
Quoted 6 lines
Quoted 2 lines

One problem that likely happen here is that under heavy interrupt load, large number of softirqs still starve out user processes.

Disagree, run 1 callback per tasklet and then you will not measure the cost of this callback compared to the cost of talking to the hardware entering/exiting kernel etc...

The difficult situation is when the workload generates -lots- of RCU callbacks, such as the tiny-files workload that Andrew pointed Dipankar at. In this case, if we rely only on softirq, we are between a rock and a hard place. The rock is that if we run too many softirq handlers processing all the RCU callbacks, we will degrade realtime response. The hard place is that if we delay softirq processing in order to avoid degrading realtime response, we risk having RCU callbacks piling up, exhausting memory.

Quoted 7 lines

This situation is what motivated using a per-CPU kernel daemon to handle the "overflow" callbacks that could not handled by softirq without degrading realtime response. Since the kernel daemon is preemptible, it can run continuously without degrading realtime response -- it will be preempted whenever a realtime task needs to run. Therefore, the kernel-daemon approach permits safely processing RCU callbacks up to the full capacity of the CPU.

and it tends to runs the machine OOM if there's a single RT application generating the dcache load ;).

Quoted 4 lines

My guess is that the small-file creation/deletion workload can generate on the order of 100K RCU callbacks per second, and perhaps as many as 1M RCU callbacks per second on a fast CPU. The kernel daemon approach should be able to handle this load gracefully.

running 1 callback per softirq (and in turn 10 callbacks per hardware irq) shouldn't be measurable compared to the cost of the hardware handling, skb memory allocation, iommu mapping etc...

why do you care about this specific irq-flood corner case where the load is lost in the noise and there's no way to make it scheduler-friendy either since hardware irqs are involved?

the only way to make that workload scheduler friendly, is to bind the irq of the network card to cpu 1 and to bind the RT app to cpu0, no other way around it, no matter where you run the rcu callbacks (if in irq context, or non-irq context).

Quoted 3 lines

Of course, it would be possible to insert preemption points in the kernel daemon should we choose to support realtime response in absence of CONFIG_PREEMPT.

2.6 support realtime response with PREEMPT=y and =n, infact preempt doesn't affect the worst case RT latency at all, it can't.

So you shouldn't relay on preempt to avoid explicit schedule points there.

Quoted 7 lines

That said, it may well be necessary to use IPIs in some cases, as rcu-poll does, to accelerate RCU grace periods. For example, if low on memory or if too many callbacks have accumulated. If this ends up being necessary, it might get the best of both worlds, since one would shorten grace periods only when there are already a lot of callbacks, so that the overhead would be nicely amortized. It will be interesting to see how this goes!

I'm not sure in this case if IPI are needed just for offloading the remaining work to a rearming tasklet.

Quoted 9 lines
Quoted 6 lines
Quoted 2 lines

In my DoS testing setup, I see that limiting RCU softirqs and re-arming tasklets has no effect on user process starvation.

in an irq flood load that stalls userspace anyways it's ok to spread the callback load into the irqs, 10 tasklets and in turn 10 callbacks per irqs or so. That load isn't scheduler friendly anyways.

The goal is to run reasonably, even under this workload, which, as you say is not scheduler friendly. Scheduler hostile, in fact. ;-)

Indeed it is, and I'm simply expecting not any real difference by running 10 callbacks per hardware irq, so I find it a non very interesting workload to choose between a softirq or the kernel thread, but maybe I'm overlooking something.

Quoted 10 lines
Quoted 4 lines

the one property you need is not to be RT like eventd, to be scheduler friendly, but guaranteed to make progress too and that's what softirqs can give you and that's why I used only softirqs in my rcu_poll patches too ;).

The problem is that some of the workloads generate thousands of RCU callbacks per grace period. If we are going to provide realtime scheduling latencies in the hundreds of microseconds, we probably aren't going to get away with executing all of these callbacks in softirq context.

it should, you just need to run 1 callback per re-arming tasklet (then after the list is empty you stop re-arming), the softirq code will do the rest for you offloading it immediatly to ksoftirqd after 10 callbacks, and ksoftirqd will reschedule explicitly once every 10 callbacks too. The whole point of ksoftirqd is to make re-arming tasklets irq-friendy. Though there's a cost in offloading the work to a daemon, so we must not do it too frequently, so we retry 10 times before giving up and claiming the tasklet re-entrant.

#10 lore raw
Quoted 25 lines · Andrea Arcangeli
Quoted 16 lines · Paul E. McKenney
Quoted 6 lines
Quoted 2 lines

One problem that likely happen here is that under heavy interrupt load, large number of softirqs still starve out user processes.

Disagree, run 1 callback per tasklet and then you will not measure the cost of this callback compared to the cost of talking to the hardware entering/exiting kernel etc...

The difficult situation is when the workload generates -lots- of RCU callbacks, such as the tiny-files workload that Andrew pointed Dipankar at. In this case, if we rely only on softirq, we are between a rock and a hard place. The rock is that if we run too many softirq handlers processing all the RCU callbacks, we will degrade realtime response. The hard place is that if we delay softirq processing in order to avoid degrading realtime response, we risk having RCU callbacks piling up, exhausting memory.

Quoted 7 lines

This situation is what motivated using a per-CPU kernel daemon to handle the "overflow" callbacks that could not handled by softirq without degrading realtime response. Since the kernel daemon is preemptible, it can run continuously without degrading realtime response -- it will be preempted whenever a realtime task needs to run. Therefore, the kernel-daemon approach permits safely processing RCU callbacks up to the full capacity of the CPU.

Quoted 2 lines

and it tends to runs the machine OOM if there's a single RT application generating the dcache load ;).

A CPU-bound RT application needs to run standalone on bare metal. Realtime applications need to either leave enough CPU time for the OS to get necessary housekeeping done, or they need to take responsibility for doing everything, which means running without an OS.

Quoted 9 lines
Quoted 4 lines

My guess is that the small-file creation/deletion workload can generate on the order of 100K RCU callbacks per second, and perhaps as many as 1M RCU callbacks per second on a fast CPU. The kernel daemon approach should be able to handle this load gracefully.

running 1 callback per softirq (and in turn 10 callbacks per hardware irq) shouldn't be measurable compared to the cost of the hardware handling, skb memory allocation, iommu mapping etc...

Quoted 8 lines

why do you care about this specific irq-flood corner case where the load is lost in the noise and there's no way to make it scheduler-friendy either since hardware irqs are involved?

the only way to make that workload scheduler friendly, is to bind the irq of the network card to cpu 1 and to bind the RT app to cpu0, no other way around it, no matter where you run the rcu callbacks (if in irq context, or non-irq context).

Yes, these are two different problems. One other way to handle the DoS case is to limit the amount of time in IRQ context.

Quoted 9 lines
Quoted 3 lines

Of course, it would be possible to insert preemption points in the kernel daemon should we choose to support realtime response in absence of CONFIG_PREEMPT.

2.6 support realtime response with PREEMPT=y and =n, infact preempt doesn't affect the worst case RT latency at all, it can't.

So you shouldn't relay on preempt to avoid explicit schedule points there.

It can if there is a long preemptible kernel code path. It might be that there is currently no such code path in the kernel. However, I agree that there are a lot of advantages in avoiding preemption, especially in SMP kernels. It is good to be able to rely on running on the same CPU without taking special precautions!

Quoted 10 lines
Quoted 7 lines

That said, it may well be necessary to use IPIs in some cases, as rcu-poll does, to accelerate RCU grace periods. For example, if low on memory or if too many callbacks have accumulated. If this ends up being necessary, it might get the best of both worlds, since one would shorten grace periods only when there are already a lot of callbacks, so that the overhead would be nicely amortized. It will be interesting to see how this goes!

I'm not sure in this case if IPI are needed just for offloading the remaining work to a rearming tasklet.

Different problem -- my thought here was to shorten the grace period in order to stave off OOM.

Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
Quoted 2 lines

In my DoS testing setup, I see that limiting RCU softirqs and re-arming tasklets has no effect on user process starvation.

in an irq flood load that stalls userspace anyways it's ok to spread the callback load into the irqs, 10 tasklets and in turn 10 callbacks per irqs or so. That load isn't scheduler friendly anyways.

Quoted 7 lines
Quoted 2 lines

The goal is to run reasonably, even under this workload, which, as you say is not scheduler friendly. Scheduler hostile, in fact. ;-)

Indeed it is, and I'm simply expecting not any real difference by running 10 callbacks per hardware irq, so I find it a non very interesting workload to choose between a softirq or the kernel thread, but maybe I'm overlooking something.

Might be the "nice" value, which is 19 for softirq, and -19 for kernel thread. But I am likely to be missing something here myself.

Quoted 11 lines
Quoted 10 lines
Quoted 4 lines

the one property you need is not to be RT like eventd, to be scheduler friendly, but guaranteed to make progress too and that's what softirqs can give you and that's why I used only softirqs in my rcu_poll patches too ;).

The problem is that some of the workloads generate thousands of RCU callbacks per grace period. If we are going to provide realtime scheduling latencies in the hundreds of microseconds, we probably aren't going to get away with executing all of these callbacks in softirq context.

Quoted 8 lines

it should, you just need to run 1 callback per re-arming tasklet (then after the list is empty you stop re-arming), the softirq code will do the rest for you offloading it immediatly to ksoftirqd after 10 callbacks, and ksoftirqd will reschedule explicitly once every 10 callbacks too. The whole point of ksoftirqd is to make re-arming tasklets irq-friendy. Though there's a cost in offloading the work to a daemon, so we must not do it too frequently, so we retry 10 times before giving up and claiming the tasklet re-entrant.

If the "nice" value does not matter, this seems reasonable, at least for some value of 10. ;-)

Thanx, Paul

#13 lore raw
In reply to Andrea Arcangeli
Quoted 8 lines · Andrea Arcangeli

On Wed, Mar 24, 2004 at 09:26:57AM -0800, Paul E. McKenney wrote:
running 1 callback per softirq (and in turn 10 callbacks per hardware irq) shouldn't be measurable compared to the cost of the hardware handling, skb memory allocation, iommu mapping etc...

why do you care about this specific irq-flood corner case where the load is lost in the noise and there's no way to make it scheduler-friendy either since hardware irqs are involved?

We are looking at two different problems. Scheduling latency and DoS on route cache that results in dst cache overflows. The second one is an irq-flood, but latency is the least of the problems there.

Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
Quoted 2 lines

In my DoS testing setup, I see that limiting RCU softirqs and re-arming tasklets has no effect on user process starvation.

in an irq flood load that stalls userspace anyways it's ok to spread the callback load into the irqs, 10 tasklets and in turn 10 callbacks per irqs or so. That load isn't scheduler friendly anyways.

Quoted 7 lines
Quoted 2 lines

The goal is to run reasonably, even under this workload, which, as you say is not scheduler friendly. Scheduler hostile, in fact. ;-)

Indeed it is, and I'm simply expecting not any real difference by running 10 callbacks per hardware irq, so I find it a non very interesting workload to choose between a softirq or the kernel thread, but maybe I'm overlooking something.

The difference here is that during the callbacks in the kernel thread, I don't disable softirqs unlike ksoftirqd thus giving it more opportunity for preemption.

Quoted 6 lines
Quoted 5 lines

The problem is that some of the workloads generate thousands of RCU callbacks per grace period. If we are going to provide realtime scheduling latencies in the hundreds of microseconds, we probably aren't going to get away with executing all of these callbacks in softirq context.

Quoted 8 lines

it should, you just need to run 1 callback per re-arming tasklet (then after the list is empty you stop re-arming), the softirq code will do the rest for you offloading it immediatly to ksoftirqd after 10 callbacks, and ksoftirqd will reschedule explicitly once every 10 callbacks too. The whole point of ksoftirqd is to make re-arming tasklets irq-friendy. Though there's a cost in offloading the work to a daemon, so we must not do it too frequently, so we retry 10 times before giving up and claiming the tasklet re-entrant.

I had already been testing this for the DoS issue, but I tried it with amlat on a 2.4 GHz (UP) P4 xeon with 256MB ram and dbench 32 in a loop. Here are the results (CONFIG_PREEMPT = y) -

2.6.0 vanilla - 711 microseconds
2.6.0 + throttle-rcu - 439 microseconds
2.6.0 + rcu-low-lat - 413 microseconds

So under dbench workload atleast, throttling RCU works just as good as offloading them to a kernel thread (krcud) as rcu-low-lat does.

I used the following throttle-rcu patch with rcupdate.rcumaxbatch set to 16 and rcupdate.rcuplugticks set to 0. That is essentially equvalent to Andrea's earler suggestion. I have so many knobs in the patch because I had written it earlier for other experiments. Anyway, if throttling works as well as this in terms of latency for other workloads as well and there isn't any OOM situations, it is preferable to creating another per-cpu thread.

Thanks
Dipankar

Throttle rcu by forcing a limit on how many callbacks per softirq and also implement a configurable plug.

 include/linux/list.h     |   21 +++++++++++++++++++++
 include/linux/rcupdate.h |    7 ++++++-
 kernel/rcupdate.c        |   26 +++++++++++++++++++-------
 kernel/sched.c           |    2 ++
 4 files changed, 48 insertions(+), 8 deletions(-)
include/linux/list.h renamed from include/linux/list.h~throttle-rcu +21 -0
diff -puN include/linux/list.h~throttle-rcu include/linux/list.h
@@ -251,6 +251,27 @@ static inline void list_splice(struct li
 		__list_splice(list, head);
 }
 
+static inline void __list_splice_tail(struct list_head *list,
+			struct list_head *head)
+{
+	struct list_head *first = list->next;
+	struct list_head *last = list->prev;
+	struct list_head *at = head->prev;
+
+	first->prev = at;
+	at->next = first;
+	head->prev = last;
+	last->next = head;
+}
+
+
+static inline void list_splice_tail(struct list_head *list, 
+			struct list_head *head)
+{
+	if (!list_empty(list))
+		__list_splice_tail(list, head);
+}
+
 /**
  * list_splice_init - join two lists and reinitialise the emptied list.
  * @list: the new list to add.
include/linux/rcupdate.h renamed from include/linux/rcupdate.h~throttle-rcu +6 -1
diff -puN include/linux/rcupdate.h~throttle-rcu include/linux/rcupdate.h
@@ -96,6 +96,8 @@ struct rcu_data {
         long  	       	batch;           /* Batch # for current RCU batch */
         struct list_head  nxtlist;
         struct list_head  curlist;
+	struct list_head  donelist;
+	int		plugticks;
 };
 
 DECLARE_PER_CPU(struct rcu_data, rcu_data);
@@ -106,6 +108,8 @@ extern struct rcu_ctrlblk rcu_ctrlblk;
 #define RCU_batch(cpu) 		(per_cpu(rcu_data, (cpu)).batch)
 #define RCU_nxtlist(cpu) 	(per_cpu(rcu_data, (cpu)).nxtlist)
 #define RCU_curlist(cpu) 	(per_cpu(rcu_data, (cpu)).curlist)
+#define RCU_donelist(cpu) 	(per_cpu(rcu_data, (cpu)).donelist)
+#define RCU_plugticks(cpu) 	(per_cpu(rcu_data, (cpu)).plugticks)
 
 #define RCU_QSCTR_INVALID	0
 
@@ -115,7 +119,8 @@ static inline int rcu_pending(int cpu) 
 	     rcu_batch_before(RCU_batch(cpu), rcu_ctrlblk.curbatch)) ||
 	    (list_empty(&RCU_curlist(cpu)) &&
 			 !list_empty(&RCU_nxtlist(cpu))) ||
-	    cpu_isset(cpu, rcu_ctrlblk.rcu_cpu_mask))
+	    cpu_isset(cpu, rcu_ctrlblk.rcu_cpu_mask) ||
+	    (!list_empty(&RCU_donelist(cpu)) && RCU_plugticks(cpu) == 0))
 		return 1;
 	else
 		return 0;
kernel/rcupdate.c renamed from kernel/rcupdate.c~throttle-rcu +19 -7
diff -puN kernel/rcupdate.c~throttle-rcu kernel/rcupdate.c
@@ -39,6 +39,7 @@
 #include <asm/atomic.h>
 #include <asm/bitops.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/completion.h>
 #include <linux/percpu.h>
 #include <linux/notifier.h>
@@ -54,6 +55,8 @@ DEFINE_PER_CPU(struct rcu_data, rcu_data
 /* Fake initialization required by compiler */
 static DEFINE_PER_CPU(struct tasklet_struct, rcu_tasklet) = {NULL};
 #define RCU_tasklet(cpu) (per_cpu(rcu_tasklet, cpu))
+static int rcumaxbatch = 1000000;
+static int rcuplugticks = 4;
 
 /**
  * call_rcu - Queue an RCU update request.
@@ -83,16 +86,23 @@ void fastcall call_rcu(struct rcu_head *
  * Invoke the completed RCU callbacks. They are expected to be in
  * a per-cpu list.
  */
-static void rcu_do_batch(struct list_head *list)
+static void rcu_do_batch(int cpu, struct list_head *list)
 {
 	struct list_head *entry;
 	struct rcu_head *head;
+	int count = 0;
 
 	while (!list_empty(list)) {
 		entry = list->next;
 		list_del(entry);
 		head = list_entry(entry, struct rcu_head, list);
 		head->func(head->arg);
+		if (count >= rcumaxbatch) {
+			RCU_plugticks(cpu) = rcuplugticks;
+			if (!RCU_plugticks(cpu))
+				tasklet_hi_schedule(&RCU_tasklet(cpu));
+			break;
+		}
 	}
 }
 
@@ -153,18 +163,16 @@ out_unlock:
 	spin_unlock(&rcu_ctrlblk.mutex);
 }
 
-
 /*
  * This does the RCU processing work from tasklet context. 
  */
 static void rcu_process_callbacks(unsigned long unused)
 {
 	int cpu = smp_processor_id();
-	LIST_HEAD(list);
 
 	if (!list_empty(&RCU_curlist(cpu)) &&
 	    rcu_batch_after(rcu_ctrlblk.curbatch, RCU_batch(cpu))) {
-		list_splice(&RCU_curlist(cpu), &list);
+		list_splice_tail(&RCU_curlist(cpu), &RCU_donelist(cpu));
 		INIT_LIST_HEAD(&RCU_curlist(cpu));
 	}
 
@@ -185,8 +193,8 @@ static void rcu_process_callbacks(unsign
 		local_irq_enable();
 	}
 	rcu_check_quiescent_state();
-	if (!list_empty(&list))
-		rcu_do_batch(&list);
+	if (!list_empty(&RCU_donelist(cpu)) && !RCU_plugticks(cpu))
+		rcu_do_batch(cpu, &RCU_donelist(cpu));
 }
 
 void rcu_check_callbacks(int cpu, int user)
@@ -195,7 +203,7 @@ void rcu_check_callbacks(int cpu, int us
 	    (idle_cpu(cpu) && !in_softirq() && 
 				hardirq_count() <= (1 << HARDIRQ_SHIFT)))
 		RCU_qsctr(cpu)++;
-	tasklet_schedule(&RCU_tasklet(cpu));
+	tasklet_hi_schedule(&RCU_tasklet(cpu));
 }
 
 static void __devinit rcu_online_cpu(int cpu)
@@ -204,6 +212,7 @@ static void __devinit rcu_online_cpu(int
 	tasklet_init(&RCU_tasklet(cpu), rcu_process_callbacks, 0UL);
 	INIT_LIST_HEAD(&RCU_nxtlist(cpu));
 	INIT_LIST_HEAD(&RCU_curlist(cpu));
+	INIT_LIST_HEAD(&RCU_donelist(cpu));
 }
 
 static int __devinit rcu_cpu_notify(struct notifier_block *self, 
@@ -237,6 +246,7 @@ void __init rcu_init(void)
 			(void *)(long)smp_processor_id());
 	/* Register notifier for non-boot CPUs */
 	register_cpu_notifier(&rcu_nb);
+	printk("RCU: rcumaxbatch = %d, rcuplugticks = %d\n", rcumaxbatch, rcuplugticks);
 }
 
 
@@ -262,6 +272,8 @@ void synchronize_kernel(void)
 	wait_for_completion(&completion);
 }
 
+module_param(rcumaxbatch, int, 0);
+module_param(rcuplugticks, int, 0);
 
 EXPORT_SYMBOL(call_rcu);
 EXPORT_SYMBOL(synchronize_kernel);
kernel/sched.c renamed from kernel/sched.c~throttle-rcu +2 -0
diff -puN kernel/sched.c~throttle-rcu kernel/sched.c
@@ -1486,6 +1486,8 @@ void scheduler_tick(int user_ticks, int 
 
 	if (rcu_pending(cpu))
 		rcu_check_callbacks(cpu, user_ticks);
+	if (RCU_plugticks(cpu))
+		RCU_plugticks(cpu)--;
 
 	/* note: this timer irq context must be accounted for as well */
 	if (hardirq_count() - HARDIRQ_OFFSET) {

_

#14 lore raw
Quoted 6 lines · Dipankar Sarma
Quoted 5 lines · Andrea Arcangeli

On Wed, Mar 24, 2004 at 09:26:57AM -0800, Paul E. McKenney wrote:
running 1 callback per softirq (and in turn 10 callbacks per hardware irq) shouldn't be measurable compared to the cost of the hardware handling, skb memory allocation, iommu mapping etc...

Quoted 7 lines
Quoted 3 lines

why do you care about this specific irq-flood corner case where the load is lost in the noise and there's no way to make it scheduler-friendy either since hardware irqs are involved?

We are looking at two different problems. Scheduling latency and DoS on route cache that results in dst cache overflows. The second one is an irq-flood, but latency is the least of the problems there.

agreed.

Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
Quoted 6 lines
Quoted 2 lines

In my DoS testing setup, I see that limiting RCU softirqs and re-arming tasklets has no effect on user process starvation.

in an irq flood load that stalls userspace anyways it's ok to spread the callback load into the irqs, 10 tasklets and in turn 10 callbacks per irqs or so. That load isn't scheduler friendly anyways.

The goal is to run reasonably, even under this workload, which, as you say is not scheduler friendly. Scheduler hostile, in fact. ;-)

Quoted 8 lines
Quoted 4 lines

Indeed it is, and I'm simply expecting not any real difference by running 10 callbacks per hardware irq, so I find it a non very interesting workload to choose between a softirq or the kernel thread, but maybe I'm overlooking something.

The difference here is that during the callbacks in the kernel thread, I don't disable softirqs unlike ksoftirqd thus giving it more opportunity for preemption.

preemption where? in irq? softirqd will preempt just fine.

Also not that while we process the callbacks in softirqd, the irqs will stop running the callbacks, just like in your scenario. the callbacks and the other softirqs will be processed from user context, and it won't be different from scheduling krcud first and ksoftirqd later.

Quoted 11 lines

I had already been testing this for the DoS issue, but I tried it with amlat on a 2.4 GHz (UP) P4 xeon with 256MB ram and dbench 32 in a loop. Here are the results (CONFIG_PREEMPT = y) -

2.6.0 vanilla - 711 microseconds
2.6.0 + throttle-rcu - 439 microseconds
2.6.0 + rcu-low-lat - 413 microseconds

So under dbench workload atleast, throttling RCU works just as good as offloading them to a kernel thread (krcud) as rcu-low-lat does.

very nice.

Quoted 7 lines

I used the following throttle-rcu patch with rcupdate.rcumaxbatch set to 16 and rcupdate.rcuplugticks set to 0. That is essentially equvalent to Andrea's earler suggestion. I have so many knobs in the patch because I had written it earlier for other experiments. Anyway, if throttling works as well as this in terms of latency for other workloads as well and there isn't any OOM situations, it is preferable to creating another per-cpu thread.

I don't think this is enough (it is enough for the above workload though, maybe for the dcache too, but it's not generic enough), 16 callbacks per tick too low frequency, it may not keep up, that's why I suggested to offload the work to a re-arming tasklet that will finish it ASAP (but in a scheduler-friendly way) instead of waiting the next tick.

But I certainly agree this is a nice solution in practice (at least with all the common usages).

thanks!

#15 lore raw
Quoted 6 lines · Andrea Arcangeli
Quoted 4 lines · Dipankar Sarma

The difference here is that during the callbacks in the kernel thread, I don't disable softirqs unlike ksoftirqd thus giving it more opportunity for preemption.

Quoted 6 lines

preemption where? in irq? softirqd will preempt just fine.

Also not that while we process the callbacks in softirqd, the irqs will stop running the callbacks, just like in your scenario. the callbacks and the other softirqs will be processed from user context, and it won't be different from scheduling krcud first and ksoftirqd later.

It is different because the heart of ksoftirqd - do_softirq() is run with local_bh_disable(). Sure, you get chances to preempt there, but not as much as krcud which runs completely in process context. Of course, it depends on how long we stay with softirqs disabled in do_softirq().

Quoted 8 lines
Quoted 8 lines

I had already been testing this for the DoS issue, but I tried it with amlat on a 2.4 GHz (UP) P4 xeon with 256MB ram and dbench 32 in a loop. Here are the results (CONFIG_PREEMPT = y) -

2.6.0 vanilla - 711 microseconds
2.6.0 + throttle-rcu - 439 microseconds
2.6.0 + rcu-low-lat - 413 microseconds

Quoted 5 lines
Quoted 3 lines

So under dbench workload atleast, throttling RCU works just as good as offloading them to a kernel thread (krcud) as rcu-low-lat does.

very nice.

Yes. BTW, throttle-rcu too can't avoid route cache overflow under DoS stress test. Different problem, but I just wanted to mention this. I will publish those results separately.

Quoted 11 lines
Quoted 7 lines

I used the following throttle-rcu patch with rcupdate.rcumaxbatch set to 16 and rcupdate.rcuplugticks set to 0. That is essentially equvalent to Andrea's earler suggestion. I have so many knobs in the patch because I had written it earlier for other experiments. Anyway, if throttling works as well as this in terms of latency for other workloads as well and there isn't any OOM situations, it is preferable to creating another per-cpu thread.

I don't think this is enough (it is enough for the above workload though, maybe for the dcache too, but it's not generic enough), 16 callbacks per tick too low frequency, it may not keep up, that's why I

That was not 16 callbacks per tick, it was 16 callbacks in one batch of a single softirq. And then I reschedule the RCU tasklet to process the rest. I am planning to vary this and see if we should do even less per softirq.

Quoted 2 lines

But I certainly agree this is a nice solution in practice (at least with all the common usages).

Needs more testing with other workloads. I will have some more results with the tiny files test.

Thanks
Dipankar

#16 lore raw
Quoted 2 lines · Dipankar Sarma

That was not 16 callbacks per tick, it was 16 callbacks in one batch of a single softirq. And then I reschedule the RCU tasklet

sorry so you're already using tasklets in current code? I misunderstood the current code then.

Quoted 2 lines

to process the rest. I am planning to vary this and see if we should do even less per softirq.

yes, I think 16 is too much, the softirq code should just retry 10 times, summing up to 160 callbacks. After you re-arm the tasklet the first time, all other rearmed invocations should probably execute less callbacks than 16.

it greatly depends on the number of times we retry a softirq before giving up and offloading the work to ksoftirqd, that number is 10 currently (see MAX_SOFTIRQ_RESTART). The bigger that number, the less callbacks you can execute per tasklet.

#11 lore raw
In reply to Paul E. McKenney
Quoted 2 lines · Paul E. McKenney

If the "nice" value does not matter, this seems reasonable, at least for some value of 10. ;-)

the nice value should no matter for this.

btw, (just to avoid misunderstanding) the number 10 is MAX_SOFTIRQ_RESTART.

#17 lore raw
In reply to Andrea Arcangeli
Quoted 6 lines · Andrea Arcangeli
Quoted 2 lines · Dipankar Sarma

That was not 16 callbacks per tick, it was 16 callbacks in one batch of a single softirq. And then I reschedule the RCU tasklet

sorry so you're already using tasklets in current code? I misunderstood the current code then.

+ if (count >= rcumaxbatch) {
+ RCU_plugticks(cpu) = rcuplugticks;
+ if (!RCU_plugticks(cpu))
+ tasklet_hi_schedule(&RCU_tasklet(cpu));
+ break;
+ }

That does it. Although, the tasklet handler needs to optimized to for such frequent rescheduling when there isn't anything else to process in that cpu. Later.

Thanks
Dipankar

#18 lore raw
Quoted 15 lines · Dipankar Sarma
Quoted 6 lines · Andrea Arcangeli
Quoted 2 lines · Dipankar Sarma

That was not 16 callbacks per tick, it was 16 callbacks in one batch of a single softirq. And then I reschedule the RCU tasklet

sorry so you're already using tasklets in current code? I misunderstood the current code then.

kernel/rcupdate.c renamed from kernel/rcupdate.c~throttle-rcu +6 -0
+               if (count >= rcumaxbatch) {
+                       RCU_plugticks(cpu) = rcuplugticks;
+                       if (!RCU_plugticks(cpu))
+                               tasklet_hi_schedule(&RCU_tasklet(cpu));
+                       break;
+               }
Quoted 1 line

That does it. Although, the tasklet handler needs to optimized

yes I've noticed it reading just the above chunk of your patch, I just didn't notice there was a tasklet already there ready for use :/.

thanks.

#12 lore raw
In reply to Andrea Arcangeli
Quoted 5 lines · Andrea Arcangeli
Quoted 2 lines · Paul E. McKenney

If the "nice" value does not matter, this seems reasonable, at least for some value of 10. ;-)

the nice value should no matter for this.

I agree that there would not likely be any differences except in corner-case OOM situations, and that we would probably not want to rely on such differences in any case.

Quoted 2 lines

btw, (just to avoid misunderstanding) the number 10 is MAX_SOFTIRQ_RESTART.

Ah! Thank you for the clarification -- I thought you were talking about the number of RCU callbacks to be executed in each rcu_do_batch() invocation. And, yes, after MAX_SOFTIRQ_RESTART, ksoftirqd does re-enable preemption.

Thanx, Paul

#19 lore raw
In reply to Dipankar Sarma

At Thu, 25 Mar 2004 05:16:43 +0530,

Quoted 9 lines · Dipankar Sarma
Quoted 6 lines · Andrea Arcangeli
Quoted 2 lines · Dipankar Sarma

That was not 16 callbacks per tick, it was 16 callbacks in one batch of a single softirq. And then I reschedule the RCU tasklet

sorry so you're already using tasklets in current code? I misunderstood the current code then.

kernel/rcupdate.c void fastcall call_rcu(struct rcu_head * · line 105

Quoted 6 lines
kernel/rcupdate.c renamed from kernel/rcupdate.c~throttle-rcu +6 -0
+               if (count >= rcumaxbatch) {
+                       RCU_plugticks(cpu) = rcuplugticks;
+                       if (!RCU_plugticks(cpu))
+                               tasklet_hi_schedule(&RCU_tasklet(cpu));
+                       break;
+               }

it seems count is never incremented in your patch... or am i missing something?

anyway, i confirmed that with the original krcud patch the latency with dcache flood can be eliminated.

for the non-preemptive case, rcu_bh_callback_limit() should return bhlimit always, though. otherwise cond_resched() isn't called in the callback loop properly.

Takashi

#20 lore raw
Quoted 18 lines · Takashi Iwai

At Thu, 25 Mar 2004 05:16:43 +0530,

Quoted 9 lines · Dipankar Sarma
Quoted 6 lines · Andrea Arcangeli
Quoted 2 lines · Dipankar Sarma

That was not 16 callbacks per tick, it was 16 callbacks in one batch of a single softirq. And then I reschedule the RCU tasklet

sorry so you're already using tasklets in current code? I misunderstood the current code then.

kernel/rcupdate.c void fastcall call_rcu(struct rcu_head * · line 105

Quoted 6 lines
kernel/rcupdate.c renamed from kernel/rcupdate.c~throttle-rcu +6 -0
+               if (count >= rcumaxbatch) {
+                       RCU_plugticks(cpu) = rcuplugticks;
+                       if (!RCU_plugticks(cpu))
+                               tasklet_hi_schedule(&RCU_tasklet(cpu));
+                       break;
+               }
Quoted 2 lines

it seems count is never incremented in your patch... or am i missing something?

I messed it up when I forward ported the throttle-rcu.patch from 2.6.0+lots-of-instrumentation to 2.6.4-vanilla in order to publish in lkml. The original patch did this -

@@ -110,6 +113,10 @@ static void rcu_do_batch(int cpu, struct

                head->func(head->arg);
                RCU_nr_rcupdates(cpu)++;
                count++;

+ if (count >= rcumaxbatch) {
+ RCU_plugticks(cpu) = rcuplugticks;
+ break;
+ }

        }

Sorry about that.

Quoted 2 lines

anyway, i confirmed that with the original krcud patch the latency with dcache flood can be eliminated.

Does the throttle-rcu patch also help eliminate dcache flood ? You can try by just changing count >= rcumaxbatch to ++count > rcumaxbatch.

Quoted 4 lines

for the non-preemptive case, rcu_bh_callback_limit() should return bhlimit always, though. otherwise cond_resched() isn't called in the callback loop properly.

Yes, I think we should consider using limiting even in the non-preemptive case.

Thanks
Dipankar

#21 lore raw

At Sun, 28 Mar 2004 22:50:36 +0530,

Quoted 9 lines · Dipankar Sarma
Quoted 2 lines · Takashi Iwai

it seems count is never incremented in your patch... or am i missing something?

I messed it up when I forward ported the throttle-rcu.patch from 2.6.0+lots-of-instrumentation to 2.6.4-vanilla in order to publish in lkml. The original patch did this -

thans for the patch. i expected the similar fix :)

Quoted 5 lines
Quoted 2 lines

anyway, i confirmed that with the original krcud patch the latency with dcache flood can be eliminated.

Does the throttle-rcu patch also help eliminate dcache flood ? You can try by just changing count >= rcumaxbatch to ++count > rcumaxbatch.

i'll try it later.

Quoted 6 lines
Quoted 3 lines

for the non-preemptive case, rcu_bh_callback_limit() should return bhlimit always, though. otherwise cond_resched() isn't called in the callback loop properly.

Yes, I think we should consider using limiting even in the non-preemptive case.

you mean preemptive case?

Takashi

#22 lore raw

At Sun, 28 Mar 2004 19:28:41 +0200,

Quoted 8 lines · I wrote:
Quoted 6 lines
Quoted 3 lines

anyway, i confirmed that with the original krcud patch the latency with dcache flood can be eliminated.

Does the throttle-rcu patch also help eliminate dcache flood ? You can try by just changing count >= rcumaxbatch to ++count > rcumaxbatch.

i'll try it later.

the throttle-rcu patch does work indeed well even without preemption. i've tested maxbatch=16 and plugticks=0. in the older version, there was 20ms long latency, while in the patched version, no measurable latency more than 1ms.

thanks for your work!

Takashi

#23 lore raw
Quoted 9 lines · Takashi Iwai

At Sun, 28 Mar 2004 19:28:41 +0200,

Quoted 7 lines · I wrote:
Quoted 6 lines
Quoted 3 lines

anyway, i confirmed that with the original krcud patch the latency with dcache flood can be eliminated.

Does the throttle-rcu patch also help eliminate dcache flood ? You can try by just changing count >= rcumaxbatch to ++count > rcumaxbatch.

Quoted 6 lines
Quoted 1 line

i'll try it later.

the throttle-rcu patch does work indeed well even without preemption. i've tested maxbatch=16 and plugticks=0. in the older version, there was 20ms long latency, while in the patched version, no measurable latency more than 1ms.

Thanks for the measurements. throttle-rcu may eventually be the way to go, but I would wait until we have sorted out several other problems like route cache DoS testing that we are looking at currently.

Thanks
Dipankar