diff options
| author | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-12 14:56:11 -0400 |
|---|---|---|
| committer | Arthur Hanson Rasmusson <arthur@vgpu.io> | 2026-10-12 14:56:11 -0400 |
| commit | eea7829f7aa00e772e1568f8e46d7334b7d5ac67 (patch) | |
| tree | f214beb3e2c37236674b74f0a306b52412c192f2 /tools | |
| parent | 2a5621c8ac5c11fd4c41300a88c4fa08c03c5079 (diff) | |
| download | open-iov-eea7829f7aa00e772e1568f8e46d7334b7d5ac67.tar.gz open-iov-eea7829f7aa00e772e1568f8e46d7334b7d5ac67.zip | |
guest-diag: seed channel-event sets from the trace ring on client switch
clear_trace() on a pid switch dropped exactly the one-shot uvmt/uvch
events of the new client when they landed in the switch instant; the
pipe reader then never saw them and the whole session ran with an empty
sem set (r126: vecadd_loop sem=0 for minutes while its CE entries paid
the 8 s grace). Scan the ring tail once per switch and seed the sets
instead - stale kptrs that are also re-learned resolve to no content and
are deferred by the candidate scoring.
Diffstat (limited to 'tools')
| -rw-r--r-- | tools/guest-diag/guest_pin_stream.py | 50 |
1 files changed, 41 insertions, 9 deletions
diff --git a/tools/guest-diag/guest_pin_stream.py b/tools/guest-diag/guest_pin_stream.py index b031733..c0cf485 100644 --- a/tools/guest-diag/guest_pin_stream.py +++ b/tools/guest-diag/guest_pin_stream.py @@ -807,15 +807,41 @@ def resolve_channel_pins(kc, ch, out): -def clear_trace(): - """Drop stale ring events so the fallback tail reader cannot re-learn a - previous client's freed sems after a client switch. The new client's - events are delivered fresh through the consuming trace_pipe reader.""" +def seed_events_from_trace(seen_sems, seen_pbs, seen_chs): + """One-shot tail scan of the trace ring after a pid switch / start. + + The uvmt/uvbp/uvch kprobe events are one-shot per object, and the + trace_pipe reader only sees events that arrive after it attaches: a + client whose channels are registered in the instant around the scanner's + pid switch would otherwise never appear in the sets (observed r126: + vecadd_loop ran for minutes with sem=0 while its CE entries paid the + 8 s grace). The ring keeps recent events, so scan its tail once and add + every distinct kptr. Stale previous-client pointers that are also + re-learned are harmless: their chains no longer resolve to content + (the mem candidates are scored and deferred). + """ try: - with open(TRACE, "w") as f: - f.write("") - except OSError: - pass + out = subprocess.run(["tail", "-c", "1048576", TRACE], + capture_output=True, timeout=10).stdout + except Exception: + return 0 + n = 0 + for m in re.finditer(rb"sem=0x([0-9a-fA-F]+)", out): + v = int(m.group(1), 16) + if v not in seen_sems: + seen_sems.add(v) + n += 1 + for m in re.finditer(rb"pb=0x([0-9a-fA-F]+)", out): + v = int(m.group(1), 16) + if v not in seen_pbs: + seen_pbs.add(v) + n += 1 + for m in re.finditer(rb"ch=0x([0-9a-fA-F]+)", out): + v = int(m.group(1), 16) + if v not in seen_chs: + seen_chs.add(v) + n += 1 + return n class TraceReader: @@ -1190,10 +1216,16 @@ def main(): # emitted as if they were the new client's counters. CHAN_PUTS.clear() PUT_LAST.clear() - clear_trace() tracer.reset() RESOLVED_KC_PB.clear() KC_PB_STATE.clear() + # One-shot: recover the new client's one-shot channel events + # from the trace ring (they can fall in the switch instant and + # be invisible to the pipe reader; the old clear_trace() made + # that permanent - part of the r126 stall class). + _seeded = seed_events_from_trace(seen_sems, seen_pbs, seen_chs) + if _seeded: + dbg("switch seed: +%d event kptr(s)" % _seeded) if sock is not None: try: sock.sendall(("#pid %d\n" % pid).encode()) |
