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);
         }
     }
 }
コード例 #6
0
 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;
            }
        }