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; |
| 45 __thread int g_xray_thread_id_placeholder = 0; |
46 | 46 |
47 | 47 |
48 struct XRayTraceStackEntry { | 48 struct XRayTraceStackEntry { |
49 uint32_t depth_addr; | 49 uint32_t depth_addr; |
50 uint64_t tsc; | 50 uint64_t tsc; |
51 uint32_t dest; | 51 uint32_t dest; |
52 uint32_t annotation_index; | 52 uint32_t annotation_index; |
53 }; | 53 }; |
54 | 54 |
55 | 55 |
56 struct XRayTraceFrameEntry { | 56 struct XRayTraceFrameEntry { |
57 /* Indices into global tracebuffer */ | 57 /* Indices into global tracebuffer */ |
58 int start; | 58 int start; |
59 int end; | 59 int end; |
60 uint64_t start_tsc; | 60 uint64_t start_tsc; |
61 uint64_t end_tsc; | 61 uint64_t end_tsc; |
62 uint64_t total_ticks; | 62 uint64_t total_ticks; |
63 int annotation_count; | 63 int annotation_count; |
64 bool valid; | 64 bool valid; |
| 65 |
| 66 #ifndef XRAY_DISABLE_BROWSER_INTEGRATION |
| 67 struct XRayTimestampPair start_time; |
| 68 struct XRayTimestampPair end_time; |
| 69 #endif |
65 }; | 70 }; |
66 | 71 |
67 | 72 |
68 struct XRayTraceFrame { | 73 struct XRayTraceFrame { |
69 struct XRayTraceFrameEntry* entry; | 74 struct XRayTraceFrameEntry* entry; |
70 int head; | 75 int head; |
71 int tail; | 76 int tail; |
72 int count; | 77 int count; |
73 }; | 78 }; |
74 | 79 |
(...skipping 11 matching lines...) Expand all Loading... |
86 bool initialized; | 91 bool initialized; |
87 uint32_t annotation_filter; | 92 uint32_t annotation_filter; |
88 uint32_t guard0; | 93 uint32_t guard0; |
89 struct XRayTraceStackEntry stack[XRAY_TRACE_STACK_SIZE] XRAY_ALIGN64; | 94 struct XRayTraceStackEntry stack[XRAY_TRACE_STACK_SIZE] XRAY_ALIGN64; |
90 uint32_t guard1; | 95 uint32_t guard1; |
91 uint32_t guard2; | 96 uint32_t guard2; |
92 char annotation[XRAY_ANNOTATION_STACK_SIZE] XRAY_ALIGN64; | 97 char annotation[XRAY_ANNOTATION_STACK_SIZE] XRAY_ALIGN64; |
93 uint32_t guard3; | 98 uint32_t guard3; |
94 struct XRayTraceBufferEntry* buffer; | 99 struct XRayTraceBufferEntry* buffer; |
95 struct XRayTraceFrame frame; | 100 struct XRayTraceFrame frame; |
| 101 |
| 102 #ifndef XRAY_DISABLE_BROWSER_INTEGRATION |
| 103 int32_t thread_id; |
| 104 #endif |
96 } XRAY_ALIGN64; | 105 } XRAY_ALIGN64; |
97 | 106 |
98 | 107 |
99 #ifdef __cplusplus | 108 #ifdef __cplusplus |
100 extern "C" { | 109 extern "C" { |
101 #endif | 110 #endif |
102 | 111 |
| 112 #if defined(__pnacl__) |
| 113 XRAY_NO_INSTRUMENT void __pnacl_profile_func_enter(const char* fname); |
| 114 XRAY_NO_INSTRUMENT void __pnacl_profile_func_exit(const char* fname); |
| 115 #else |
103 XRAY_NO_INSTRUMENT void __cyg_profile_func_enter(void* this_fn, | 116 XRAY_NO_INSTRUMENT void __cyg_profile_func_enter(void* this_fn, |
104 void* call_site); | 117 void* call_site); |
105 XRAY_NO_INSTRUMENT void __cyg_profile_func_exit(void* this_fn, | 118 XRAY_NO_INSTRUMENT void __cyg_profile_func_exit(void* this_fn, |
106 void* call_site); | 119 void* call_site); |
| 120 #endif |
| 121 |
107 XRAY_NO_INSTRUMENT void __xray_profile_append_annotation( | 122 XRAY_NO_INSTRUMENT void __xray_profile_append_annotation( |
108 struct XRayTraceCapture* capture, | 123 struct XRayTraceCapture* capture, |
109 struct XRayTraceStackEntry* se, | 124 struct XRayTraceStackEntry* se, |
110 struct XRayTraceBufferEntry* be); | 125 struct XRayTraceBufferEntry* be); |
111 | 126 |
112 #ifdef __cplusplus | 127 #ifdef __cplusplus |
113 } | 128 } |
114 #endif | 129 #endif |
115 | 130 |
116 | |
117 /* Asserts that the guard values haven't changed. */ | 131 /* Asserts that the guard values haven't changed. */ |
118 void XRayCheckGuards(struct XRayTraceCapture* capture) { | 132 void XRayCheckGuards(struct XRayTraceCapture* capture) { |
119 assert(capture->guard0 == XRAY_GUARD_VALUE_0x12345678); | 133 assert(capture->guard0 == XRAY_GUARD_VALUE_0x12345678); |
120 assert(capture->guard1 == XRAY_GUARD_VALUE_0x12345678); | 134 assert(capture->guard1 == XRAY_GUARD_VALUE_0x12345678); |
121 assert(capture->guard2 == XRAY_GUARD_VALUE_0x87654321); | 135 assert(capture->guard2 == XRAY_GUARD_VALUE_0x87654321); |
122 assert(capture->guard3 == XRAY_GUARD_VALUE_0x12345678); | 136 assert(capture->guard3 == XRAY_GUARD_VALUE_0x12345678); |
123 } | 137 } |
124 | 138 |
125 /* Decrements the trace index, wrapping around if needed. */ | 139 /* Decrements the trace index, wrapping around if needed. */ |
126 XRAY_FORCE_INLINE int XRayTraceDecrementIndexInline( | 140 XRAY_FORCE_INLINE int XRayTraceDecrementIndexInline( |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 } | 310 } |
297 | 311 |
298 | 312 |
299 /* Generic memory free for XRay */ | 313 /* Generic memory free for XRay */ |
300 void XRayFree(void* data) { | 314 void XRayFree(void* data) { |
301 assert(NULL != data); | 315 assert(NULL != data); |
302 free(data); | 316 free(data); |
303 } | 317 } |
304 | 318 |
305 | 319 |
306 | |
307 /* Main profile capture function that is called at the start */ | 320 /* Main profile capture function that is called at the start */ |
308 /* of every instrumented function. This function is implicitly */ | 321 /* of every instrumented function. This function is implicitly */ |
309 /* called when code is compilied with the -finstrument-functions option */ | 322 /* called when code is compilied with the -finstrument-functions option */ |
| 323 #if defined(__pnacl__) |
| 324 void __pnacl_profile_func_enter(const char* this_fn) { |
| 325 #else |
310 void __cyg_profile_func_enter(void* this_fn, void* call_site) { | 326 void __cyg_profile_func_enter(void* this_fn, void* call_site) { |
| 327 #endif |
311 struct XRayTraceCapture* capture = g_xray_capture; | 328 struct XRayTraceCapture* capture = g_xray_capture; |
312 if (capture && capture->recording) { | 329 if (capture && capture->recording) { |
313 uint32_t depth = capture->stack_depth; | 330 uint32_t depth = capture->stack_depth; |
314 if (depth < capture->max_stack_depth) { | 331 if (depth < capture->max_stack_depth) { |
315 struct XRayTraceStackEntry* se = &capture->stack[depth]; | 332 struct XRayTraceStackEntry* se = &capture->stack[depth]; |
316 uint32_t addr = (uint32_t)this_fn; | 333 uint32_t addr = (uint32_t)this_fn; |
317 se->depth_addr = XRAY_PACK_DEPTH_ADDR(depth, addr); | 334 se->depth_addr = XRAY_PACK_DEPTH_ADDR(depth, addr); |
318 se->dest = capture->buffer_index; | 335 se->dest = capture->buffer_index; |
319 se->annotation_index = 0; | 336 se->annotation_index = 0; |
320 GTSC(se->tsc); | 337 GTSC(se->tsc); |
321 capture->buffer_index = | 338 capture->buffer_index = |
322 XRayTraceIncrementIndexInline(capture, capture->buffer_index); | 339 XRayTraceIncrementIndexInline(capture, capture->buffer_index); |
323 } | 340 } |
324 ++capture->stack_depth; | 341 ++capture->stack_depth; |
325 } | 342 } |
326 } | 343 } |
327 | 344 |
328 | 345 |
329 /* Main profile capture function that is called at the exit of */ | 346 /* Main profile capture function that is called at the exit of */ |
330 /* every instrumented function. This function is implicity called */ | 347 /* every instrumented function. This function is implicity called */ |
331 /* when the code is compiled with the -finstrument-functions option */ | 348 /* when the code is compiled with the -finstrument-functions option */ |
| 349 #if defined(__pnacl__) |
| 350 void __pnacl_profile_func_exit(const char* this_fn) { |
| 351 #else |
332 void __cyg_profile_func_exit(void* this_fn, void* call_site) { | 352 void __cyg_profile_func_exit(void* this_fn, void* call_site) { |
| 353 #endif |
333 struct XRayTraceCapture* capture = g_xray_capture; | 354 struct XRayTraceCapture* capture = g_xray_capture; |
334 if (capture && capture->recording) { | 355 if (capture && capture->recording) { |
335 --capture->stack_depth; | 356 --capture->stack_depth; |
336 if (capture->stack_depth < capture->max_stack_depth) { | 357 if (capture->stack_depth < capture->max_stack_depth) { |
337 uint32_t depth = capture->stack_depth; | 358 uint32_t depth = capture->stack_depth; |
338 struct XRayTraceStackEntry* se = &capture->stack[depth]; | 359 struct XRayTraceStackEntry* se = &capture->stack[depth]; |
339 uint32_t buffer_index = se->dest; | 360 uint32_t buffer_index = se->dest; |
340 uint64_t tsc; | 361 uint64_t tsc; |
341 struct XRayTraceBufferEntry* be = &capture->buffer[buffer_index]; | 362 struct XRayTraceBufferEntry* be = &capture->buffer[buffer_index]; |
342 GTSC(tsc); | 363 GTSC(tsc); |
343 be->depth_addr = se->depth_addr; | 364 be->depth_addr = se->depth_addr; |
344 be->start_tick = se->tsc; | 365 be->start_tick = se->tsc; |
345 be->end_tick = tsc; | 366 be->end_tick = tsc; |
346 be->annotation_index = 0; | 367 be->annotation_index = 0; |
347 if (0 != se->annotation_index) | 368 if (0 != se->annotation_index) |
348 __xray_profile_append_annotation(capture, se, be); | 369 __xray_profile_append_annotation(capture, se, be); |
349 } | 370 } |
350 } | 371 } |
351 } | 372 } |
352 | 373 |
| 374 #ifndef XRAY_DISABLE_BROWSER_INTEGRATION |
| 375 void XRayGetTSC(uint64_t* tsc) { |
| 376 GTSC(*tsc); |
| 377 } |
| 378 |
| 379 int32_t XRayGetSavedThreadID(struct XRayTraceCapture* capture) { |
| 380 return capture->thread_id; |
| 381 } |
| 382 |
| 383 struct XRayTimestampPair XRayFrameGetStartTimestampPair( |
| 384 struct XRayTraceCapture* capture, int frame) { |
| 385 return capture->frame.entry[frame].start_time; |
| 386 } |
| 387 |
| 388 struct XRayTimestampPair XRayFrameGetEndTimestampPair( |
| 389 struct XRayTraceCapture* capture, int frame) { |
| 390 return capture->frame.entry[frame].end_time; |
| 391 } |
| 392 #endif |
353 | 393 |
354 /* Special case appending annotation string to trace buffer */ | 394 /* Special case appending annotation string to trace buffer */ |
355 /* this function should only ever be called from __cyg_profile_func_exit() */ | 395 /* this function should only ever be called from __cyg_profile_func_exit() */ |
356 void __xray_profile_append_annotation(struct XRayTraceCapture* capture, | 396 void __xray_profile_append_annotation(struct XRayTraceCapture* capture, |
357 struct XRayTraceStackEntry* se, | 397 struct XRayTraceStackEntry* se, |
358 struct XRayTraceBufferEntry* be) { | 398 struct XRayTraceBufferEntry* be) { |
359 struct XRayTraceStackEntry* parent = se - 1; | 399 struct XRayTraceStackEntry* parent = se - 1; |
360 int start = parent->annotation_index; | 400 int start = parent->annotation_index; |
361 be->annotation_index = capture->buffer_index; | 401 be->annotation_index = capture->buffer_index; |
362 char* str = &capture->annotation[start]; | 402 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 */ | 606 /* The trace stack[0] is reserved */ |
567 memset(&capture->stack[0], 0, sizeof(capture->stack[0])); | 607 memset(&capture->stack[0], 0, sizeof(capture->stack[0])); |
568 /* Annotation index 0 is reserved to indicate no annotation */ | 608 /* Annotation index 0 is reserved to indicate no annotation */ |
569 capture->stack[0].annotation_index = 1; | 609 capture->stack[0].annotation_index = 1; |
570 capture->annotation[0] = 0; | 610 capture->annotation[0] = 0; |
571 capture->annotation[1] = 0; | 611 capture->annotation[1] = 0; |
572 capture->annotation_count = 0; | 612 capture->annotation_count = 0; |
573 capture->recording = true; | 613 capture->recording = true; |
574 GTSC(capture->frame.entry[i].start_tsc); | 614 GTSC(capture->frame.entry[i].start_tsc); |
575 g_xray_capture = capture; | 615 g_xray_capture = capture; |
| 616 |
| 617 #ifndef XRAY_DISABLE_BROWSER_INTEGRATION |
| 618 capture->frame.entry[i].start_time = XRayGenerateTimestampsNow(); |
| 619 #endif |
| 620 |
576 } | 621 } |
577 | 622 |
578 | 623 |
579 /* Ends a frame and disables capturing. Advances to the next frame. */ | 624 /* Ends a frame and disables capturing. Advances to the next frame. */ |
580 /* Must be paired with XRayStartFrame(), and called from the same thread. */ | 625 /* Must be paired with XRayStartFrame(), and called from the same thread. */ |
581 void XRayEndFrame(struct XRayTraceCapture* capture) { | 626 void XRayEndFrame(struct XRayTraceCapture* capture) { |
582 int i; | 627 int i; |
583 assert(capture); | 628 assert(capture); |
584 assert(capture->initialized); | 629 assert(capture->initialized); |
585 assert(capture->recording); | 630 assert(capture->recording); |
(...skipping 19 matching lines...) Expand all Loading... |
605 if (be->depth_addr != XRAY_FRAME_MARKER) { | 650 if (be->depth_addr != XRAY_FRAME_MARKER) { |
606 fprintf(stderr, | 651 fprintf(stderr, |
607 "XRay: XRayStopFrame() detects insufficient trace buffer size!\n"); | 652 "XRay: XRayStopFrame() detects insufficient trace buffer size!\n"); |
608 XRayReset(capture); | 653 XRayReset(capture); |
609 } else { | 654 } else { |
610 /* Replace marker with an empty annotation string. */ | 655 /* Replace marker with an empty annotation string. */ |
611 be->depth_addr = XRAY_NULL_ANNOTATION; | 656 be->depth_addr = XRAY_NULL_ANNOTATION; |
612 XRayCheckGuards(capture); | 657 XRayCheckGuards(capture); |
613 } | 658 } |
614 g_xray_capture = NULL; | 659 g_xray_capture = NULL; |
| 660 |
| 661 #ifndef XRAY_DISABLE_BROWSER_INTEGRATION |
| 662 capture->frame.entry[i].end_time = XRayGenerateTimestampsNow(); |
| 663 #endif |
615 } | 664 } |
616 | 665 |
617 | 666 |
618 /* Get the last frame captured. Do not call while capturing. */ | 667 /* Get the last frame captured. Do not call while capturing. */ |
619 /* (ie call outside of XRayStartFrame() / XRayStopFrame() pair) */ | 668 /* (ie call outside of XRayStartFrame() / XRayStopFrame() pair) */ |
620 int XRayGetLastFrame(struct XRayTraceCapture* capture) { | 669 int XRayGetLastFrame(struct XRayTraceCapture* capture) { |
621 assert(capture); | 670 assert(capture); |
622 assert(capture->initialized); | 671 assert(capture->initialized); |
623 assert(!capture->recording); | 672 assert(!capture->recording); |
624 assert(0 == capture->disabled); | 673 assert(0 == capture->disabled); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
692 capture->recording = false; | 741 capture->recording = false; |
693 XRaySetMaxStackDepth(capture, stack_depth); | 742 XRaySetMaxStackDepth(capture, stack_depth); |
694 XRayReset(capture); | 743 XRayReset(capture); |
695 | 744 |
696 /* Mapfile is optional; we don't need it for captures, only for reports. */ | 745 /* Mapfile is optional; we don't need it for captures, only for reports. */ |
697 capture->symbols = | 746 capture->symbols = |
698 XRaySymbolTableCreate(XRAY_DEFAULT_SYMBOL_TABLE_SIZE); | 747 XRaySymbolTableCreate(XRAY_DEFAULT_SYMBOL_TABLE_SIZE); |
699 if (NULL != mapfilename) | 748 if (NULL != mapfilename) |
700 XRaySymbolTableParseMapfile(capture->symbols, mapfilename); | 749 XRaySymbolTableParseMapfile(capture->symbols, mapfilename); |
701 | 750 |
| 751 #ifndef XRAY_DISABLE_BROWSER_INTEGRATION |
| 752 /* Use the address of a thread local variable as a fake thread id. */ |
| 753 capture->thread_id = (int32_t)(&g_xray_thread_id_placeholder); |
| 754 #endif |
| 755 |
702 return capture; | 756 return capture; |
703 } | 757 } |
704 | 758 |
705 | 759 |
706 /* Shut down and free memory used by XRay. */ | 760 /* Shut down and free memory used by XRay. */ |
707 void XRayShutdown(struct XRayTraceCapture* capture) { | 761 void XRayShutdown(struct XRayTraceCapture* capture) { |
708 assert(capture); | 762 assert(capture); |
709 assert(capture->initialized); | 763 assert(capture->initialized); |
710 assert(!capture->recording); | 764 assert(!capture->recording); |
711 XRayCheckGuards(capture); | 765 XRayCheckGuards(capture); |
712 if (NULL != capture->symbols) { | 766 if (NULL != capture->symbols) { |
713 XRaySymbolTableFree(capture->symbols); | 767 XRaySymbolTableFree(capture->symbols); |
714 } | 768 } |
715 XRayFree(capture->frame.entry); | 769 XRayFree(capture->frame.entry); |
716 XRayFree(capture->buffer); | 770 XRayFree(capture->buffer); |
717 capture->initialized = false; | 771 capture->initialized = false; |
718 XRayFree(capture); | 772 XRayFree(capture); |
719 } | 773 } |
720 | 774 |
721 #endif /* XRAY */ | 775 #endif /* XRAY */ |
OLD | NEW |