public void Waking(Timestamp timestamp, ThreadInfo readyingThread) { this.stateTransition(timestamp, ThreadState.TASK_WAKING); if (readyingThread != null) { this.readyingPid = readyingThread.PidAsString(); this.readyingTid = readyingThread.Tid.ToString(); } }
void ProcessSyscallEventMetadata(LTTngEvent data) { int tid = data.StreamDefinedEventContext.ReadFieldAsInt32("_tid"); ThreadInfo callerThread; if (!this.runningThreads.TryGetValue(tid, out callerThread)) { callerThread = new ThreadInfo(tid, data.Timestamp, ThreadInfo.ThreadState.TASK_RUNNING); this.AddNewThread(callerThread); } this.ProcessThreadMetadata(data, callerThread); }
public void ProcessThreadCloneSyscallEntry(LTTngEvent data, LTTngContext context) { ThreadInfo threadInExecution = this.EventCreatorThread(data, context.CurrentCpu); if (threadInExecution != null) { if (this.closingEventsToBeSkipped.TryGetValue(threadInExecution.Tid, out int eventsToBeSkipped) && eventsToBeSkipped > 0) { this.closingEventsToBeSkipped[threadInExecution.Tid] = eventsToBeSkipped + 1; return; } uint? cloneFlags = null; const string SysCallCloneFlags = "_clone_flags"; const string SysCallFlagsAsStruct = "_flags"; // https://lttng.org/docs/v2.13/#doc-whats-new & https://github.com/lttng/lttng-modules/commit/d775625e2ba4825b73b5897e7701ad6e2bdba115 if (data.Payload.FieldsByName.ContainsKey(SysCallCloneFlags)) { cloneFlags = data.Payload.ReadFieldAsUInt32(SysCallCloneFlags); } else if (data.Payload.FieldsByName.ContainsKey(SysCallFlagsAsStruct)) // New since v2.13 { var flags = data.Payload.ReadFieldAsUInt32(SysCallFlagsAsStruct); // var exitSignal = flags & 0xFF; // the least significant byte of the `unsigned long` is the signal the kernel need to send to the parent process on child exit cloneFlags = flags & 0xFFFFFF00; // the remaining bytes of the `unsigned long` is used a bitwise flag for the clone options. } if (cloneFlags.HasValue) { if (cloneSyscallFlagsPerTid.TryGetValue(threadInExecution.Tid, out Dictionary <uint, int> lastCalls)) { if (lastCalls.TryGetValue(cloneFlags.Value, out int timesUsed)) { lastCalls[cloneFlags.Value] = timesUsed + 1; } else { lastCalls[cloneFlags.Value] = 1; } } else { cloneSyscallFlagsPerTid[threadInExecution.Tid] = new Dictionary <uint, int>() { [cloneFlags.Value] = 1 }; } } } }
public void ProcessThreadWakeUp(LTTngEvent data, LTTngContext context) { int tid = data.Payload.ReadFieldAsInt32("_tid"); if (runningThreads.TryGetValue(tid, out ThreadInfo nextThread)) { nextThread.Wakeup(data.Timestamp); } else { ThreadInfo readyingThread = this.EventCreatorThread(data, context.CurrentCpu); this.AddNewThread(new ThreadInfo(tid, data.Timestamp, ThreadInfo.ThreadState.TASK_RUNNING, readyingThread)); } }
private void ProcessGetPidSyscallExit(LTTngEvent data, LTTngContext context) { if (data.StreamDefinedEventContext == null || !data.StreamDefinedEventContext.FieldsByName.ContainsKey("_pid") || !data.StreamDefinedEventContext.FieldsByName.ContainsKey("_tid")) { ///This heuristic is activated when the event context does not have metadata regarding to tid and pid ThreadInfo executingThread = CurrentExecutingThread(context.CurrentCpu); int pid = data.Payload.ReadFieldAsInt32("_ret"); if (executingThread != null && executingThread.Pid < 0) { this.RecoverPid(executingThread, pid); } } }
public Thread(ThreadInfo threadInfo) { this.tid = threadInfo.Tid; this.pidAsInt = threadInfo.Pid; this.pidAsString = threadInfo.PidAsString(); this.command = threadInfo.Command; this.startTime = threadInfo.StartTime; this.exitTime = threadInfo.ExitTime; this.execTime = threadInfo.ExecTimeNs; this.readyTime = threadInfo.ReadyTimeNs; this.sleepTime = threadInfo.SleepTimeNs; this.diskSleepTime = threadInfo.DiskSleepTimeNs; this.stoppedTime = threadInfo.StoppedTimeNs; this.parkedTime = threadInfo.ParkedTimeNs; this.idleTime = threadInfo.IdleTimeNs; }
public void ProcessSchedForkEvent(LTTngEvent data, LTTngContext context) { int newTid = data.Payload.ReadFieldAsInt32("_child_tid"); if (runningThreads.TryGetValue(newTid, out ThreadInfo oldThreadWithSamePid)) { this.terminatedThreads.Add(new Thread(oldThreadWithSamePid)); } ThreadInfo parentThread = null; int parentTid = data.Payload.ReadFieldAsInt32("_parent_tid"); if (runningThreads.ContainsKey(parentTid)) { parentThread = runningThreads[parentTid]; if (parentThread.Pid < 0) { this.RecoverPid(parentThread, data.Payload.ReadFieldAsInt32("_parent_pid")); } } this.AddNewThread(new ThreadInfo(newTid, data.Timestamp, ThreadInfo.ThreadState.TASK_NEW, parentThread)); }
public ContextSwitch(LTTngEvent data, ThreadInfo nextThread, ThreadInfo previousThread, uint cpu) { this.cpu = cpu; this.nextPid = nextThread.PidAsString(); this.nextTid = nextThread.Tid; this.previousPid = previousThread.PidAsString(); this.previousTid = previousThread.Tid; this.priority = data.Payload.ReadFieldAsInt32("_next_prio"); if (nextThread.currentState == ThreadInfo.SchedulingState.Running) { this.readyingPid = nextThread.readyingPid; this.readyingTid = nextThread.readyingTid; this.readyTime = data.Timestamp - nextThread.lastEventTimestamp; this.previousState = ThreadInfo.SchedulingStateToString(nextThread.previousState); if (nextThread.previousState == ThreadInfo.SchedulingState.Running || nextThread.previousState == ThreadInfo.SchedulingState.NewlyCreated || nextThread.previousState == ThreadInfo.SchedulingState.Unknown) { this.waitTime = new TimestampDelta(0); } else { this.waitTime = nextThread.previousWaitTime; } } else { this.readyingPid = string.Empty; this.readyingTid = string.Empty; this.readyTime = new TimestampDelta(0); this.waitTime = data.Timestamp - nextThread.lastEventTimestamp; this.previousState = ThreadInfo.SchedulingStateToString(nextThread.currentState); } this.nextCommand = data.Payload.ReadFieldAsArray("_next_comm").GetValueAsString(); this.previousCommand = data.Payload.ReadFieldAsArray("_prev_comm").GetValueAsString(); this.switchInTime = data.Timestamp; this.nextThreadPreviousSwitchOutTime = nextThread.previousSwitchOutTime; }
void ProcessThreadMetadata(LTTngEvent data, ThreadInfo thread) { if (data.StreamDefinedEventContext.FieldsByName.ContainsKey("_pid")) { int pid = data.StreamDefinedEventContext.ReadFieldAsInt32("_pid"); if (thread.Pid != pid) { this.RecoverPid(thread, pid); } } if (thread.Command.Equals(String.Empty)) { if (data.StreamDefinedEventContext.FieldsByName.ContainsKey("_procname")) { thread.Command = data.StreamDefinedEventContext.ReadFieldAsArray("_procname").ReadAsString(); } else if (data.StreamDefinedEventContext.FieldsByName.ContainsKey("_name")) { thread.Command = data.StreamDefinedEventContext.ReadFieldAsArray("_name").ReadAsString(); } } }
public void ProcessThreadCloneSyscallExit(LTTngEvent data, LTTngContext context) { int newThreadTid = data.Payload.ReadFieldAsInt32("_ret"); if (newThreadTid == 0) { ///This is the returning syscall for the newly created child return; } ThreadInfo threadInExecution = this.EventCreatorThread(data, context.CurrentCpu); if (threadInExecution != null) { if (this.closingEventsToBeSkipped.TryGetValue(threadInExecution.Tid, out int eventsToBeSkipped) && eventsToBeSkipped > 0) { if (eventsToBeSkipped == 1) { this.closingEventsToBeSkipped.Remove(threadInExecution.Tid); } else { this.closingEventsToBeSkipped[threadInExecution.Tid] = eventsToBeSkipped - 1; } } else if (cloneSyscallFlagsPerTid.TryGetValue(threadInExecution.Tid, out Dictionary <uint, int> lastCalls)) { if (lastCalls.Count == 1) { uint flag = new List <uint>(lastCalls.Keys)[0]; if (newThreadTid > 0 && (flag & 0x00010000) > 0 && runningThreads.TryGetValue(threadInExecution.Tid, out ThreadInfo parentThread)) { if (runningThreads.TryGetValue(newThreadTid, out ThreadInfo newThread)) { newThread.Pid = parentThread.Pid; } else { this.AddNewThread(new ThreadInfo(newThreadTid, data.Timestamp, ThreadInfo.ThreadState.TASK_NEW, threadInExecution, true)); } } int amountOfEntries = lastCalls[flag]; if (amountOfEntries <= 1) { lastCalls.Remove(flag); } else { lastCalls[flag] = amountOfEntries - 1; } } else if (lastCalls.Count > 1) { int pendingEntryEvents = 0; foreach (var entry in lastCalls) { pendingEntryEvents += entry.Value; } closingEventsToBeSkipped[threadInExecution.Tid] = pendingEntryEvents - 1; ///Decrease one for the current closing event lastCalls.Clear(); } } } }
public void ProcessContextSwitch(LTTngEvent data, LTTngContext context) { int prevTid = data.Payload.ReadFieldAsInt32("_prev_tid"); if (lastContextSwitch.TryGetValue(context.CurrentCpu, out ContextSwitch previousContextSwitch)) { if (prevTid == previousContextSwitch.NextTid) { processedExecutionEvents.Add(new ExecutionEvent(previousContextSwitch, data.Timestamp)); } else { ///If we missed context switch events, processedExecutionEvents.Add(new ExecutionEvent(previousContextSwitch, previousContextSwitch.SwitchInTime)); } } int nextTid = data.Payload.ReadFieldAsInt32("_next_tid"); ThreadInfo.ThreadState switchOutState; var prevStateValue = data.Payload.FieldsByName["_prev_state"]; if (prevStateValue.FieldType == CtfTypes.Enum) { ((CtfEnumValue)prevStateValue).IntegerValue.TryGetInt32(out int enumValue); switchOutState = (ThreadInfo.ThreadState)enumValue; } else { switchOutState = (ThreadInfo.ThreadState)data.Payload.ReadFieldAsInt32("_prev_state"); } ThreadInfo prevThread; if (runningThreads.TryGetValue(prevTid, out prevThread)) { prevThread.SwitchOut(data, switchOutState); } else { prevThread = new ThreadInfo(prevTid, data.Timestamp, switchOutState); this.AddNewThread(prevThread); } if (this.EventHasMetadata(data)) { this.ProcessThreadMetadata(data, prevThread); } ThreadInfo nextThread; if (runningThreads.TryGetValue(nextTid, out nextThread)) { lastContextSwitch[context.CurrentCpu] = new ContextSwitch(data, nextThread, prevThread, context.CurrentCpu); nextThread.SwitchIn(data.Timestamp); } else { nextThread = new ThreadInfo(nextTid, data.Timestamp, ThreadInfo.ThreadState.TASK_RUNNING); lastContextSwitch[context.CurrentCpu] = new ContextSwitch(data, nextThread, prevThread, context.CurrentCpu); this.AddNewThread(nextThread); } }
private void RecoverPid(ThreadInfo thread, int newPid) { this.recoveredPids[thread.Pid] = newPid; thread.Pid = newPid; }
private void AddNewThread(ThreadInfo newThread) { this.runningThreads[newThread.Tid] = newThread; }
public ThreadInfo(int tid, Timestamp firstEventTime, ThreadState startingState, ThreadInfo parentThread = null, bool inheritPid = false) { this.Tid = tid; if (startingState == ThreadState.TASK_NEW) { this.previousState = SchedulingState.NewlyCreated; if (inheritPid && parentThread != null) { this.Pid = parentThread.Pid; } else { this.Pid = tid; } if (parentThread != null) { if (inheritPid) { this.Pid = parentThread.Pid; } else { this.Pid = tid; } this.Command = parentThread.Command; } else { this.Command = String.Empty; this.Pid = tid; } this.StartTime = firstEventTime; } else { this.Pid = tid * (-1); this.previousState = SchedulingState.Unknown; this.Command = String.Empty; this.StartTime = Timestamp.Zero; } this.lastEventTimestamp = firstEventTime; this.currentState = ThreadStateToSchedulingState(startingState); if (startingState == ThreadState.TASK_WAKING && parentThread != null) { this.readyingPid = parentThread.PidAsString(); this.readyingTid = parentThread.Tid.ToString(); } else { this.readyingPid = String.Empty; this.readyingTid = String.Empty; } }