RCU performance

Christian Prochaska <[email protected]>
Newsgroups gmane.comp.micro-kernel.l4.devel
Message-ID <[email protected]>
Hello,

when building Fiasco.OC with multiprocessor support enabled, the
unmapping of an IPC gate via 'l4_task_unmap()' appears to require at
least 3 timer interrupts to occur until completion, which can make a
noticable difference in overall execution time compared to the
uniprocessor configuration (extreme example:
https://github.com/genodelabs/genode/issues/712, in a more realistic
scenario (compiling an application) the difference was still like ~2
minutes execution time with the uniprocessor configuration vs. ~6
minutes with the multiprocessor configuration).

I've attached the debug output I got while trying to understand what's
going on and which shows some of the RCU-related activities after each
of the 3 timer interrupts (patch used for the debug messages:
https://github.com/cproc/foc/commit/fa7b6f823cb29c0fc1db389ceb956d554d9e1546.patch).

According to these messages, the quiescent period had ended after the
second timer interrupt and I wonder if it is really necessary to wait
for a third timer interrupt before executing the corresponding
callbacks. Would it work correctly with the attached patch, too?

Christian

_______________________________________________
l4-hackers mailing list
[email protected]
http://os.inf.tu-dresden.de/mailman/listinfo/l4-hackers
rcu_debug_messages.txt (text/plain, 2.7 KB)
*** userland ***

void Genode::Capability_map::remove(Genode::Cap_index*): calling l4_task_unmap()

*** kernel ***

Reap_list::del(): calling rcu_wait()
Context::rcu_wait(): adding 'rcu_unblock()' callback to _n list
Context::rcu_wait(): calling schedule()
idle_op()
Thread::handle_timer_interrupt(): calling Rcu::do_pending_work(0)
Rcu::do_pending_work(): calling process_callbacks(0)
Rcu_data::process_callbacks(): _n.empty() = 0, _c.empty() = 1, _d.empty() = 1, rgp->_completed = -298, CPU-local batch number = -298
Rcu_data::process_callbacks(): moving callbacks from _n list to _c list
Rcu_data::process_callbacks(): increased CPU-local batch number to -297
Rcu_glbl::start_batch(): increased current global batch number to -297
Rcu_data::check_quiescent_state(): _q_batch = -298
Rcu_data::check_quiescent_state(): _q_batch != rgp->_current, starting new grace period
Rcu_data::check_quiescent_state(): _q_batch increased to -297
Rcu_data::process_callbacks(): check_quiescent_state() returned, _n.empty() = 1, _c.empty() = 0, _d.empty() = 1, rgp->_completed = -298, CPU-local batch number = -297
Thread::handle_timer_interrupt(): resched = 0
idle_op()
Thread::handle_timer_interrupt(): calling Rcu::do_pending_work(0)
Rcu::do_pending_work(): calling process_callbacks(0)
Rcu_data::process_callbacks(): _n.empty() = 1, _c.empty() = 0, _d.empty() = 1, rgp->_completed = -298, CPU-local batch number = -297
Rcu_data::check_quiescent_state(): _q_batch = -297
Rcu_data::check_quiescent_state(): quiescent state passed, calling rgp->cpu_quiet()
Rcu_glbl::cpu_quiet(): clearing cpu 0
Rcu_glbl::cpu_quiet(): all CPUs clear, quiescent period has ended
Rcu_glbl::cpu_quiet(): global _completed is now -297
Rcu_data::process_callbacks(): check_quiescent_state() returned, _n.empty() = 1, _c.empty() = 0, _d.empty() = 1, rgp->_completed = -297, CPU-local batch number = -297
Thread::handle_timer_interrupt(): resched = 0
idle_op()
Thread::handle_timer_interrupt(): calling Rcu::do_pending_work(0)
Rcu::do_pending_work(): calling process_callbacks(0)
Rcu_data::process_callbacks(): _n.empty() = 1, _c.empty() = 0, _d.empty() = 1, rgp->_completed = -297, CPU-local batch number = -297
Rcu_data::process_callbacks(): calling _d.append(_c)
Rcu_data::check_quiescent_state(): _q_batch = -297
Rcu_data::process_callbacks(): check_quiescent_state() returned, _n.empty() = 1, _c.empty() = 1, _d.empty() = 0, rgp->_completed = -297, CPU-local batch number = -297
Rcu_data::process_callbacks(): calling do_batch()
Context::rcu_unblock()
Thread::handle_timer_interrupt(): resched = 1
Thread::handle_timer_interrupt(): calling schedule()

*** userland ***

void Genode::Capability_map::remove(Genode::Cap_index*): l4_task_unmap() returned
rcu.diff (text/x-patch, 726 B)
diff --git a/kernel/fiasco/src/kern/rcupdate.cpp b/kernel/fiasco/src/kern/rcupdate.cpp
index 398f072..f125e42 100644
--- a/kernel/fiasco/src/kern/rcupdate.cpp
+++ b/kernel/fiasco/src/kern/rcupdate.cpp
@@ -425,8 +425,7 @@ Rcu_data::process_callbacks(Rcu_glbl *rgp)
       l->item = 0;
       l->event = Rcu::Rcu_process);
 
-  if (!_c.empty() && rgp->_completed >= _batch)
-    _d.append(_c);
+  bool saved_c_empty = _c.empty();
 
   if (!_n.empty() && _c.empty())
     {
@@ -450,8 +449,11 @@ Rcu_data::process_callbacks(Rcu_glbl *rgp)
     }
 
   check_quiescent_state(rgp);
-  if (!_d.empty())
+
+  if (!saved_c_empty && rgp->_completed >= _batch) {
+    _d.append(_c);
     return do_batch();
+  }
 
   return false;
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.