1 # The MIT License (MIT)
3 # Copyright (C) 2015 - Antoine Busque <abusque@efficios.com>
5 # Permission is hereby granted, free of charge, to any person obtaining a copy
6 # of this software and associated documentation files (the "Software"), to deal
7 # in the Software without restriction, including without limitation the rights
8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 # copies of the Software, and to permit persons to whom the Software is
10 # furnished to do so, subject to the following conditions:
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 from .analysis
import Analysis
26 class IrqAnalysis(Analysis
):
27 def __init__(self
, state
, conf
):
29 'irq_handler_entry': self
._process
_irq
_handler
_entry
,
30 'irq_handler_exit': self
._process
_irq
_handler
_exit
,
31 'softirq_exit': self
._process
_softirq
_exit
34 super().__init
__(state
, conf
)
35 self
._state
.register_notification_cbs(notification_cbs
)
37 # Indexed by irq 'id' (irq or vec)
38 self
.hard_irq_stats
= {}
39 self
.softirq_stats
= {}
40 # Log of individual interrupts
45 for id in self
.hard_irq_stats
:
46 self
.hard_irq_stats
[id].reset()
47 for id in self
.softirq_stats
:
48 self
.softirq_stats
[id].reset()
50 def _process_irq_handler_entry(self
, **kwargs
):
52 name
= kwargs
['irq_name']
53 if id not in self
.hard_irq_stats
:
54 self
.hard_irq_stats
[id] = HardIrqStats(name
)
55 elif self
.hard_irq_stats
[id].name
!= name
:
56 self
.hard_irq_stats
[id].name
= name
58 def _process_irq_handler_exit(self
, **kwargs
):
59 irq
= kwargs
['hard_irq']
61 if not self
._filter
_cpu
(irq
.cpu_id
):
64 if self
._conf
.min_duration
is not None and \
65 irq
.duration
< self
._conf
.min_duration
:
67 if self
._conf
.max_duration
is not None and \
68 irq
.duration
> self
._conf
.max_duration
:
71 self
.irq_list
.append(irq
)
72 if irq
.id not in self
.hard_irq_stats
:
73 self
.hard_irq_stats
[irq
.id] = HardIrqStats()
75 self
.hard_irq_stats
[irq
.id].update_stats(irq
)
77 def _process_softirq_exit(self
, **kwargs
):
78 irq
= kwargs
['softirq']
80 if not self
._filter
_cpu
(irq
.cpu_id
):
83 if self
._conf
.min_duration
is not None and \
84 irq
.duration
< self
._conf
.min_duration
:
86 if self
._conf
.max_duration
is not None and \
87 irq
.duration
> self
._conf
.max_duration
:
90 self
.irq_list
.append(irq
)
91 if irq
.id not in self
.softirq_stats
:
92 name
= SoftIrqStats
.names
[irq
.id]
93 self
.softirq_stats
[irq
.id] = SoftIrqStats(name
)
95 self
.softirq_stats
[irq
.id].update_stats(irq
)
99 def __init__(self
, name
):
101 self
.min_duration
= None
102 self
.max_duration
= None
103 self
.total_duration
= 0
108 return len(self
.irq_list
)
110 def update_stats(self
, irq
):
111 if self
.min_duration
is None or irq
.duration
< self
.min_duration
:
112 self
.min_duration
= irq
.duration
114 if self
.max_duration
is None or irq
.duration
> self
.max_duration
:
115 self
.max_duration
= irq
.duration
117 self
.total_duration
+= irq
.duration
118 self
.irq_list
.append(irq
)
121 self
.min_duration
= None
122 self
.max_duration
= None
123 self
.total_duration
= 0
127 class HardIrqStats(IrqStats
):
128 def __init__(self
, name
='unknown'):
129 super().__init
__(name
)
132 class SoftIrqStats(IrqStats
):
133 # from include/linux/interrupt.h
134 names
= {0: 'HI_SOFTIRQ',
139 5: 'BLOCK_IOPOLL_SOFTIRQ',
140 6: 'TASKLET_SOFTIRQ',
142 8: 'HRTIMER_SOFTIRQ',
145 def __init__(self
, name
):
146 super().__init
__(name
)
147 self
.min_raise_latency
= None
148 self
.max_raise_latency
= None
149 self
.total_raise_latency
= 0
152 def update_stats(self
, irq
):
153 super().update_stats(irq
)
155 if irq
.raise_ts
is None:
158 raise_latency
= irq
.begin_ts
- irq
.raise_ts
159 if self
.min_raise_latency
is None or \
160 raise_latency
< self
.min_raise_latency
:
161 self
.min_raise_latency
= raise_latency
163 if self
.max_raise_latency
is None or \
164 raise_latency
> self
.max_raise_latency
:
165 self
.max_raise_latency
= raise_latency
167 self
.total_raise_latency
+= raise_latency
168 self
.raise_count
+= 1
172 self
.min_raise_latency
= None
173 self
.max_raise_latency
= None
174 self
.total_raise_latency
= 0
This page took 0.033862 seconds and 5 git commands to generate.