Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 /* Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 * Use of this source code is governed by a BSD-style license that can be | 2 * Use of this source code is governed by a BSD-style license that can be |
| 3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
| 4 */ | 4 */ |
| 5 | 5 |
| 6 | 6 |
| 7 /* XRay -- a simple profiler for Native Client */ | 7 /* XRay -- a simple profiler for Native Client */ |
| 8 | 8 |
| 9 #include <assert.h> | 9 #include <assert.h> |
| 10 #include <errno.h> | 10 #include <errno.h> |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 33 #define GTSC(_x) __asm__ __volatile__ ("rdtsc" : "=A" (_x)); | 33 #define GTSC(_x) __asm__ __volatile__ ("rdtsc" : "=A" (_x)); |
| 34 #else | 34 #else |
| 35 FORCE_INLINE uint64_t GTOD() { | 35 FORCE_INLINE uint64_t GTOD() { |
| 36 struct timeval tv; | 36 struct timeval tv; |
| 37 gettimeofday(&tv, NULL); | 37 gettimeofday(&tv, NULL); |
| 38 return (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec; | 38 return (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec; |
| 39 } | 39 } |
| 40 #define GTSC(_x) _x = GTOD(); | 40 #define GTSC(_x) _x = GTOD(); |
| 41 #endif | 41 #endif |
| 42 | 42 |
| 43 | |
| 44 /* Use a TLS variable for cheap thread uid. */ | 43 /* Use a TLS variable for cheap thread uid. */ |
| 45 __thread struct XRayTraceCapture* g_xray_capture = NULL; | 44 __thread struct XRayTraceCapture* g_xray_capture = NULL; |
| 46 | 45 |
| 47 | 46 |
| 48 struct XRayTraceStackEntry { | 47 struct XRayTraceStackEntry { |
| 49 uint32_t depth_addr; | 48 uint32_t depth_addr; |
| 50 uint64_t tsc; | 49 uint64_t tsc; |
| 51 uint32_t dest; | 50 uint32_t dest; |
| 52 uint32_t annotation_index; | 51 uint32_t annotation_index; |
| 53 }; | 52 }; |
| 54 | 53 |
| 55 | 54 |
| 56 struct XRayTraceFrameEntry { | 55 struct XRayTraceFrameEntry { |
| 57 /* Indices into global tracebuffer */ | 56 /* Indices into global tracebuffer */ |
| 58 int start; | 57 int start; |
| 59 int end; | 58 int end; |
| 60 uint64_t start_tsc; | 59 uint64_t start_tsc; |
| 61 uint64_t end_tsc; | 60 uint64_t end_tsc; |
| 62 uint64_t total_ticks; | 61 uint64_t total_ticks; |
| 63 int annotation_count; | 62 int annotation_count; |
| 64 bool valid; | 63 bool valid; |
| 64 | |
| 65 #ifndef XRAY_DISABLE_BROWSER_INTEGRATION | |
| 66 struct XRayTimestampPair start_time; | |
| 67 struct XRayTimestampPair end_time; | |
| 68 #endif | |
| 65 }; | 69 }; |
| 66 | 70 |
| 67 | 71 |
| 68 struct XRayTraceFrame { | 72 struct XRayTraceFrame { |
| 69 struct XRayTraceFrameEntry* entry; | 73 struct XRayTraceFrameEntry* entry; |
| 70 int head; | 74 int head; |
| 71 int tail; | 75 int tail; |
| 72 int count; | 76 int count; |
| 73 }; | 77 }; |
| 74 | 78 |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 86 bool initialized; | 90 bool initialized; |
| 87 uint32_t annotation_filter; | 91 uint32_t annotation_filter; |
| 88 uint32_t guard0; | 92 uint32_t guard0; |
| 89 struct XRayTraceStackEntry stack[XRAY_TRACE_STACK_SIZE] XRAY_ALIGN64; | 93 struct XRayTraceStackEntry stack[XRAY_TRACE_STACK_SIZE] XRAY_ALIGN64; |
| 90 uint32_t guard1; | 94 uint32_t guard1; |
| 91 uint32_t guard2; | 95 uint32_t guard2; |
| 92 char annotation[XRAY_ANNOTATION_STACK_SIZE] XRAY_ALIGN64; | 96 char annotation[XRAY_ANNOTATION_STACK_SIZE] XRAY_ALIGN64; |
| 93 uint32_t guard3; | 97 uint32_t guard3; |
| 94 struct XRayTraceBufferEntry* buffer; | 98 struct XRayTraceBufferEntry* buffer; |
| 95 struct XRayTraceFrame frame; | 99 struct XRayTraceFrame frame; |
| 100 | |
| 101 #ifndef XRAY_DISABLE_BROWSER_INTEGRATION | |
| 102 int32_t thread_id; | |
| 103 #endif | |
| 96 } XRAY_ALIGN64; | 104 } XRAY_ALIGN64; |
| 97 | 105 |
| 98 | 106 |
| 99 #ifdef __cplusplus | 107 #ifdef __cplusplus |
| 100 extern "C" { | 108 extern "C" { |
| 101 #endif | 109 #endif |
| 102 | 110 |
| 103 XRAY_NO_INSTRUMENT void __cyg_profile_func_enter(void* this_fn, | 111 #if defined(__pnacl__) |
| 104 void* call_site); | 112 XRAY_NO_INSTRUMENT void __pnacl_profile_func_enter(const char* fname); |
| 105 XRAY_NO_INSTRUMENT void __cyg_profile_func_exit(void* this_fn, | 113 XRAY_NO_INSTRUMENT void __pnacl_profile_func_exit(const char* fname); |
| 106 void* call_site); | 114 #else |
| 115 XRAY_NO_INSTRUMENT void __cyg_profile_func_enter( | |
| 116 void* this_fn, void* call_site); | |
| 117 XRAY_NO_INSTRUMENT void __cyg_profile_func_exit(void* this_fn, void* call_site); | |
| 118 #endif | |
| 119 | |
| 107 XRAY_NO_INSTRUMENT void __xray_profile_append_annotation( | 120 XRAY_NO_INSTRUMENT void __xray_profile_append_annotation( |
| 108 struct XRayTraceCapture* capture, | 121 struct XRayTraceCapture* capture, |
| 109 struct XRayTraceStackEntry* se, | 122 struct XRayTraceStackEntry* se, |
| 110 struct XRayTraceBufferEntry* be); | 123 struct XRayTraceBufferEntry* be); |
| 111 | 124 |
| 112 #ifdef __cplusplus | 125 #ifdef __cplusplus |
| 113 } | 126 } |
| 114 #endif | 127 #endif |
| 115 | 128 |
| 116 | |
| 117 /* Asserts that the guard values haven't changed. */ | 129 /* Asserts that the guard values haven't changed. */ |
| 118 void XRayCheckGuards(struct XRayTraceCapture* capture) { | 130 void XRayCheckGuards(struct XRayTraceCapture* capture) { |
| 119 assert(capture->guard0 == XRAY_GUARD_VALUE_0x12345678); | 131 assert(capture->guard0 == XRAY_GUARD_VALUE_0x12345678); |
| 120 assert(capture->guard1 == XRAY_GUARD_VALUE_0x12345678); | 132 assert(capture->guard1 == XRAY_GUARD_VALUE_0x12345678); |
| 121 assert(capture->guard2 == XRAY_GUARD_VALUE_0x87654321); | 133 assert(capture->guard2 == XRAY_GUARD_VALUE_0x87654321); |
| 122 assert(capture->guard3 == XRAY_GUARD_VALUE_0x12345678); | 134 assert(capture->guard3 == XRAY_GUARD_VALUE_0x12345678); |
| 123 } | 135 } |
| 124 | 136 |
| 125 /* Decrements the trace index, wrapping around if needed. */ | 137 /* Decrements the trace index, wrapping around if needed. */ |
| 126 XRAY_FORCE_INLINE int XRayTraceDecrementIndexInline( | 138 XRAY_FORCE_INLINE int XRayTraceDecrementIndexInline( |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 } | 308 } |
| 297 | 309 |
| 298 | 310 |
| 299 /* Generic memory free for XRay */ | 311 /* Generic memory free for XRay */ |
| 300 void XRayFree(void* data) { | 312 void XRayFree(void* data) { |
| 301 assert(NULL != data); | 313 assert(NULL != data); |
| 302 free(data); | 314 free(data); |
| 303 } | 315 } |
| 304 | 316 |
| 305 | 317 |
| 306 | 318 #if defined(__pnacl__) |
| 307 /* Main profile capture function that is called at the start */ | 319 /* Main profile capture function that is called at the start */ |
| 308 /* of every instrumented function. This function is implicitly */ | 320 /* of every instrumented function. This function is implicitly */ |
| 309 /* called when code is compilied with the -finstrument-functions option */ | 321 /* called when code is compilied with the -finstrument-functions option */ |
| 322 void __pnacl_profile_func_enter(const char* fname) { | |
|
nfullagar1
2013/07/18 00:47:22
(you may have missed this one from last round)
sug
| |
| 323 struct XRayTraceCapture* capture = g_xray_capture; | |
| 324 if (capture && capture->recording) { | |
| 325 uint32_t depth = capture->stack_depth; | |
| 326 if (depth < capture->max_stack_depth) { | |
| 327 struct XRayTraceStackEntry* se = &capture->stack[depth]; | |
| 328 uint32_t addr = (uint32_t)fname; | |
| 329 se->depth_addr = XRAY_PACK_DEPTH_ADDR(depth, addr); | |
| 330 se->dest = capture->buffer_index; | |
| 331 se->annotation_index = 0; | |
| 332 GTSC(se->tsc); | |
| 333 capture->buffer_index = | |
| 334 XRayTraceIncrementIndexInline(capture, capture->buffer_index); | |
| 335 } | |
| 336 ++capture->stack_depth; | |
| 337 } | |
| 338 } | |
| 339 | |
| 340 | |
| 341 /* Main profile capture function that is called at the exit of */ | |
| 342 /* every instrumented function. This function is implicity called */ | |
| 343 /* when the code is compiled with the -finstrument-functions option */ | |
| 344 void __pnacl_profile_func_exit(const char* fname) { | |
| 345 struct XRayTraceCapture* capture = g_xray_capture; | |
| 346 if (capture && capture->recording) { | |
| 347 --capture->stack_depth; | |
| 348 if (capture->stack_depth < capture->max_stack_depth) { | |
| 349 uint32_t depth = capture->stack_depth; | |
| 350 struct XRayTraceStackEntry* se = &capture->stack[depth]; | |
| 351 uint32_t buffer_index = se->dest; | |
| 352 uint64_t tsc; | |
| 353 struct XRayTraceBufferEntry* be = &capture->buffer[buffer_index]; | |
| 354 GTSC(tsc); | |
| 355 be->depth_addr = se->depth_addr; | |
| 356 be->start_tick = se->tsc; | |
| 357 be->end_tick = tsc; | |
| 358 be->annotation_index = 0; | |
| 359 if (0 != se->annotation_index) | |
| 360 __xray_profile_append_annotation(capture, se, be); | |
| 361 } | |
| 362 } | |
| 363 } | |
| 364 #else | |
| 365 /* Main profile capture function that is called at the start */ | |
| 366 /* of every instrumented function. This function is implicitly */ | |
| 367 /* called when code is compilied with the -finstrument-functions option */ | |
| 310 void __cyg_profile_func_enter(void* this_fn, void* call_site) { | 368 void __cyg_profile_func_enter(void* this_fn, void* call_site) { |
| 311 struct XRayTraceCapture* capture = g_xray_capture; | 369 struct XRayTraceCapture* capture = g_xray_capture; |
| 312 if (capture && capture->recording) { | 370 if (capture && capture->recording) { |
| 313 uint32_t depth = capture->stack_depth; | 371 uint32_t depth = capture->stack_depth; |
| 314 if (depth < capture->max_stack_depth) { | 372 if (depth < capture->max_stack_depth) { |
| 315 struct XRayTraceStackEntry* se = &capture->stack[depth]; | 373 struct XRayTraceStackEntry* se = &capture->stack[depth]; |
| 316 uint32_t addr = (uint32_t)this_fn; | 374 uint32_t addr = (uint32_t)this_fn; |
| 317 se->depth_addr = XRAY_PACK_DEPTH_ADDR(depth, addr); | 375 se->depth_addr = XRAY_PACK_DEPTH_ADDR(depth, addr); |
| 318 se->dest = capture->buffer_index; | 376 se->dest = capture->buffer_index; |
| 319 se->annotation_index = 0; | 377 se->annotation_index = 0; |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 342 GTSC(tsc); | 400 GTSC(tsc); |
| 343 be->depth_addr = se->depth_addr; | 401 be->depth_addr = se->depth_addr; |
| 344 be->start_tick = se->tsc; | 402 be->start_tick = se->tsc; |
| 345 be->end_tick = tsc; | 403 be->end_tick = tsc; |
| 346 be->annotation_index = 0; | 404 be->annotation_index = 0; |
| 347 if (0 != se->annotation_index) | 405 if (0 != se->annotation_index) |
| 348 __xray_profile_append_annotation(capture, se, be); | 406 __xray_profile_append_annotation(capture, se, be); |
| 349 } | 407 } |
| 350 } | 408 } |
| 351 } | 409 } |
| 410 #endif /* __pnacl__ */ | |
| 352 | 411 |
| 412 #ifndef XRAY_DISABLE_BROWSER_INTEGRATION | |
| 413 void XRayGetTSC(uint64_t* tsc) {GTSC(*tsc);} | |
|
nfullagar1
2013/07/18 00:47:22
above: unless it is inlined in a class, avoid putt
grosse
2013/07/18 01:26:40
Done.
| |
| 414 | |
| 415 int32_t XRayGetThreadID(struct XRayTraceCapture* capture) { | |
|
nfullagar1
2013/07/18 00:47:22
Need a brief comment here that ret val is the thre
grosse
2013/07/18 01:26:40
Done.
| |
| 416 return capture->thread_id; | |
| 417 } | |
| 418 | |
| 419 struct XRayTimestampPair* XRayGetTimestamp( | |
| 420 struct XRayTraceCapture* capture, int frame, bool end) { | |
| 421 | |
| 422 struct XRayTraceFrameEntry* entry = &(capture->frame.entry[frame]); | |
| 423 return end ? &entry->end_time : &entry->start_time; | |
| 424 } | |
| 425 #endif | |
| 353 | 426 |
| 354 /* Special case appending annotation string to trace buffer */ | 427 /* Special case appending annotation string to trace buffer */ |
| 355 /* this function should only ever be called from __cyg_profile_func_exit() */ | 428 /* this function should only ever be called from __cyg_profile_func_exit() */ |
| 356 void __xray_profile_append_annotation(struct XRayTraceCapture* capture, | 429 void __xray_profile_append_annotation(struct XRayTraceCapture* capture, |
| 357 struct XRayTraceStackEntry* se, | 430 struct XRayTraceStackEntry* se, |
| 358 struct XRayTraceBufferEntry* be) { | 431 struct XRayTraceBufferEntry* be) { |
| 359 struct XRayTraceStackEntry* parent = se - 1; | 432 struct XRayTraceStackEntry* parent = se - 1; |
| 360 int start = parent->annotation_index; | 433 int start = parent->annotation_index; |
| 361 be->annotation_index = capture->buffer_index; | 434 be->annotation_index = capture->buffer_index; |
| 362 char* str = &capture->annotation[start]; | 435 char* str = &capture->annotation[start]; |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 566 /* The trace stack[0] is reserved */ | 639 /* The trace stack[0] is reserved */ |
| 567 memset(&capture->stack[0], 0, sizeof(capture->stack[0])); | 640 memset(&capture->stack[0], 0, sizeof(capture->stack[0])); |
| 568 /* Annotation index 0 is reserved to indicate no annotation */ | 641 /* Annotation index 0 is reserved to indicate no annotation */ |
| 569 capture->stack[0].annotation_index = 1; | 642 capture->stack[0].annotation_index = 1; |
| 570 capture->annotation[0] = 0; | 643 capture->annotation[0] = 0; |
| 571 capture->annotation[1] = 0; | 644 capture->annotation[1] = 0; |
| 572 capture->annotation_count = 0; | 645 capture->annotation_count = 0; |
| 573 capture->recording = true; | 646 capture->recording = true; |
| 574 GTSC(capture->frame.entry[i].start_tsc); | 647 GTSC(capture->frame.entry[i].start_tsc); |
| 575 g_xray_capture = capture; | 648 g_xray_capture = capture; |
| 649 | |
| 650 #ifndef XRAY_DISABLE_BROWSER_INTEGRATION | |
| 651 capture->frame.entry[i].start_time = XRayGenerateTimestampsNow(); | |
| 652 #endif /* XRAY_DISABLE_BROWSER_INTEGRATION */ | |
|
nfullagar1
2013/07/18 00:47:22
code style is to have two spaces between #endif an
grosse
2013/07/18 01:26:40
Done.
| |
| 653 | |
| 576 } | 654 } |
| 577 | 655 |
| 578 | 656 |
| 579 /* Ends a frame and disables capturing. Advances to the next frame. */ | 657 /* Ends a frame and disables capturing. Advances to the next frame. */ |
| 580 /* Must be paired with XRayStartFrame(), and called from the same thread. */ | 658 /* Must be paired with XRayStartFrame(), and called from the same thread. */ |
| 581 void XRayEndFrame(struct XRayTraceCapture* capture) { | 659 void XRayEndFrame(struct XRayTraceCapture* capture) { |
| 582 int i; | 660 int i; |
| 583 assert(capture); | 661 assert(capture); |
| 584 assert(capture->initialized); | 662 assert(capture->initialized); |
| 585 assert(capture->recording); | 663 assert(capture->recording); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 605 if (be->depth_addr != XRAY_FRAME_MARKER) { | 683 if (be->depth_addr != XRAY_FRAME_MARKER) { |
| 606 fprintf(stderr, | 684 fprintf(stderr, |
| 607 "XRay: XRayStopFrame() detects insufficient trace buffer size!\n"); | 685 "XRay: XRayStopFrame() detects insufficient trace buffer size!\n"); |
| 608 XRayReset(capture); | 686 XRayReset(capture); |
| 609 } else { | 687 } else { |
| 610 /* Replace marker with an empty annotation string. */ | 688 /* Replace marker with an empty annotation string. */ |
| 611 be->depth_addr = XRAY_NULL_ANNOTATION; | 689 be->depth_addr = XRAY_NULL_ANNOTATION; |
| 612 XRayCheckGuards(capture); | 690 XRayCheckGuards(capture); |
| 613 } | 691 } |
| 614 g_xray_capture = NULL; | 692 g_xray_capture = NULL; |
| 693 | |
| 694 #ifndef XRAY_DISABLE_BROWSER_INTEGRATION | |
| 695 capture->frame.entry[i].end_time = XRayGenerateTimestampsNow(); | |
| 696 #endif /* XRAY_DISABLE_BROWSER_INTEGRATION */ | |
| 615 } | 697 } |
| 616 | 698 |
| 617 | 699 |
| 618 /* Get the last frame captured. Do not call while capturing. */ | 700 /* Get the last frame captured. Do not call while capturing. */ |
| 619 /* (ie call outside of XRayStartFrame() / XRayStopFrame() pair) */ | 701 /* (ie call outside of XRayStartFrame() / XRayStopFrame() pair) */ |
| 620 int XRayGetLastFrame(struct XRayTraceCapture* capture) { | 702 int XRayGetLastFrame(struct XRayTraceCapture* capture) { |
| 621 assert(capture); | 703 assert(capture); |
| 622 assert(capture->initialized); | 704 assert(capture->initialized); |
| 623 assert(!capture->recording); | 705 assert(!capture->recording); |
| 624 assert(0 == capture->disabled); | 706 assert(0 == capture->disabled); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 692 capture->recording = false; | 774 capture->recording = false; |
| 693 XRaySetMaxStackDepth(capture, stack_depth); | 775 XRaySetMaxStackDepth(capture, stack_depth); |
| 694 XRayReset(capture); | 776 XRayReset(capture); |
| 695 | 777 |
| 696 /* Mapfile is optional; we don't need it for captures, only for reports. */ | 778 /* Mapfile is optional; we don't need it for captures, only for reports. */ |
| 697 capture->symbols = | 779 capture->symbols = |
| 698 XRaySymbolTableCreate(XRAY_DEFAULT_SYMBOL_TABLE_SIZE); | 780 XRaySymbolTableCreate(XRAY_DEFAULT_SYMBOL_TABLE_SIZE); |
| 699 if (NULL != mapfilename) | 781 if (NULL != mapfilename) |
| 700 XRaySymbolTableParseMapfile(capture->symbols, mapfilename); | 782 XRaySymbolTableParseMapfile(capture->symbols, mapfilename); |
| 701 | 783 |
| 784 #ifndef XRAY_DISABLE_BROWSER_INTEGRATION | |
| 785 capture->thread_id = (int32_t)(&g_xray_capture); | |
|
nfullagar1
2013/07/18 00:47:22
Suggest having a separate '__thread int g_xray_tid
grosse
2013/07/18 01:26:40
Done.
| |
| 786 #endif | |
| 787 | |
| 702 return capture; | 788 return capture; |
| 703 } | 789 } |
| 704 | 790 |
| 705 | 791 |
| 706 /* Shut down and free memory used by XRay. */ | 792 /* Shut down and free memory used by XRay. */ |
| 707 void XRayShutdown(struct XRayTraceCapture* capture) { | 793 void XRayShutdown(struct XRayTraceCapture* capture) { |
| 708 assert(capture); | 794 assert(capture); |
| 709 assert(capture->initialized); | 795 assert(capture->initialized); |
| 710 assert(!capture->recording); | 796 assert(!capture->recording); |
| 711 XRayCheckGuards(capture); | 797 XRayCheckGuards(capture); |
| 712 if (NULL != capture->symbols) { | 798 if (NULL != capture->symbols) { |
| 713 XRaySymbolTableFree(capture->symbols); | 799 XRaySymbolTableFree(capture->symbols); |
| 714 } | 800 } |
| 715 XRayFree(capture->frame.entry); | 801 XRayFree(capture->frame.entry); |
| 716 XRayFree(capture->buffer); | 802 XRayFree(capture->buffer); |
| 717 capture->initialized = false; | 803 capture->initialized = false; |
| 718 XRayFree(capture); | 804 XRayFree(capture); |
| 719 } | 805 } |
| 720 | 806 |
| 721 #endif /* XRAY */ | 807 #endif /* XRAY */ |
| OLD | NEW |