Fix get_syscall_name string indexing
[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():
3ce8423c
AB
35 def __init__(self, tid=None, pid=None, comm=''):
36 self.tid = tid
37 self.pid = pid
38 self.comm = 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 46 self.current_syscall = {}
bd3cd7c5 47 # the process scheduled before this one
2b4a3c12 48 self.prev_tid = None
bd3cd7c5 49
44823c31
AB
50 def track_chrono_fd(self, fd, filename, fdtype, timestamp):
51 chrono_metadata = {}
3f52a605
AB
52 chrono_metadata['filename'] = filename
53 chrono_metadata['fdtype'] = fdtype
44823c31
AB
54
55 if fd not in self.chrono_fds:
56 self.chrono_fds[fd] = OrderedDict()
57 self.chrono_fds[fd][timestamp] = chrono_metadata
58 else:
59 chrono_fd = self.chrono_fds[fd]
60 last_ts = next(reversed(chrono_fd))
3f52a605 61 if filename != chrono_fd[last_ts]['filename']:
44823c31
AB
62 chrono_fd[timestamp] = chrono_metadata
63
bd3cd7c5
JD
64
65class CPU():
3c9bf3fa
AB
66 def __init__(self, cpu_id):
67 self.cpu_id = cpu_id
2b4a3c12 68 self.current_tid = None
f4522f09 69 self.current_hard_irq = None
26facb3a
AB
70 # softirqs use a dict because multiple ones can be raised before
71 # handling. They are indexed by vec, and each entry is a list,
72 # ordered chronologically
73 self.current_softirqs = {}
bd3cd7c5
JD
74
75
994541c3
AB
76class MemoryManagement():
77 def __init__(self):
78 self.page_count = 0
79
21167679 80class SyscallEvent():
3b1dda96
AB
81 def __init__(self, name, begin_ts):
82 self.name = name
83 self.begin_ts = begin_ts
84 self.end_ts = None
21167679
JD
85 self.ret = None
86 self.duration = None
bd3cd7c5 87
3b1dda96
AB
88 def process_exit(self, event):
89 self.end_ts = event.timestamp
90 self.ret = event['ret']
91 self.duration = self.end_ts - self.begin_ts
92
93 @classmethod
94 def new_from_entry(cls, event):
95 return cls(event.name, event.timestamp)
96
bd3cd7c5
JD
97
98class Disk():
99 def __init__(self):
3b1dda96 100 # pending block IO Requests, indexed by sector
bd3cd7c5 101 self.pending_requests = {}
bd3cd7c5
JD
102
103
bd3cd7c5
JD
104class FDType():
105 unknown = 0
106 disk = 1
107 net = 2
108 # not 100% sure they are network FDs (assumed when net_dev_xmit is
109 # called during a write syscall and the type in unknown).
110 maybe_net = 3
111
112
113class FD():
114 def __init__(self):
3f52a605 115 self.filename = ''
2b4a3c12 116 self.fd = None
bd3cd7c5
JD
117 # address family
118 self.family = socket.AF_UNSPEC
119 self.fdtype = FDType.unknown
120 # if FD was inherited, parent PID
2b4a3c12 121 self.parent = None
6f2c9e92 122 self.cloexec = False
bd3cd7c5
JD
123 self.init_counts()
124
6f2c9e92
AB
125 @classmethod
126 def new_from_fd(cls, fd):
127 new_fd = cls()
128 new_fd.filename = fd.filename
129 new_fd.fd = fd.fd
130 new_fd.family = fd.family
131 new_fd.fdtype = fd.fdtype
132 new_fd.parent = fd.parent
133 new_fd.cloexec = fd.cloexec
134 return new_fd
135
bd3cd7c5
JD
136 def init_counts(self):
137 # network read/write
138 self.net_read = 0
139 self.net_write = 0
140 # disk read/write (might be cached)
141 self.disk_read = 0
142 self.disk_write = 0
143 # unclassified read/write (FD passing and statedump)
144 self.unk_read = 0
145 self.unk_write = 0
146 # total read/write
147 self.read = 0
148 self.write = 0
bd3cd7c5
JD
149 # array of syscall IORequest objects for freq analysis later
150 self.iorequests = []
151
152
153class IRQ():
0297cb98 154 def __init__(self, id, cpu_id, begin_ts=None):
f4522f09 155 self.id = id
9b94fe47 156 self.cpu_id = cpu_id
0297cb98
AB
157 self.begin_ts = begin_ts
158 self.end_ts = None
bd3cd7c5 159
f4522f09
AB
160
161class HardIRQ(IRQ):
0297cb98
AB
162 def __init__(self, id, cpu_id, begin_ts):
163 super().__init__(id, cpu_id, begin_ts)
f4522f09
AB
164 self.ret = None
165
166 @classmethod
167 def new_from_irq_handler_entry(cls, event):
3f52a605 168 id = event['irq']
9b94fe47 169 cpu_id = event['cpu_id']
0297cb98
AB
170 begin_ts = event.timestamp
171 return cls(id, cpu_id, begin_ts)
f4522f09
AB
172
173
174class SoftIRQ(IRQ):
0297cb98
AB
175 def __init__(self, id, cpu_id, raise_ts=None, begin_ts=None):
176 super().__init__(id, cpu_id, begin_ts)
f4522f09
AB
177 self.raise_ts = raise_ts
178
179 @classmethod
180 def new_from_softirq_raise(cls, event):
3f52a605 181 id = event['vec']
9b94fe47 182 cpu_id = event['cpu_id']
f4522f09 183 raise_ts = event.timestamp
9b94fe47 184 return cls(id, cpu_id, raise_ts)
f4522f09
AB
185
186 @classmethod
187 def new_from_softirq_entry(cls, event):
3f52a605 188 id = event['vec']
9b94fe47 189 cpu_id = event['cpu_id']
0297cb98
AB
190 begin_ts = event.timestamp
191 return cls(id, cpu_id, begin_ts=begin_ts)
ca95b1c3 192
bd3cd7c5
JD
193
194class IORequest():
bd3cd7c5
JD
195 # I/O operations
196 OP_OPEN = 1
197 OP_READ = 2
198 OP_WRITE = 3
199 OP_CLOSE = 4
200 OP_SYNC = 5
201
3b1dda96
AB
202 def __init__(self, begin_ts, size, tid, operation):
203 self.begin_ts = begin_ts
204 self.end_ts = None
bd3cd7c5 205 self.duration = None
3b1dda96
AB
206 # request size in bytes
207 self.size = size
208 self.operation = operation
209 # tid of process that triggered the rq
210 self.tid = tid
211
212
213class SyscallIORequest(IORequest):
214 def __init__(self, begin_ts, size, tid, operation):
215 super().__init__(begin_ts, size, tid)
bd3cd7c5 216 self.fd = None
3b1dda96
AB
217 self.syscall_name = None
218 # Number of pages alloc'd/freed/written to disk during the rq
219 self.pages_allocated = 0
220 self.pages_freed = 0
221 self.pages_written = 0
222 # Whether kswapd was forced to wakeup during the rq
bd3cd7c5 223 self.woke_kswapd = False
3b1dda96
AB
224
225
226class BlockIORequest(IORequest):
227 # Logical sector size in bytes, according to the kernel
228 SECTOR_SIZE = 512
229
230 def __init__(self, begin_ts, tid, operation, dev, sector, nr_sector):
231 size = nr_sector * BlockIORequest.SECTOR_SIZE
232 super().__init__(begin_ts, size, tid, operation)
233 self.dev = dev
234 self.sector = sector
235 self.nr_sector = nr_sector
236
237 def update_from_rq_complete(self, event):
238 self.end_ts = event.timestamp
239 self.duration = self.end_ts - self.begin_ts
240
241 @classmethod
242 def new_from_rq_issue(cls, event):
243 begin_ts = event.timestamp
244 dev = event['dev']
245 sector = event['sector']
246 nr_sector = event['nr_sector']
247 tid = event['tid']
248 # An even rwbs indicates read operation, odd indicates write
249 if event['rwbs'] % 2 == 0:
250 operation = IORequest.OP_READ
251 else:
252 operation = IORequest.OP_WRITE
253
254 return cls(begin_ts, tid, operation, dev, sector, nr_sector)
255
256
257class BlockRemapRequest():
258 def __init__(self, dev, sector, old_dev, old_sector):
259 self.dev = dev
260 self.sector = sector
261 self.old_dev = old_dev
262 self.old_sector = old_sector
bd3cd7c5
JD
263
264
265class Syscalls_stats():
266 def __init__(self):
267 self.read_max = 0
268 self.read_min = None
269 self.read_total = 0
270 self.read_count = 0
271 self.read_rq = []
272 self.all_read = []
273
274 self.write_max = 0
275 self.write_min = None
276 self.write_total = 0
277 self.write_count = 0
278 self.write_rq = []
279 self.all_write = []
280
281 self.open_max = 0
282 self.open_min = None
283 self.open_total = 0
284 self.open_count = 0
285 self.open_rq = []
286 self.all_open = []
287
288 self.sync_max = 0
289 self.sync_min = None
290 self.sync_total = 0
291 self.sync_count = 0
292 self.sync_rq = []
293 self.all_sync = []
294
295
296class SyscallConsts():
297 # TODO: decouple socket/family logic from this class
298 INET_FAMILIES = [socket.AF_INET, socket.AF_INET6]
299 DISK_FAMILIES = [socket.AF_UNIX]
300 # list nof syscalls that open a FD on disk (in the exit_syscall event)
baa4cfe9 301 DISK_OPEN_SYSCALLS = ['open', 'openat']
bd3cd7c5
JD
302 # list of syscalls that open a FD on the network
303 # (in the exit_syscall event)
baa4cfe9 304 NET_OPEN_SYSCALLS = ['accept', 'accept4', 'socket']
bd3cd7c5 305 # list of syscalls that can duplicate a FD
baa4cfe9
AB
306 DUP_OPEN_SYSCALLS = ['fcntl', 'dup2']
307 SYNC_SYSCALLS = ['sync', 'sync_file_range', 'fsync', 'fdatasync']
bd3cd7c5
JD
308 # merge the 3 open lists
309 OPEN_SYSCALLS = DISK_OPEN_SYSCALLS + NET_OPEN_SYSCALLS + DUP_OPEN_SYSCALLS
3f52a605 310 # list of syscalls that close a FD (in the 'fd =' field)
baa4cfe9 311 CLOSE_SYSCALLS = ['close']
bd3cd7c5 312 # list of syscall that read on a FD, value in the exit_syscall following
baa4cfe9
AB
313 READ_SYSCALLS = ['read', 'recvmsg', 'recvfrom', 'splice', 'readv',
314 'sendfile64']
bd3cd7c5 315 # list of syscall that write on a FD, value in the exit_syscall following
baa4cfe9 316 WRITE_SYSCALLS = ['write', 'sendmsg', 'sendto', 'writev']
21167679
JD
317 # All I/O related syscalls
318 IO_SYSCALLS = OPEN_SYSCALLS + CLOSE_SYSCALLS + READ_SYSCALLS + \
c437b3bd 319 WRITE_SYSCALLS + SYNC_SYSCALLS
bd3cd7c5
JD
320 # generic names assigned to special FDs, don't try to match these in the
321 # closed_fds dict
3f52a605 322 GENERIC_NAMES = ['unknown', 'socket']
This page took 0.038815 seconds and 5 git commands to generate.