1------------------result
(CONFIG_HZ=1000 and CONFIG_PREEMPT=y)
Before patch applied: 10% empty calls (something 30+ percent)
after patch applied: <0.5% empty calls
2------------------test procedure
I think you can add kernel trace code to detect it. (I think it's simpler)
The next is my fast test:
ensure CONFIG_FUNCTION_GRAPH_TRACER = y
mount -t debugfs xx /debugfs/
echo rcu_process_callbacks > /debugfs/tracing/set_graph_function
echo function_graph > /debugfs/tracing/current_tracer
# make all cpu busy, example: complier the kernel with 'make -j XXX'
cat /debugfs/tracing/trace_pipe > trace.tmp # CTRL-C after 20 seconds
./parser.py trace.tmp
3----------------------test code and ....
(Because compiler may or may not inline a static function, So:)
Your 'empty_call_graph' is not deferent from mine very likely,
you should change it.
Q: why 'rcu_process_gp_end();' is empty call?
A: _raw_spin_trylock() is not inline-ed, we will
see a '{' and '_raw_spin_trylock()' in the graph
when it is not empty call:
0) | rcu_process_gp_end() {
0) 0.350 us | _raw_spin_trylock();
0) 0.250 us | _raw_spin_unlock_irqrestore();
0) 1.326 us | }
Q: Is this test trusted.
A: No, but I believe it.
------------------parser.py----------
#!/bin/env python
import sys
empty_call_graph = tuple(
''' rcu_process_callbacks() {
__rcu_process_callbacks() {
rcu_process_gp_end();
check_for_new_grace_period();
}
__rcu_process_callbacks() {
rcu_process_gp_end();
check_for_new_grace_period();
}
}
'''.splitlines())
total=0
empty=0
match=0
empty_block=[]
for line in file(sys.argv[1]):
empty_block.append(line)
if line.find('force_quiescent_state();') >= 0:
continue
if line.find(empty_call_graph[match]) < 0:
match = 0
empty_block=[]
continue
match = match + 1
if match == 1:
total = total + 1
elif match == len(empty_call_graph):
empty = empty + 1
for emptyline in empty_block:
print emptyline,
empty_block=[]
match = 0
print('empty call/total call: %d/%d' % (empty, total))
print('fraction: %f%%' % (100.0 * empty / total))
--