public void FlushBlockedThreadsAt(double endTime) { foreach (int threadid in EndingStates.Keys) { if (EndingStates[threadid].Key == LinuxThreadState.BLOCKED_TIME) { KeyValuePair <LinuxThreadState, LinuxEvent> sampleInfo = EndingStates[threadid]; sampleInfo.Value.Period = TimeStamp - sampleInfo.Value.TimeMSec; AddThreadPeriod(threadid, sampleInfo.Value.TimeMSec, TimeStamp); StackSource.AddSample(StackSource.CreateSampleFor(sampleInfo.Value, this)); } } }
private void DoMetrics(LinuxEvent linuxEvent) { KeyValuePair <LinuxThreadState, LinuxEvent> sampleInfo; // This is check for completed scheduler events, ones that start with prev_comm and have // corresponding next_comm. if (linuxEvent.Kind == EventKind.Scheduler) { SchedulerEvent schedEvent = (SchedulerEvent)linuxEvent; if (EndingStates.ContainsKey(schedEvent.Switch.PreviousThreadID) && EndingStates[schedEvent.Switch.PreviousThreadID].Key == LinuxThreadState.CPU_TIME) // Blocking { // PreviousThreadID is now blocking. linuxEvent contains its blocking stack, so save it here. // When it unblocks (becomes NextThreadID below, we'll log a sample for it.) EndingStates[schedEvent.Switch.PreviousThreadID] = new KeyValuePair <LinuxThreadState, LinuxEvent>(LinuxThreadState.BLOCKED_TIME, linuxEvent); } if (EndingStates.TryGetValue(schedEvent.Switch.NextThreadID, out sampleInfo) && sampleInfo.Key == LinuxThreadState.BLOCKED_TIME) // Unblocking { sampleInfo.Value.Period = linuxEvent.TimeMSec - sampleInfo.Value.TimeMSec; AddThreadPeriod(sampleInfo.Value.ThreadID, sampleInfo.Value.TimeMSec, linuxEvent.TimeMSec); StackSource.AddSample(StackSource.CreateSampleFor(sampleInfo.Value, this)); EndingStates[schedEvent.Switch.NextThreadID] = new KeyValuePair <LinuxThreadState, LinuxEvent>(LinuxThreadState.CPU_TIME, linuxEvent); } } else if (linuxEvent.Kind == EventKind.ThreadExit) { ThreadExitEvent exitEvent = (ThreadExitEvent)linuxEvent; if (EndingStates.TryGetValue(exitEvent.Exit.ThreadID, out sampleInfo)) { if (sampleInfo.Key == LinuxThreadState.BLOCKED_TIME) // Blocked on exit { sampleInfo.Value.Period = linuxEvent.TimeMSec - sampleInfo.Value.TimeMSec; AddThreadPeriod(sampleInfo.Value.ThreadID, sampleInfo.Value.TimeMSec, linuxEvent.TimeMSec); StackSource.AddSample(StackSource.CreateSampleFor(sampleInfo.Value, this)); } else // Unblocked on exit { linuxEvent.Period = linuxEvent.TimeMSec - sampleInfo.Value.TimeMSec; StackSource.AddSample(StackSource.CreateSampleFor(linuxEvent, this)); } // Remove the thread so that any events that might come after the exit are ignored. EndingStates.Remove(exitEvent.Exit.ThreadID); } } else if (linuxEvent.Kind == EventKind.Cpu) { // Keep track of the last CPU sample for each CPU, and use its timestamp // to determine how much weight to give the sample. if (LastCpuUsage.TryGetValue(linuxEvent.CpuNumber, out LinuxEvent lastCpuEvent)) { lastCpuEvent.Period = linuxEvent.TimeMSec - lastCpuEvent.TimeMSec; StackSource.AddSample(StackSource.CreateSampleFor(lastCpuEvent, this)); } LastCpuUsage[linuxEvent.CpuNumber] = linuxEvent; } }