3 # The MIT License (MIT)
5 # Copyright (C) 2015 - Antoine Busque <abusque@efficios.com>
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to deal
9 # in the Software without restriction, including without limitation the rights
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 # copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
14 # The above copyright notice and this permission notice shall be included in
15 # all copies or substantial portions of the Software.
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 from .analysis
import Analysis
28 class IrqAnalysis(Analysis
):
29 def __init__(self
, state
, min_duration
, max_duration
):
31 'irq_handler_entry': self
._process
_irq
_handler
_entry
,
32 'irq_handler_exit': self
._process
_irq
_handler
_exit
,
33 'softirq_exit': self
._process
_softirq
_exit
37 self
._state
.register_notification_cbs(notification_cbs
)
38 self
._min
_duration
= min_duration
39 self
._max
_duration
= max_duration
41 if self
._min
_duration
is not None:
42 self
._min
_duration
*= 1000
43 if self
._max
_duration
is not None:
44 self
._max
_duration
*= 1000
46 # Indexed by irq 'id' (irq or vec)
47 self
.hard_irq_stats
= {}
48 self
.softirq_stats
= {}
49 # Log of individual interrupts
52 def process_event(self
, ev
):
57 for id in self
.hard_irq_stats
:
58 self
.hard_irq_stats
[id].reset()
59 for id in self
.softirq_stats
:
60 self
.softirq_stats
[id].reset()
62 def _process_irq_handler_entry(self
, **kwargs
):
64 name
= kwargs
['irq_name']
65 if id not in self
.hard_irq_stats
:
66 self
.hard_irq_stats
[id] = HardIrqStats(name
)
67 elif self
.hard_irq_stats
[id].name
!= name
:
68 self
.hard_irq_stats
[id].name
= name
70 def _process_irq_handler_exit(self
, **kwargs
):
71 irq
= kwargs
['hard_irq']
73 duration
= irq
.end_ts
- irq
.begin_ts
74 if self
._min
_duration
is not None and duration
< self
._min
_duration
:
76 if self
._max
_duration
is not None and duration
> self
._max
_duration
:
79 self
.irq_list
.append(irq
)
80 if irq
.id not in self
.hard_irq_stats
:
81 self
.hard_irq_stats
[irq
.id] = HardIrqStats()
83 self
.hard_irq_stats
[irq
.id].update_stats(irq
)
85 def _process_softirq_exit(self
, **kwargs
):
86 irq
= kwargs
['softirq']
88 duration
= irq
.end_ts
- irq
.begin_ts
89 if self
._min
_duration
is not None and duration
< self
._min
_duration
:
91 if self
._max
_duration
is not None and duration
> self
._max
_duration
:
94 self
.irq_list
.append(irq
)
95 if irq
.id not in self
.softirq_stats
:
96 name
= SoftIrqStats
.names
[irq
.id]
97 self
.softirq_stats
[irq
.id] = SoftIrqStats(name
)
99 self
.softirq_stats
[irq
.id].update_stats(irq
)
103 def __init__(self
, name
):
105 self
.min_duration
= None
106 self
.max_duration
= None
107 self
.total_duration
= 0
112 return len(self
.irq_list
)
114 def update_stats(self
, irq
):
115 duration
= irq
.end_ts
- irq
.begin_ts
117 if self
.min_duration
is None or duration
< self
.min_duration
:
118 self
.min_duration
= duration
120 if self
.max_duration
is None or duration
> self
.max_duration
:
121 self
.max_duration
= duration
123 self
.total_duration
+= duration
124 self
.irq_list
.append(irq
)
127 self
.min_duration
= None
128 self
.max_duration
= None
129 self
.total_duration
= 0
133 class HardIrqStats(IrqStats
):
134 def __init__(self
, name
='unknown'):
135 super().__init
__(name
)
138 class SoftIrqStats(IrqStats
):
139 # from include/linux/interrupt.h
140 names
= {0: 'HI_SOFTIRQ',
145 5: 'BLOCK_IOPOLL_SOFTIRQ',
146 6: 'TASKLET_SOFTIRQ',
148 8: 'HRTIMER_SOFTIRQ',
151 def __init__(self
, name
):
152 super().__init
__(name
)
153 self
.min_raise_latency
= None
154 self
.max_raise_latency
= None
155 self
.total_raise_latency
= 0
158 def update_stats(self
, irq
):
159 super().update_stats(irq
)
161 if irq
.raise_ts
is None:
164 raise_latency
= irq
.begin_ts
- irq
.raise_ts
165 if self
.min_raise_latency
is None or \
166 raise_latency
< self
.min_raise_latency
:
167 self
.min_raise_latency
= raise_latency
169 if self
.max_raise_latency
is None or \
170 raise_latency
> self
.max_raise_latency
:
171 self
.max_raise_latency
= raise_latency
173 self
.total_raise_latency
+= raise_latency
174 self
.raise_count
+= 1
178 self
.min_raise_latency
= None
179 self
.max_raise_latency
= None
180 self
.total_raise_latency
= 0
This page took 0.043775 seconds and 5 git commands to generate.