Home | History | Annotate | Download | only in tools
      1 Demonstrations of criticalstat: Find long atomic critical sections in the kernel.
      2 
      3 criticalstat traces and reports occurences of atomic critical sections in the
      4 kernel with useful stacktraces showing the origin of them. Such critical
      5 sections frequently occur due to use of spinlocks, or if interrupts or
      6 preemption were explicity disabled by a driver. IRQ routines in Linux are also
      7 executed with interrupts disabled. There are many reasons. Such critical
      8 sections are a source of long latency/responsive issues for real-time systems.
      9 
     10 This works by probing the preempt/irq and cpuidle tracepoints in the kernel.
     11 Since this uses BPF, only the root user can use this tool. Further, the kernel
     12 has to be built with certain CONFIG options enabled inorder for it to work:
     13 CONFIG_PREEMPTIRQ_EVENTS
     14 CONFIG_DEBUG_PREEMPT
     15 Additionally, the following options should be turned off on older kernels:
     16 CONFIG_PROVE_LOCKING
     17 CONFIG_LOCKDEP
     18 
     19 USAGE:
     20 # ./criticalstat -h
     21 usage: criticalstat [-h] [-p] [-i] [-d DURATION]
     22 
     23 Trace long critical sections
     24 
     25 optional arguments:
     26   -h, --help            Show this help message and exit
     27   -p, --preemptoff      Find long sections where preemption was off
     28   -i, --irqoff          Find long sections where IRQ was off
     29   -d DURATION, --duration DURATION
     30                         Duration in uS (microseconds) below which we filter
     31 
     32 examples:
     33     ./criticalstat          	# run with default options: irq off for more than 100 uS
     34     ./criticalstat -p       	# find sections with preemption disabled for more than 100 uS
     35     ./criticalstat -d 500   	# find sections with IRQs disabled for more than 500 uS
     36     ./criticalstat -p -d 500	# find sections with preemption disabled for more than 500 uS
     37 
     38 The tool runs continuously until interrupted by Ctrl-C
     39 
     40 
     41 By default, criticalstat finds IRQ disable sections for > 100us.
     42 
     43 # ./criticalstat
     44 Finding critical section with IRQ disabled for > 100us
     45 ===================================
     46 TASK: kworker/u16:5 (pid  5903 tid  5903) Total Time: 194.427  us
     47 
     48 Section start: __schedule -> schedule
     49 Section end:   _raw_spin_unlock_irq -> finish_task_switch
     50   trace_hardirqs_on+0xdc
     51   trace_hardirqs_on+0xdc
     52   _raw_spin_unlock_irq+0x18
     53   finish_task_switch+0xf0
     54   __schedule+0x8c8
     55   preempt_schedule_irq+0x38
     56   el1_preempt+0x8
     57 ===================================
     58 
     59 
     60 If too many sections are showing up, the user can raise the threshold to only
     61 show critical sections that are > 500us by passing "-d" option:
     62 
     63 # ./criticalstat -d 500
     64 Finding critical section with IRQ disabled for > 500us
     65 ===================================
     66 TASK: crtc_commit:111 (pid   246 tid   246) Total Time: 580.730  us
     67 
     68 Section start: clk_enable_lock -> clk_enable
     69 Section end:   _raw_spin_unlock_irqrestore -> clk_enable
     70   trace_hardirqs_on+0xdc
     71   trace_hardirqs_on+0xdc
     72   _raw_spin_unlock_irqrestore+0x24
     73   clk_enable+0x80
     74   msm_dss_enable_clk+0x7c
     75   sde_power_resource_enable+0x578
     76   _sde_crtc_vblank_enable_no_lock+0x68
     77   sde_crtc_vblank+0x8c
     78   sde_kms_enable_vblank+0x18
     79   vblank_ctrl_worker+0xd0
     80   kthread_worker_fn+0xf8
     81   kthread+0x114
     82   ret_from_fork+0x10
     83 ===================================
     84 
     85 
     86 If instead of irq disabled sections, we want to see preempt disabled sections,
     87 then pass the "-p" option. Below we try to find preempt-disabled critical
     88 sections that are > 500us.
     89 
     90 # ./criticalstat -p -d 500
     91 Finding critical section with preempt disabled for > 500us
     92 ===================================
     93 TASK: swapper/1 (pid     0 tid     0) Total Time: 618.437  us
     94 
     95 Section start: preempt_count_add -> preempt_count_add
     96 Section end:   preempt_count_sub -> preempt_count_sub
     97   trace_preempt_on+0x98
     98   trace_preempt_on+0x98
     99   preempt_latency_stop+0x164
    100   preempt_count_sub+0x50
    101   schedule+0x74
    102   schedule_preempt_disabled+0x14
    103   cpu_startup_entry+0x84
    104   secondary_start_kernel+0x1c8
    105   [unknown]
    106 ===================================
    107 
    108 
    109 criticalstat -p can also reflect kernel scheduler issues sometimes. These may
    110 show up as long preempt-off sections if the functions in the scheduler take a
    111 long time to run (such as pick_next_task_fair which selects the CPU for a task
    112 
    113 Follow is a report showing a preempt-off latency of 700us during the schedule
    114 loop's execution:
    115 
    116 ===================================
    117 TASK: irq/296-cs35l36 (pid   666 tid   666) Total Time: 732.657  us
    118 
    119 Section start: schedule -> schedule
    120 Section end:   schedule -> schedule
    121   trace_preempt_on+0x98
    122   trace_preempt_on+0x98
    123   preempt_count_sub+0xa4
    124   schedule+0x78
    125   schedule_timeout+0x80
    126   wait_for_common+0xb4
    127   wait_for_completion_timeout+0x28
    128   geni_i2c_xfer+0x298
    129   __i2c_transfer+0x4e0
    130   i2c_transfer+0x8
    131   irq_thread_fn+0x2c
    132   irq_thread+0x160
    133   kthread+0x118
    134   ret_from_fork+0x10
    135 ===================================
    136 
    137 
    138 See Also: Linux kernel's preemptoff and irqoff tracers which provide similar
    139 tracing but with some limitations.
    140