Minor: add comment in irq state provider to clarify execptional softirq creation
[deliverable/lttng-analyses.git] / linuxautomaton / linuxautomaton / sv.py
CommitLineData
4ed24f86
JD
1#!/usr/bin/env python3
2#
3# The MIT License (MIT)
4#
a3fa57c0 5# Copyright (C) 2015 - Julien Desfossez <jdesfossez@efficios.com>
4ed24f86
JD
6#
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:
13#
14# The above copyright notice and this permission notice shall be included in
15# all copies or substantial portions of the Software.
16#
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
23# SOFTWARE.
24
bd3cd7c5 25import socket
44823c31 26from collections import OrderedDict
bd3cd7c5
JD
27
28
29class StateVariable:
30 pass
31
32
33class Process():
34 def __init__(self):
2b4a3c12
AB
35 self.tid = None
36 self.pid = None
3f52a605 37 self.comm = ''
bd3cd7c5
JD
38 # indexed by fd
39 self.fds = {}
40 # indexed by filename
41 self.closed_fds = {}
31d9c53b
AB
42 # filenames (indexed by timestamp) associated with given fd (top-level
43 # index) at a given point in time
44 self.chrono_fds = {}
bd3cd7c5
JD
45 self.current_syscall = {}
46 self.init_counts()
47
48 def init_counts(self):
49 self.cpu_ns = 0
50 self.migrate_count = 0
51 # network read/write
52 self.net_read = 0
53 self.net_write = 0
54 # disk read/write (might be cached)
55 self.disk_read = 0
56 self.disk_write = 0
57 # actual block access read/write
58 self.block_read = 0
59 self.block_write = 0
60 # unclassified read/write (FD passing and statedump)
61 self.unk_read = 0
62 self.unk_write = 0
63 # total I/O read/write
64 self.read = 0
65 self.write = 0
66 # last TS where the process was scheduled in
6ddb1dd6 67 self.last_sched = None
bd3cd7c5 68 # the process scheduled before this one
2b4a3c12 69 self.prev_tid = None
bd3cd7c5
JD
70 # indexed by syscall_name
71 self.syscalls = {}
72 self.perf = {}
73 self.dirty = 0
74 self.allocated_pages = 0
75 self.freed_pages = 0
76 self.total_syscalls = 0
77 # array of IORequest objects for freq analysis later (block and
78 # syscalls with no FD like sys_sync)
79 self.iorequests = []
80
44823c31
AB
81 def track_chrono_fd(self, fd, filename, fdtype, timestamp):
82 chrono_metadata = {}
3f52a605
AB
83 chrono_metadata['filename'] = filename
84 chrono_metadata['fdtype'] = fdtype
44823c31
AB
85
86 if fd not in self.chrono_fds:
87 self.chrono_fds[fd] = OrderedDict()
88 self.chrono_fds[fd][timestamp] = chrono_metadata
89 else:
90 chrono_fd = self.chrono_fds[fd]
91 last_ts = next(reversed(chrono_fd))
3f52a605 92 if filename != chrono_fd[last_ts]['filename']:
44823c31
AB
93 chrono_fd[timestamp] = chrono_metadata
94
bd3cd7c5
JD
95
96class CPU():
97 def __init__(self):
2b4a3c12 98 self.cpu_id = None
bd3cd7c5 99 self.cpu_ns = 0
2b4a3c12 100 self.current_tid = None
f4522f09 101 self.current_hard_irq = None
26facb3a
AB
102 # softirqs use a dict because multiple ones can be raised before
103 # handling. They are indexed by vec, and each entry is a list,
104 # ordered chronologically
105 self.current_softirqs = {}
bd3cd7c5
JD
106 self.start_task_ns = 0
107 self.perf = {}
108 self.wakeup_queue = []
109
110
994541c3
AB
111class MemoryManagement():
112 def __init__(self):
113 self.page_count = 0
114
115
bd3cd7c5 116class Syscall():
21167679 117 # One instance for each unique syscall name per process
bd3cd7c5 118 def __init__(self):
3f52a605 119 self.name = ''
bd3cd7c5 120 self.count = 0
21167679
JD
121 # duration min/max
122 self.min = None
123 self.max = 0
124 self.total_duration = 0
125 # list of all syscall events (SyscallEvent)
126 self.rq = []
127
128
129class SyscallEvent():
130 def __init__(self):
131 self.entry_ts = None
132 self.exit_ts = None
133 self.ret = None
134 self.duration = None
bd3cd7c5
JD
135
136
137class Disk():
138 def __init__(self):
3f52a605
AB
139 self.name = ''
140 self.prettyname = ''
bd3cd7c5
JD
141 self.init_counts()
142
143 def init_counts(self):
144 self.nr_sector = 0
145 self.nr_requests = 0
146 self.completed_requests = 0
147 self.request_time = 0
148 self.pending_requests = {}
149 self.rq_list = []
150 self.max = None
151 self.min = None
152 self.total = None
153 self.count = None
154 self.rq_values = None
155 self.stdev = None
156
157
158class Iface():
159 def __init__(self):
3f52a605 160 self.name = ''
bd3cd7c5
JD
161 self.init_counts()
162
163 def init_counts(self):
164 self.recv_bytes = 0
165 self.recv_packets = 0
166 self.send_bytes = 0
167 self.send_packets = 0
168
169
170class FDType():
171 unknown = 0
172 disk = 1
173 net = 2
174 # not 100% sure they are network FDs (assumed when net_dev_xmit is
175 # called during a write syscall and the type in unknown).
176 maybe_net = 3
177
178
179class FD():
180 def __init__(self):
3f52a605 181 self.filename = ''
2b4a3c12 182 self.fd = None
bd3cd7c5
JD
183 # address family
184 self.family = socket.AF_UNSPEC
185 self.fdtype = FDType.unknown
186 # if FD was inherited, parent PID
2b4a3c12 187 self.parent = None
bd3cd7c5
JD
188 self.init_counts()
189
190 def init_counts(self):
191 # network read/write
192 self.net_read = 0
193 self.net_write = 0
194 # disk read/write (might be cached)
195 self.disk_read = 0
196 self.disk_write = 0
197 # unclassified read/write (FD passing and statedump)
198 self.unk_read = 0
199 self.unk_write = 0
200 # total read/write
201 self.read = 0
202 self.write = 0
203 self.open = 0
204 self.close = 0
205 self.cloexec = 0
206 # array of syscall IORequest objects for freq analysis later
207 self.iorequests = []
208
209
210class IRQ():
9b94fe47 211 def __init__(self, id, cpu_id, start_ts=None):
f4522f09 212 self.id = id
9b94fe47 213 self.cpu_id = cpu_id
f4522f09 214 self.start_ts = start_ts
2b4a3c12 215 self.stop_ts = None
bd3cd7c5 216
f4522f09
AB
217
218class HardIRQ(IRQ):
9b94fe47
AB
219 def __init__(self, id, cpu_id, start_ts):
220 super().__init__(id, cpu_id, start_ts)
f4522f09
AB
221 self.ret = None
222
223 @classmethod
224 def new_from_irq_handler_entry(cls, event):
3f52a605 225 id = event['irq']
9b94fe47 226 cpu_id = event['cpu_id']
f4522f09 227 start_ts = event.timestamp
9b94fe47 228 return cls(id, cpu_id, start_ts)
f4522f09
AB
229
230
231class SoftIRQ(IRQ):
9b94fe47 232 def __init__(self, id, cpu_id, raise_ts=None, start_ts=None):
26facb3a 233 super().__init__(id, cpu_id, start_ts)
f4522f09
AB
234 self.raise_ts = raise_ts
235
236 @classmethod
237 def new_from_softirq_raise(cls, event):
3f52a605 238 id = event['vec']
9b94fe47 239 cpu_id = event['cpu_id']
f4522f09 240 raise_ts = event.timestamp
9b94fe47 241 return cls(id, cpu_id, raise_ts)
f4522f09
AB
242
243 @classmethod
244 def new_from_softirq_entry(cls, event):
3f52a605 245 id = event['vec']
9b94fe47 246 cpu_id = event['cpu_id']
f4522f09 247 start_ts = event.timestamp
9b94fe47 248 return cls(id, cpu_id, start_ts=start_ts)
ca95b1c3 249
bd3cd7c5
JD
250
251class IORequest():
3f52a605 252 # I/O 'type'
bd3cd7c5
JD
253 IO_SYSCALL = 1
254 IO_BLOCK = 2
255 IO_NET = 3
256 # I/O operations
257 OP_OPEN = 1
258 OP_READ = 2
259 OP_WRITE = 3
260 OP_CLOSE = 4
261 OP_SYNC = 5
262
263 def __init__(self):
264 # IORequest.IO_*
265 self.iotype = None
266 # bytes for syscalls and net, sectors for block
267 # FIXME: syscalls handling vectors (vector size missing)
268 self.size = None
269 # for syscalls and block: delay between issue and completion
270 # of the request
271 self.duration = None
272 # IORequest.OP_*
273 self.operation = None
274 # syscall name
275 self.name = None
276 # begin syscall timestamp
277 self.begin = None
278 # end syscall timestamp
279 self.end = None
280 # current process
281 self.proc = None
282 # current FD (for syscalls)
283 self.fd = None
284 # buffers dirtied during the operation
285 self.dirty = 0
286 # pages allocated during the operation
287 self.page_alloc = 0
288 # pages freed during the operation
289 self.page_free = 0
290 # pages written on disk during the operation
291 self.page_written = 0
292 # kswapd was forced to wakeup during the operation
293 self.woke_kswapd = False
294 # estimated pages flushed during a sync operation
295 self.page_cleared = 0
296
297
298class Syscalls_stats():
299 def __init__(self):
300 self.read_max = 0
301 self.read_min = None
302 self.read_total = 0
303 self.read_count = 0
304 self.read_rq = []
305 self.all_read = []
306
307 self.write_max = 0
308 self.write_min = None
309 self.write_total = 0
310 self.write_count = 0
311 self.write_rq = []
312 self.all_write = []
313
314 self.open_max = 0
315 self.open_min = None
316 self.open_total = 0
317 self.open_count = 0
318 self.open_rq = []
319 self.all_open = []
320
321 self.sync_max = 0
322 self.sync_min = None
323 self.sync_total = 0
324 self.sync_count = 0
325 self.sync_rq = []
326 self.all_sync = []
327
328
329class SyscallConsts():
330 # TODO: decouple socket/family logic from this class
331 INET_FAMILIES = [socket.AF_INET, socket.AF_INET6]
332 DISK_FAMILIES = [socket.AF_UNIX]
333 # list nof syscalls that open a FD on disk (in the exit_syscall event)
3f52a605
AB
334 DISK_OPEN_SYSCALLS = ['sys_open', 'syscall_entry_open',
335 'sys_openat', 'syscall_entry_openat']
bd3cd7c5
JD
336 # list of syscalls that open a FD on the network
337 # (in the exit_syscall event)
3f52a605
AB
338 NET_OPEN_SYSCALLS = ['sys_accept', 'syscall_entry_accept',
339 'sys_accept4', 'syscall_entry_accept4',
340 'sys_socket', 'syscall_entry_socket']
bd3cd7c5 341 # list of syscalls that can duplicate a FD
3f52a605
AB
342 DUP_OPEN_SYSCALLS = ['sys_fcntl', 'syscall_entry_fcntl',
343 'sys_dup2', 'syscall_entry_dup2']
344 SYNC_SYSCALLS = ['sys_sync', 'syscall_entry_sync',
345 'sys_sync_file_range', 'syscall_entry_sync_file_range',
346 'sys_fsync', 'syscall_entry_fsync',
347 'sys_fdatasync', 'syscall_entry_fdatasync']
bd3cd7c5
JD
348 # merge the 3 open lists
349 OPEN_SYSCALLS = DISK_OPEN_SYSCALLS + NET_OPEN_SYSCALLS + DUP_OPEN_SYSCALLS
3f52a605
AB
350 # list of syscalls that close a FD (in the 'fd =' field)
351 CLOSE_SYSCALLS = ['sys_close', 'syscall_entry_close']
bd3cd7c5 352 # list of syscall that read on a FD, value in the exit_syscall following
3f52a605
AB
353 READ_SYSCALLS = ['sys_read', 'syscall_entry_read',
354 'sys_recvmsg', 'syscall_entry_recvmsg',
355 'sys_recvfrom', 'syscall_entry_recvfrom',
356 'sys_splice', 'syscall_entry_splice',
357 'sys_readv', 'syscall_entry_readv',
358 'sys_sendfile64', 'syscall_entry_sendfile64']
bd3cd7c5 359 # list of syscall that write on a FD, value in the exit_syscall following
3f52a605
AB
360 WRITE_SYSCALLS = ['sys_write', 'syscall_entry_write',
361 'sys_sendmsg', 'syscall_entry_sendmsg',
362 'sys_sendto', 'syscall_entry_sendto',
363 'sys_writev', 'syscall_entry_writev']
21167679
JD
364 # All I/O related syscalls
365 IO_SYSCALLS = OPEN_SYSCALLS + CLOSE_SYSCALLS + READ_SYSCALLS + \
c437b3bd 366 WRITE_SYSCALLS + SYNC_SYSCALLS
bd3cd7c5
JD
367 # generic names assigned to special FDs, don't try to match these in the
368 # closed_fds dict
3f52a605 369 GENERIC_NAMES = ['unknown', 'socket']
bd3cd7c5
JD
370
371 def __init__():
372 pass
This page took 0.043961 seconds and 5 git commands to generate.