public ThreadExitEvent( string comm, int tid, int pid, double time, int timeProp, int cpu, string eventName, string eventProp, IEnumerable <Frame> callerStacks, ThreadExit exit) : base(EventKind.ThreadExit, comm, tid, pid, time, timeProp, cpu, eventName, eventProp, callerStacks) { Exit = exit; }
private IEnumerable <LinuxEvent> NextEvent(Regex regex, FastStream source) { string line = string.Empty; while (true) { source.SkipWhiteSpace(); if (source.EndOfStream) { break; } EventKind eventKind = EventKind.Cpu; StringBuilder sb = new StringBuilder(); // Fetch Command (processName) - Stops when it sees the pattern \s+\d+/\d int idx = FindEndOfProcessCommand(source); if (idx < 0) { break; } source.ReadFixedString(idx, sb); source.SkipWhiteSpace(); string processCommand = sb.ToString(); sb.Clear(); // Process ID int pid = source.ReadInt(); // Detect whether or not the Thread ID is present. int tid = pid; if (source.Peek(0) == '/') { // Thread ID source.MoveNext(); // Move past the "/" tid = source.ReadInt(); } // CPU source.SkipWhiteSpace(); int cpu = -1; if (source.Peek(0) == '[') { source.MoveNext(); // Move past the "[" cpu = source.ReadInt(); source.MoveNext(); // Move past the "]" } // Time source.SkipWhiteSpace(); source.ReadAsciiStringUpTo(':', sb); double time = double.Parse(sb.ToString(), CultureInfo.InvariantCulture) * 1000; // To convert to MSec sb.Clear(); source.MoveNext(); // Move past ":" // Time Property source.SkipWhiteSpace(); int timeProp = -1; if (IsNumberChar((char)source.Current)) { timeProp = source.ReadInt(); } // Event Name source.SkipWhiteSpace(); source.ReadAsciiStringUpTo(':', sb); string eventName = sb.ToString(); sb.Clear(); source.MoveNext(); // Event Properties // I mark a position here because I need to check what type of event this is without screwing up the stream var markedPosition = source.MarkPosition(); source.ReadAsciiStringUpTo('\n', sb); string eventDetails = sb.ToString().Trim(); sb.Clear(); if (eventDetails.Length >= SchedulerEvent.Name.Length && eventDetails.Substring(0, SchedulerEvent.Name.Length) == SchedulerEvent.Name) { eventKind = EventKind.Scheduler; } else if (eventDetails.Length > ThreadExitEvent.Name.Length && eventDetails.Substring(0, ThreadExitEvent.Name.Length) == ThreadExitEvent.Name) { eventKind = EventKind.ThreadExit; } // Now that we know the header of the trace, we can decide whether or not to skip it given our pattern if (regex != null && !regex.IsMatch(eventName)) { while (true) { source.MoveNext(); if (IsEndOfSample(source, source.Current, source.Peek(1))) { break; } } yield return(null); } else { LinuxEvent linuxEvent; Frame threadTimeFrame = null; // For the sake of immutability, I have to do a similar if-statement twice. I'm trying to figure out a better way // but for now this will do. ScheduleSwitch schedSwitch = null; if (eventKind == EventKind.Scheduler) { source.RestoreToMark(markedPosition); schedSwitch = ReadScheduleSwitch(source); source.SkipUpTo('\n'); } ThreadExit exit = null; if (eventKind == EventKind.ThreadExit) { source.RestoreToMark(markedPosition); exit = ReadExit(source); source.SkipUpTo('\n'); } IEnumerable <Frame> frames = ReadFramesForSample(processCommand, pid, tid, threadTimeFrame, source); if (eventKind == EventKind.Scheduler) { linuxEvent = new SchedulerEvent(processCommand, tid, pid, time, timeProp, cpu, eventName, eventDetails, frames, schedSwitch); } else if (eventKind == EventKind.ThreadExit) { linuxEvent = new ThreadExitEvent(processCommand, tid, pid, time, timeProp, cpu, eventName, eventDetails, frames, exit); } else { linuxEvent = new CpuEvent(processCommand, tid, pid, time, timeProp, cpu, eventName, eventDetails, frames); } yield return(linuxEvent); } } }