| OLD | NEW |
| 1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
| 2 <!-- | 2 <!-- |
| 3 Copyright (c) 2012 The Chromium Authors. All rights reserved. | 3 Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 4 Use of this source code is governed by a BSD-style license that can be | 4 Use of this source code is governed by a BSD-style license that can be |
| 5 found in the LICENSE file. | 5 found in the LICENSE file. |
| 6 --> | 6 --> |
| 7 | 7 |
| 8 <link rel="import" href="/tracing/base/color_scheme.html"> | 8 <link rel="import" href="/tracing/base/color_scheme.html"> |
| 9 <link rel="import" href="/tracing/base/iteration_helpers.html"> | 9 <link rel="import" href="/tracing/base/iteration_helpers.html"> |
| 10 <link rel="import" href="/tracing/extras/importer/linux_perf/android_parser.html
"> | 10 <link rel="import" href="/tracing/extras/importer/linux_perf/android_parser.html
"> |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 '^\\s*(.+)-(\\d+)\\s+\\(\\s*(\\d+|-+)\\)\\s\\[(\\d+)\\]' + | 83 '^\\s*(.+)-(\\d+)\\s+\\(\\s*(\\d+|-+)\\)\\s\\[(\\d+)\\]' + |
| 84 '\\s+[dX.][Nnp.][Hhs.][0-9a-f.]' + | 84 '\\s+[dX.][Nnp.][Hhs.][0-9a-f.]' + |
| 85 '\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$'); | 85 '\\s+(\\d+\\.\\d+):\\s+(\\S+):\\s(.*)$'); |
| 86 var lineParserWithTGID = function(line) { | 86 var lineParserWithTGID = function(line) { |
| 87 var groups = lineREWithTGID.exec(line); | 87 var groups = lineREWithTGID.exec(line); |
| 88 if (!groups) { | 88 if (!groups) { |
| 89 return groups; | 89 return groups; |
| 90 } | 90 } |
| 91 | 91 |
| 92 var tgid = groups[3]; | 92 var tgid = groups[3]; |
| 93 if (tgid[0] === '-') | 93 if (tgid[0] === '-') tgid = undefined; |
| 94 tgid = undefined; | |
| 95 | 94 |
| 96 return { | 95 return { |
| 97 threadName: groups[1], | 96 threadName: groups[1], |
| 98 pid: groups[2], | 97 pid: groups[2], |
| 99 tgid: tgid, | 98 tgid: tgid, |
| 100 cpuNumber: groups[4], | 99 cpuNumber: groups[4], |
| 101 timestamp: groups[5], | 100 timestamp: groups[5], |
| 102 eventName: groups[6], | 101 eventName: groups[6], |
| 103 details: groups[7] | 102 details: groups[7] |
| 104 }; | 103 }; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 161 | 160 |
| 162 /** | 161 /** |
| 163 * Deduce the format of trace data. Linux kernels prior to 3.3 used one | 162 * Deduce the format of trace data. Linux kernels prior to 3.3 used one |
| 164 * format (by default); 3.4 and later used another. Additionally, newer | 163 * format (by default); 3.4 and later used another. Additionally, newer |
| 165 * kernels can optionally trace the TGID. | 164 * kernels can optionally trace the TGID. |
| 166 * | 165 * |
| 167 * @return {function} the function for parsing data when the format is | 166 * @return {function} the function for parsing data when the format is |
| 168 * recognized; otherwise undefined. | 167 * recognized; otherwise undefined. |
| 169 */ | 168 */ |
| 170 function autoDetectLineParser(line) { | 169 function autoDetectLineParser(line) { |
| 171 if (line[0] === '{') | 170 if (line[0] === '{') return false; |
| 172 return false; | 171 if (lineREWithTGID.test(line)) { |
| 173 if (lineREWithTGID.test(line)) | |
| 174 return lineParserWithTGID; | 172 return lineParserWithTGID; |
| 175 if (lineREWithIRQInfo.test(line)) | 173 } |
| 174 if (lineREWithIRQInfo.test(line)) { |
| 176 return lineParserWithIRQInfo; | 175 return lineParserWithIRQInfo; |
| 177 if (lineREWithLegacyFmt.test(line)) | 176 } |
| 177 if (lineREWithLegacyFmt.test(line)) { |
| 178 return lineParserWithLegacyFmt; | 178 return lineParserWithLegacyFmt; |
| 179 } |
| 179 return undefined; | 180 return undefined; |
| 180 } | 181 } |
| 181 TestExports.autoDetectLineParser = autoDetectLineParser; | 182 TestExports.autoDetectLineParser = autoDetectLineParser; |
| 182 | 183 |
| 183 /** | 184 /** |
| 184 * Guesses whether the provided events is a Linux perf string. | 185 * Guesses whether the provided events is a Linux perf string. |
| 185 * Looks for the magic string "# tracer" at the start of the file, | 186 * Looks for the magic string "# tracer" at the start of the file, |
| 186 * or the typical task-pid-cpu-timestamp-function sequence of a typical | 187 * or the typical task-pid-cpu-timestamp-function sequence of a typical |
| 187 * trace's body. | 188 * trace's body. |
| 188 * | 189 * |
| 189 * @return {boolean} True when events is a linux perf array. | 190 * @return {boolean} True when events is a linux perf array. |
| 190 */ | 191 */ |
| 191 FTraceImporter.canImport = function(events) { | 192 FTraceImporter.canImport = function(events) { |
| 192 if (!(typeof(events) === 'string' || events instanceof String)) | 193 if (!(typeof(events) === 'string' || events instanceof String)) { |
| 193 return false; | 194 return false; |
| 195 } |
| 194 | 196 |
| 195 if (FTraceImporter._extractEventsFromSystraceHTML(events, false).ok) | 197 if (FTraceImporter._extractEventsFromSystraceHTML(events, false).ok) { |
| 196 return true; | 198 return true; |
| 199 } |
| 197 | 200 |
| 198 if (FTraceImporter._extractEventsFromSystraceMultiHTML(events, false).ok) | 201 if (FTraceImporter._extractEventsFromSystraceMultiHTML(events, false).ok) { |
| 199 return true; | 202 return true; |
| 203 } |
| 200 | 204 |
| 201 if (/^# tracer:/.test(events)) | 205 if (/^# tracer:/.test(events)) { |
| 202 return true; | 206 return true; |
| 207 } |
| 203 | 208 |
| 204 var lineBreakIndex = events.indexOf('\n'); | 209 var lineBreakIndex = events.indexOf('\n'); |
| 205 if (lineBreakIndex > -1) | 210 if (lineBreakIndex > -1) { |
| 206 events = events.substring(0, lineBreakIndex); | 211 events = events.substring(0, lineBreakIndex); |
| 212 } |
| 207 | 213 |
| 208 if (autoDetectLineParser(events)) | 214 if (autoDetectLineParser(events)) { |
| 209 return true; | 215 return true; |
| 216 } |
| 210 | 217 |
| 211 return false; | 218 return false; |
| 212 }; | 219 }; |
| 213 | 220 |
| 214 FTraceImporter._extractEventsFromSystraceHTML = function( | 221 FTraceImporter._extractEventsFromSystraceHTML = function( |
| 215 incomingEvents, produceResult) { | 222 incomingEvents, produceResult) { |
| 216 var failure = {ok: false}; | 223 var failure = {ok: false}; |
| 217 if (produceResult === undefined) | 224 if (produceResult === undefined) { |
| 218 produceResult = true; | 225 produceResult = true; |
| 226 } |
| 219 | 227 |
| 220 if (!/^<!DOCTYPE html>/.test(incomingEvents)) | 228 if (!/^<!DOCTYPE html>/.test(incomingEvents)) { |
| 221 return failure; | 229 return failure; |
| 230 } |
| 222 var r = new tr.importer.SimpleLineReader(incomingEvents); | 231 var r = new tr.importer.SimpleLineReader(incomingEvents); |
| 223 | 232 |
| 224 // Try to find the data... | 233 // Try to find the data... |
| 225 if (!r.advanceToLineMatching(/^ <script>$/)) | 234 if (!r.advanceToLineMatching(/^ <script>$/)) { |
| 226 return failure; | 235 return failure; |
| 227 if (!r.advanceToLineMatching(/^ var linuxPerfData = "\\$/)) | 236 } |
| 237 if (!r.advanceToLineMatching(/^ var linuxPerfData = "\\$/)) { |
| 228 return failure; | 238 return failure; |
| 239 } |
| 229 | 240 |
| 230 var eventsBeginAtLine = r.curLineNumber + 1; | 241 var eventsBeginAtLine = r.curLineNumber + 1; |
| 231 r.beginSavingLines(); | 242 r.beginSavingLines(); |
| 232 if (!r.advanceToLineMatching(/^ <\/script>$/)) | 243 if (!r.advanceToLineMatching(/^ <\/script>$/)) { |
| 233 return failure; | 244 return failure; |
| 245 } |
| 234 | 246 |
| 235 var rawEvents = r.endSavingLinesAndGetResult(); | 247 var rawEvents = r.endSavingLinesAndGetResult(); |
| 236 | 248 |
| 237 // Drop off first and last event as it contains the tag. | 249 // Drop off first and last event as it contains the tag. |
| 238 rawEvents = rawEvents.slice(1, rawEvents.length - 1); | 250 rawEvents = rawEvents.slice(1, rawEvents.length - 1); |
| 239 | 251 |
| 240 if (!r.advanceToLineMatching(/^<\/body>$/)) | 252 if (!r.advanceToLineMatching(/^<\/body>$/)) { |
| 241 return failure; | 253 return failure; |
| 242 if (!r.advanceToLineMatching(/^<\/html>$/)) | 254 } |
| 255 if (!r.advanceToLineMatching(/^<\/html>$/)) { |
| 243 return failure; | 256 return failure; |
| 257 } |
| 244 | 258 |
| 245 function endsWith(str, suffix) { | 259 function endsWith(str, suffix) { |
| 246 return str.indexOf(suffix, str.length - suffix.length) !== -1; | 260 return str.indexOf(suffix, str.length - suffix.length) !== -1; |
| 247 } | 261 } |
| 248 function stripSuffix(str, suffix) { | 262 function stripSuffix(str, suffix) { |
| 249 if (!endsWith(str, suffix)) | 263 if (!endsWith(str, suffix)) { |
| 250 return str; | 264 return str; |
| 265 } |
| 251 return str.substring(str, str.length - suffix.length); | 266 return str.substring(str, str.length - suffix.length); |
| 252 } | 267 } |
| 253 | 268 |
| 254 // Strip off escaping in the file needed to preserve linebreaks. | 269 // Strip off escaping in the file needed to preserve linebreaks. |
| 255 var events = []; | 270 var events = []; |
| 256 if (produceResult) { | 271 if (produceResult) { |
| 257 for (var i = 0; i < rawEvents.length; i++) { | 272 for (var i = 0; i < rawEvents.length; i++) { |
| 258 var event = rawEvents[i]; | 273 var event = rawEvents[i]; |
| 259 event = stripSuffix(event, '\\n\\'); | 274 event = stripSuffix(event, '\\n\\'); |
| 260 events.push(event); | 275 events.push(event); |
| 261 } | 276 } |
| 262 } else { | 277 } else { |
| 263 events = [rawEvents[rawEvents.length - 1]]; | 278 events = [rawEvents[rawEvents.length - 1]]; |
| 264 } | 279 } |
| 265 | 280 |
| 266 // Last event ends differently. Strip that off too, | 281 // Last event ends differently. Strip that off too, |
| 267 // treating absence of that trailing string as a failure. | 282 // treating absence of that trailing string as a failure. |
| 268 var oldLastEvent = events[events.length - 1]; | 283 var oldLastEvent = events[events.length - 1]; |
| 269 var newLastEvent = stripSuffix(oldLastEvent, '\\n";'); | 284 var newLastEvent = stripSuffix(oldLastEvent, '\\n";'); |
| 270 if (newLastEvent === oldLastEvent) | 285 if (newLastEvent === oldLastEvent) { |
| 271 return failure; | 286 return failure; |
| 287 } |
| 272 events[events.length - 1] = newLastEvent; | 288 events[events.length - 1] = newLastEvent; |
| 273 | 289 |
| 274 return {ok: true, | 290 return {ok: true, |
| 275 lines: produceResult ? events : undefined, | 291 lines: produceResult ? events : undefined, |
| 276 eventsBeginAtLine: eventsBeginAtLine}; | 292 eventsBeginAtLine: eventsBeginAtLine}; |
| 277 }; | 293 }; |
| 278 | 294 |
| 279 FTraceImporter._extractEventsFromSystraceMultiHTML = function( | 295 FTraceImporter._extractEventsFromSystraceMultiHTML = function( |
| 280 incomingEvents, produceResult) { | 296 incomingEvents, produceResult) { |
| 281 var failure = {ok: false}; | 297 var failure = {ok: false}; |
| 282 if (produceResult === undefined) | 298 if (produceResult === undefined) { |
| 283 produceResult = true; | 299 produceResult = true; |
| 300 } |
| 284 | 301 |
| 285 if (!(new RegExp('^<!DOCTYPE HTML>', 'i').test(incomingEvents))) | 302 if (!(new RegExp('^<!DOCTYPE HTML>', 'i').test(incomingEvents))) { |
| 286 return failure; | 303 return failure; |
| 304 } |
| 287 | 305 |
| 288 var r = new tr.importer.SimpleLineReader(incomingEvents); | 306 var r = new tr.importer.SimpleLineReader(incomingEvents); |
| 289 | 307 |
| 290 // Try to find the Linux perf trace in any of the trace-data tags | 308 // Try to find the Linux perf trace in any of the trace-data tags |
| 291 var events = []; | 309 var events = []; |
| 292 while (!/^# tracer:/.test(events)) { | 310 while (!/^# tracer:/.test(events)) { |
| 293 if (!r.advanceToLineMatching( | 311 if (!r.advanceToLineMatching( |
| 294 /^ <script class="trace-data" type="application\/text">$/)) | 312 /^ <script class="trace-data" type="application\/text">$/)) { |
| 295 return failure; | 313 return failure; |
| 314 } |
| 296 | 315 |
| 297 var eventsBeginAtLine = r.curLineNumber + 1; | 316 var eventsBeginAtLine = r.curLineNumber + 1; |
| 298 | 317 |
| 299 r.beginSavingLines(); | 318 r.beginSavingLines(); |
| 300 if (!r.advanceToLineMatching(/^ <\/script>$/)) | 319 if (!r.advanceToLineMatching(/^ <\/script>$/)) return failure; |
| 301 return failure; | |
| 302 | 320 |
| 303 events = r.endSavingLinesAndGetResult(); | 321 events = r.endSavingLinesAndGetResult(); |
| 304 | 322 |
| 305 // Drop off first and last event as it contains the tag. | 323 // Drop off first and last event as it contains the tag. |
| 306 events = events.slice(1, events.length - 1); | 324 events = events.slice(1, events.length - 1); |
| 307 } | 325 } |
| 308 | 326 |
| 309 if (!r.advanceToLineMatching(/^<\/body>$/)) | 327 if (!r.advanceToLineMatching(/^<\/body>$/)) { |
| 310 return failure; | 328 return failure; |
| 311 if (!r.advanceToLineMatching(/^<\/html>$/)) | 329 } |
| 330 if (!r.advanceToLineMatching(/^<\/html>$/)) { |
| 312 return failure; | 331 return failure; |
| 332 } |
| 313 | 333 |
| 314 return {ok: true, | 334 return {ok: true, |
| 315 lines: produceResult ? events : undefined, | 335 lines: produceResult ? events : undefined, |
| 316 eventsBeginAtLine: eventsBeginAtLine}; | 336 eventsBeginAtLine: eventsBeginAtLine}; |
| 317 }; | 337 }; |
| 318 | 338 |
| 319 FTraceImporter.prototype = { | 339 FTraceImporter.prototype = { |
| 320 __proto__: tr.importer.Importer.prototype, | 340 __proto__: tr.importer.Importer.prototype, |
| 321 | 341 |
| 322 get importerName() { | 342 get importerName() { |
| 323 return 'FTraceImporter'; | 343 return 'FTraceImporter'; |
| 324 }, | 344 }, |
| 325 | 345 |
| 326 get model() { | 346 get model() { |
| 327 return this.model_; | 347 return this.model_; |
| 328 }, | 348 }, |
| 329 | 349 |
| 330 /** | 350 /** |
| 331 * Imports clock sync markers into model_. | 351 * Imports clock sync markers into model_. |
| 332 */ | 352 */ |
| 333 importClockSyncMarkers: function() { | 353 importClockSyncMarkers: function() { |
| 334 this.lazyInit_(); | 354 this.lazyInit_(); |
| 335 | 355 |
| 336 this.forEachLine_(function(text, eventBase, cpuNumber, pid, ts) { | 356 this.forEachLine_(function(text, eventBase, cpuNumber, pid, ts) { |
| 337 var eventName = eventBase.eventName; | 357 var eventName = eventBase.eventName; |
| 338 if (eventName !== 'tracing_mark_write' && eventName !== '0') | 358 if (eventName !== 'tracing_mark_write' && eventName !== '0') { |
| 339 return; | 359 return; |
| 360 } |
| 340 | 361 |
| 341 if (traceEventClockSyncRE.exec(eventBase.details) || | 362 if (traceEventClockSyncRE.exec(eventBase.details) || |
| 342 genericClockSyncRE.exec(eventBase.details)) { | 363 genericClockSyncRE.exec(eventBase.details)) { |
| 343 this.traceClockSyncEvent_(eventName, cpuNumber, pid, ts, eventBase); | 364 this.traceClockSyncEvent_(eventName, cpuNumber, pid, ts, eventBase); |
| 344 } else if (realTimeClockSyncRE.exec(eventBase.details)) { | 365 } else if (realTimeClockSyncRE.exec(eventBase.details)) { |
| 345 // TODO(charliea): Migrate this sync to ClockSyncManager. | 366 // TODO(charliea): Migrate this sync to ClockSyncManager. |
| 346 // This entry syncs CLOCK_REALTIME with CLOCK_MONOTONIC. Store the | 367 // This entry syncs CLOCK_REALTIME with CLOCK_MONOTONIC. Store the |
| 347 // offset between the two in the model so that importers parsing files | 368 // offset between the two in the model so that importers parsing files |
| 348 // with CLOCK_REALTIME timestamps can map back to CLOCK_MONOTONIC. | 369 // with CLOCK_REALTIME timestamps can map back to CLOCK_MONOTONIC. |
| 349 var match = realTimeClockSyncRE.exec(eventBase.details); | 370 var match = realTimeClockSyncRE.exec(eventBase.details); |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 var SCHEDULING_STATE = tr.model.SCHEDULING_STATE; | 505 var SCHEDULING_STATE = tr.model.SCHEDULING_STATE; |
| 485 | 506 |
| 486 // Push the cpu slices to the threads that they run on. | 507 // Push the cpu slices to the threads that they run on. |
| 487 for (var cpuNumber in this.model_.kernel.cpus) { | 508 for (var cpuNumber in this.model_.kernel.cpus) { |
| 488 var cpu = this.model_.kernel.cpus[cpuNumber]; | 509 var cpu = this.model_.kernel.cpus[cpuNumber]; |
| 489 | 510 |
| 490 for (var i = 0; i < cpu.slices.length; i++) { | 511 for (var i = 0; i < cpu.slices.length; i++) { |
| 491 var cpuSlice = cpu.slices[i]; | 512 var cpuSlice = cpu.slices[i]; |
| 492 | 513 |
| 493 var thread = this.threadsByLinuxPid[cpuSlice.args.tid]; | 514 var thread = this.threadsByLinuxPid[cpuSlice.args.tid]; |
| 494 if (!thread) | 515 if (!thread) continue; |
| 495 continue; | |
| 496 | 516 |
| 497 cpuSlice.threadThatWasRunning = thread; | 517 cpuSlice.threadThatWasRunning = thread; |
| 498 | 518 |
| 499 if (!thread.tempCpuSlices) | 519 if (!thread.tempCpuSlices) { |
| 500 thread.tempCpuSlices = []; | 520 thread.tempCpuSlices = []; |
| 521 } |
| 501 thread.tempCpuSlices.push(cpuSlice); | 522 thread.tempCpuSlices.push(cpuSlice); |
| 502 } | 523 } |
| 503 } | 524 } |
| 504 | 525 |
| 505 for (var i in this.wakeups_) { | 526 for (var i in this.wakeups_) { |
| 506 var wakeup = this.wakeups_[i]; | 527 var wakeup = this.wakeups_[i]; |
| 507 var thread = this.threadsByLinuxPid[wakeup.tid]; | 528 var thread = this.threadsByLinuxPid[wakeup.tid]; |
| 508 if (!thread) | 529 if (!thread) continue; |
| 509 continue; | |
| 510 thread.tempWakeups = thread.tempWakeups || []; | 530 thread.tempWakeups = thread.tempWakeups || []; |
| 511 thread.tempWakeups.push(wakeup); | 531 thread.tempWakeups.push(wakeup); |
| 512 } | 532 } |
| 513 for (var i in this.blockedReasons_) { | 533 for (var i in this.blockedReasons_) { |
| 514 var reason = this.blockedReasons_[i]; | 534 var reason = this.blockedReasons_[i]; |
| 515 var thread = this.threadsByLinuxPid[reason.tid]; | 535 var thread = this.threadsByLinuxPid[reason.tid]; |
| 516 if (!thread) | 536 if (!thread) continue; |
| 517 continue; | |
| 518 thread.tempBlockedReasons = thread.tempBlockedReasons || []; | 537 thread.tempBlockedReasons = thread.tempBlockedReasons || []; |
| 519 thread.tempBlockedReasons.push(reason); | 538 thread.tempBlockedReasons.push(reason); |
| 520 } | 539 } |
| 521 | 540 |
| 522 // Create slices for when the thread is not running. | 541 // Create slices for when the thread is not running. |
| 523 this.model_.getAllThreads().forEach(function(thread) { | 542 this.model_.getAllThreads().forEach(function(thread) { |
| 524 if (thread.tempCpuSlices === undefined) | 543 if (thread.tempCpuSlices === undefined) return; |
| 525 return; | |
| 526 var origSlices = thread.tempCpuSlices; | 544 var origSlices = thread.tempCpuSlices; |
| 527 delete thread.tempCpuSlices; | 545 delete thread.tempCpuSlices; |
| 528 | 546 |
| 529 origSlices.sort(function(x, y) { | 547 origSlices.sort(function(x, y) { |
| 530 return x.start - y.start; | 548 return x.start - y.start; |
| 531 }); | 549 }); |
| 532 | 550 |
| 533 var wakeups = thread.tempWakeups || []; | 551 var wakeups = thread.tempWakeups || []; |
| 534 delete thread.tempWakeups; | 552 delete thread.tempWakeups; |
| 535 wakeups.sort(function(x, y) { | 553 wakeups.sort(function(x, y) { |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 732 if (event) { | 750 if (event) { |
| 733 // TODO(alexandermont): This section of code seems to be broken. It | 751 // TODO(alexandermont): This section of code seems to be broken. It |
| 734 // creates an "args" variable, but doesn't seem to do anything with it. | 752 // creates an "args" variable, but doesn't seem to do anything with it. |
| 735 var name = event[1]; | 753 var name = event[1]; |
| 736 var pieces = event[2].split(' '); | 754 var pieces = event[2].split(' '); |
| 737 var args = { | 755 var args = { |
| 738 perfTs: ts | 756 perfTs: ts |
| 739 }; | 757 }; |
| 740 for (var i = 0; i < pieces.length; i++) { | 758 for (var i = 0; i < pieces.length; i++) { |
| 741 var parts = pieces[i].split('='); | 759 var parts = pieces[i].split('='); |
| 742 if (parts.length !== 2) | 760 if (parts.length !== 2) { |
| 743 throw new Error('omgbbq'); | 761 throw new Error('omgbbq'); |
| 762 } |
| 744 args[parts[0]] = parts[1]; | 763 args[parts[0]] = parts[1]; |
| 745 } | 764 } |
| 746 | 765 |
| 747 this.model_.clockSyncManager.addClockSyncMarker( | 766 this.model_.clockSyncManager.addClockSyncMarker( |
| 748 tr.model.ClockDomainId.LINUX_FTRACE_GLOBAL, name, ts); | 767 tr.model.ClockDomainId.LINUX_FTRACE_GLOBAL, name, ts); |
| 749 return true; | 768 return true; |
| 750 } | 769 } |
| 751 | 770 |
| 752 // Check to see if we have a "new style" clock sync marker that contains | 771 // Check to see if we have a "new style" clock sync marker that contains |
| 753 // only a sync ID. | 772 // only a sync ID. |
| 754 var event = /name=([\w\-]+)/.exec(eventBase.details); | 773 var event = /name=([\w\-]+)/.exec(eventBase.details); |
| 755 if (event) { | 774 if (event) { |
| 756 this.model_.clockSyncManager.addClockSyncMarker( | 775 this.model_.clockSyncManager.addClockSyncMarker( |
| 757 tr.model.ClockDomainId.LINUX_FTRACE_GLOBAL, event[1], ts); | 776 tr.model.ClockDomainId.LINUX_FTRACE_GLOBAL, event[1], ts); |
| 758 return true; | 777 return true; |
| 759 } | 778 } |
| 760 | 779 |
| 761 // Check to see if we have a special clock sync marker that contains both | 780 // Check to see if we have a special clock sync marker that contains both |
| 762 // the current "ftrace global" time and the current CLOCK_MONOTONIC time. | 781 // the current "ftrace global" time and the current CLOCK_MONOTONIC time. |
| 763 event = /parent_ts=(\d+\.?\d*)/.exec(eventBase.details); | 782 event = /parent_ts=(\d+\.?\d*)/.exec(eventBase.details); |
| 764 if (!event) | 783 if (!event) return false; |
| 765 return false; | |
| 766 | 784 |
| 767 var monotonicTs = event[1] * 1000; | 785 var monotonicTs = event[1] * 1000; |
| 768 // A monotonic timestamp of zero is used as a sentinel value to indicate | 786 // A monotonic timestamp of zero is used as a sentinel value to indicate |
| 769 // that CLOCK_MONOTONIC and the ftrace global clock are identical. | 787 // that CLOCK_MONOTONIC and the ftrace global clock are identical. |
| 770 if (monotonicTs === 0) | 788 if (monotonicTs === 0) monotonicTs = ts; |
| 771 monotonicTs = ts; | |
| 772 | 789 |
| 773 if (this.haveClockSyncedMonotonicToGlobal_) | 790 if (this.haveClockSyncedMonotonicToGlobal_) { |
| 774 // ftrace sometimes includes multiple clock syncs between the monotonic | 791 // ftrace sometimes includes multiple clock syncs between the monotonic |
| 775 // and global clocks within a single trace. We protect against this by | 792 // and global clocks within a single trace. We protect against this by |
| 776 // only taking the first one into account. | 793 // only taking the first one into account. |
| 777 return true; | 794 return true; |
| 795 } |
| 778 | 796 |
| 779 // We have a clock sync event that contains two timestamps: a timestamp | 797 // We have a clock sync event that contains two timestamps: a timestamp |
| 780 // according to the ftrace 'global' clock, and that same timestamp | 798 // according to the ftrace 'global' clock, and that same timestamp |
| 781 // according to clock_gettime(CLOCK_MONOTONIC). | 799 // according to clock_gettime(CLOCK_MONOTONIC). |
| 782 this.model_.clockSyncManager.addClockSyncMarker( | 800 this.model_.clockSyncManager.addClockSyncMarker( |
| 783 tr.model.ClockDomainId.LINUX_FTRACE_GLOBAL, | 801 tr.model.ClockDomainId.LINUX_FTRACE_GLOBAL, |
| 784 MONOTONIC_TO_FTRACE_GLOBAL_SYNC_ID, ts); | 802 MONOTONIC_TO_FTRACE_GLOBAL_SYNC_ID, ts); |
| 785 this.model_.clockSyncManager.addClockSyncMarker( | 803 this.model_.clockSyncManager.addClockSyncMarker( |
| 786 tr.model.ClockDomainId.LINUX_CLOCK_MONOTONIC, | 804 tr.model.ClockDomainId.LINUX_CLOCK_MONOTONIC, |
| 787 MONOTONIC_TO_FTRACE_GLOBAL_SYNC_ID, monotonicTs); | 805 MONOTONIC_TO_FTRACE_GLOBAL_SYNC_ID, monotonicTs); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 }.bind(this)); | 868 }.bind(this)); |
| 851 }, | 869 }, |
| 852 | 870 |
| 853 /** | 871 /** |
| 854 * Walks the this.events_ structure and populates this.lines_. | 872 * Walks the this.events_ structure and populates this.lines_. |
| 855 */ | 873 */ |
| 856 parseLines_: function() { | 874 parseLines_: function() { |
| 857 var lines = []; | 875 var lines = []; |
| 858 var extractResult = FTraceImporter._extractEventsFromSystraceHTML( | 876 var extractResult = FTraceImporter._extractEventsFromSystraceHTML( |
| 859 this.events_, true); | 877 this.events_, true); |
| 860 if (!extractResult.ok) | 878 if (!extractResult.ok) { |
| 861 extractResult = FTraceImporter._extractEventsFromSystraceMultiHTML( | 879 extractResult = FTraceImporter._extractEventsFromSystraceMultiHTML( |
| 862 this.events_, true); | 880 this.events_, true); |
| 881 } |
| 863 var lines = extractResult.ok ? | 882 var lines = extractResult.ok ? |
| 864 extractResult.lines : this.events_.split('\n'); | 883 extractResult.lines : this.events_.split('\n'); |
| 865 | 884 |
| 866 var lineParser = undefined; | 885 var lineParser = undefined; |
| 867 for (var lineNumber = 0; lineNumber < lines.length; ++lineNumber) { | 886 for (var lineNumber = 0; lineNumber < lines.length; ++lineNumber) { |
| 868 var line = lines[lineNumber].trim(); | 887 var line = lines[lineNumber].trim(); |
| 869 if (line.length === 0 || /^#/.test(line)) | 888 if (line.length === 0 || /^#/.test(line)) continue; |
| 870 continue; | |
| 871 | 889 |
| 872 if (!lineParser) { | 890 if (!lineParser) { |
| 873 lineParser = autoDetectLineParser(line); | 891 lineParser = autoDetectLineParser(line); |
| 874 if (!lineParser) { | 892 if (!lineParser) { |
| 875 this.model_.importWarning({ | 893 this.model_.importWarning({ |
| 876 type: 'parse_error', | 894 type: 'parse_error', |
| 877 message: 'Cannot parse line: ' + line | 895 message: 'Cannot parse line: ' + line |
| 878 }); | 896 }); |
| 879 continue; | 897 continue; |
| 880 } | 898 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 922 }; | 940 }; |
| 923 | 941 |
| 924 tr.importer.Importer.register(FTraceImporter); | 942 tr.importer.Importer.register(FTraceImporter); |
| 925 | 943 |
| 926 return { | 944 return { |
| 927 FTraceImporter, | 945 FTraceImporter, |
| 928 _FTraceImporterTestExports: TestExports | 946 _FTraceImporterTestExports: TestExports |
| 929 }; | 947 }; |
| 930 }); | 948 }); |
| 931 </script> | 949 </script> |
| OLD | NEW |