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