def process_state(self, event): tid = event["tid"] pid = event["pid"] name = event["name"] if tid not in self.tids: p = Process() p.tid = tid self.tids[tid] = p else: p = self.tids[tid] # Even if the process got created earlier, some info might be # missing, add it now. p.pid = pid p.comm = name if pid != tid: # create the parent if pid not in self.tids: parent = Process() parent.tid = pid parent.pid = pid parent.comm = name self.tids[pid] = parent else: parent = self.tids[pid] # If the thread had opened FDs, they need to be assigned # to the parent. self.merge_fd_dict(p, parent)
def migrate_task(self, event): tid = event["tid"] if tid not in self.tids: p = Process() p.tid = tid p.comm = event["comm"] self.tids[tid] = p else: p = self.tids[tid] p.migrate_count += 1
def process_exec(self, event): tid = event["tid"] if tid not in self.tids: p = Process() p.tid = tid self.tids[tid] = p else: p = self.tids[tid] if "procname" in event.keys(): p.comm = event["procname"] toremove = [] for fd in p.fds.keys(): if p.fds[fd].cloexec == 1: toremove.append(fd) for fd in toremove: p.fds.pop(fd, None)
def sched_switch_per_tid(self, ts, prev_tid, next_tid, next_comm, cpu_id, event, ret): """Compute per-tid usage""" # if we don't know yet the CPU, skip this if cpu_id not in self.cpus.keys(): self.add_cpu(cpu_id, ts, next_tid) c = self.cpus[cpu_id] # per-tid usage if prev_tid in self.tids: p = self.tids[prev_tid] p.cpu_ns += (ts - p.last_sched) # perf PMU counters checks for context in event.field_list_with_scope( CTFScope.STREAM_EVENT_CONTEXT): if context.startswith("perf_"): if context not in c.perf.keys(): c.perf[context] = event[context] # add the difference between the last known value # for this counter on the current CPU diff = event[context] - c.perf[context] if context not in p.perf.keys(): p.perf[context] = diff else: p.perf[context] += diff if diff > 0: ret[context] = diff # exclude swapper process if next_tid == 0: return ret if next_tid not in self.tids: p = Process() p.tid = next_tid p.comm = next_comm self.tids[next_tid] = p else: p = self.tids[next_tid] p.comm = next_comm p.last_sched = ts for q in c.wakeup_queue: if q["task"] == p: ret["sched_latency"] = ts - q["ts"] ret["next_tid"] = next_tid c.wakeup_queue.remove(q) return ret
def issue(self, event): dev = event["dev"] sector = event["sector"] nr_sector = event["nr_sector"] # Note: since we don't know, we assume a sector is 512 bytes block_size = 512 if nr_sector == 0: return rq = {} rq["nr_sector"] = nr_sector rq["rq_time"] = event.timestamp rq["iorequest"] = IORequest() rq["iorequest"].iotype = IORequest.IO_BLOCK rq["iorequest"].begin = event.timestamp rq["iorequest"].size = nr_sector * block_size d = None for req in self.remap_requests: if req["dev"] == dev and req["sector"] == sector: d = get_disk(req["orig_dev"], self.disks) if not d: d = get_disk(dev, self.disks) d.nr_requests += 1 d.nr_sector += nr_sector d.pending_requests[sector] = rq if "tid" in event.keys(): tid = event["tid"] if tid not in self.tids: p = Process() p.tid = tid self.tids[tid] = p else: p = self.tids[tid] if p.pid != -1 and p.tid != p.pid: p = self.tids[p.pid] rq["pid"] = p # even rwbs means read, odd means write if event["rwbs"] % 2 == 0: p.block_read += nr_sector * block_size rq["iorequest"].operation = IORequest.OP_READ else: p.block_write += nr_sector * block_size rq["iorequest"].operation = IORequest.OP_WRITE
def issue(self, event): dev = event["dev"] sector = event["sector"] nr_sector = event["nr_sector"] # Note: since we don't know, we assume a sector is 512 bytes block_size = 512 if nr_sector == 0: return rq = {} rq["nr_sector"] = nr_sector rq["rq_time"] = event.timestamp rq["iorequest"] = IORequest() rq["iorequest"].iotype = IORequest.IO_BLOCK rq["iorequest"].size = nr_sector * block_size d = None for req in self.remap_requests: if req["dev"] == dev and req["sector"] == sector: d = get_disk(req["orig_dev"], self.disks) if not d: d = get_disk(dev, self.disks) d.nr_requests += 1 d.nr_sector += nr_sector d.pending_requests[sector] = rq if "tid" in event.keys(): tid = event["tid"] if tid not in self.tids: p = Process() p.tid = tid self.tids[tid] = p else: p = self.tids[tid] if p.pid != -1 and p.tid != p.pid: p = self.tids[p.pid] rq["pid"] = p # even rwbs means read, odd means write if event["rwbs"] % 2 == 0: p.block_read += nr_sector * block_size rq["iorequest"].operation = IORequest.OP_READ else: p.block_write += nr_sector * block_size rq["iorequest"].operation = IORequest.OP_WRITE
def wakeup(self, event): """Stores the sched_wakeup infos to compute scheduling latencies""" target_cpu = event["target_cpu"] tid = event["tid"] if target_cpu not in self.cpus.keys(): c = CPU() c.cpu_id = target_cpu self.cpus[target_cpu] = c else: c = self.cpus[target_cpu] if tid not in self.tids: p = Process() p.tid = tid self.tids[tid] = p else: p = self.tids[tid] c.wakeup_queue.append({"ts": event.timestamp, "task": p})
def fix_process(self, name, tid, pid): if tid not in self.tids: p = Process() p.tid = tid self.tids[tid] = p else: p = self.tids[tid] p.pid = pid p.comm = name if pid not in self.tids: p = Process() p.tid = pid self.tids[pid] = p else: p = self.tids[pid] p.pid = pid p.comm = name
def process_fork(self, event): child_tid = event["child_tid"] child_pid = event["child_pid"] child_comm = event["child_comm"] parent_pid = event["parent_pid"] parent_tid = event["parent_pid"] parent_comm = event["parent_comm"] f = Process() f.tid = child_tid f.pid = child_pid f.comm = child_comm # make sure the parent exists self.fix_process(parent_comm, parent_tid, parent_pid) p = self.tids[parent_pid] for fd in p.fds.keys(): f.fds[fd] = self.dup_fd(p.fds[fd]) f.fds[fd].parent = parent_pid self.tids[child_tid] = f
def file_descriptor(self, event): pid = event["pid"] fd = event["fd"] filename = event["filename"] if pid not in self.tids: p = Process() p.pid = pid p.tid = pid self.tids[pid] = p else: p = self.tids[pid] if fd not in p.fds.keys(): newfile = FD() newfile.filename = filename newfile.fd = fd # FIXME: we don't have the info, just assume for now newfile.cloexec = 1 p.fds[fd] = newfile else: # just fix the filename p.fds[fd].filename = filename
def track_fds(self, name, event, cpu_id): # we don't know which process is currently on this CPU ret_string = "" if cpu_id not in self.cpus: return c = self.cpus[cpu_id] if c.current_tid == -1: return t = self.tids[c.current_tid] # check if we can fix the pid from a context if t.pid == -1 and "pid" in event.keys(): t.pid = event["pid"] p = Process() p.tid = t.pid p.pid = t.pid p.comm = t.comm self.tids[p.pid] = p # if it's a thread, we want the parent if t.pid != -1 and t.tid != t.pid: t = self.tids[t.pid] if name in Syscalls.OPEN_SYSCALLS: self.track_open(name, t, event, c) elif name in Syscalls.CLOSE_SYSCALLS: ret_string = "%s %s(%d)" % (ns_to_hour_nsec(event.timestamp), name, event["fd"]) self.track_close(name, t, event, c) # when a connect occurs, no new FD is returned, but we can fix # the "filename" if we have the destination info elif name in ["sys_connect", "syscall_entry_connect"] \ and "family" in event.keys(): if event["family"] == socket.AF_INET: fd = self.get_fd(t, event["fd"]) ipport = "%s:%d" % (get_v4_addr_str(event["v4addr"]), event["dport"]) fd.filename = ipport return ret_string