mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
xray: import Xray profiler from Chromium Native Client
This commit is contained in:
parent
54931ea238
commit
4bc311cf92
12 changed files with 2124 additions and 0 deletions
28
hermit/usr/xray/LICENSE
Normal file
28
hermit/usr/xray/LICENSE
Normal file
|
@ -0,0 +1,28 @@
|
|||
Copyright 2011, The Chromium Authors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
163
hermit/usr/xray/browser.c
Normal file
163
hermit/usr/xray/browser.c
Normal file
|
@ -0,0 +1,163 @@
|
|||
/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
/* XRay -- a simple profiler for Native Client */
|
||||
|
||||
#ifndef XRAY_DISABLE_BROWSER_INTEGRATION
|
||||
|
||||
#include <alloca.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "ppapi/c/dev/ppb_trace_event_dev.h"
|
||||
#include "xray/xray_priv.h"
|
||||
|
||||
|
||||
#if defined(XRAY)
|
||||
static PPB_Trace_Event_Dev* ppb_trace_event_interface = NULL;
|
||||
|
||||
static const char* XRayGetName(struct XRaySymbolTable* symbols,
|
||||
struct XRayTraceBufferEntry* e) {
|
||||
uint32_t addr = XRAY_EXTRACT_ADDR(e->depth_addr);
|
||||
struct XRaySymbol* symbol = XRaySymbolTableLookup(symbols, addr);
|
||||
return XRaySymbolGetName(symbol);
|
||||
}
|
||||
|
||||
struct XRayTimestampPair XRayGenerateTimestampsNow(void) {
|
||||
struct XRayTimestampPair pair;
|
||||
assert(ppb_trace_event_interface);
|
||||
|
||||
XRayGetTSC(&pair.xray);
|
||||
pair.pepper = ppb_trace_event_interface->Now();
|
||||
return pair;
|
||||
}
|
||||
|
||||
/* see chromium/src/base/trace_event/trace_event.h */
|
||||
#define TRACE_VALUE_TYPE_UINT (2)
|
||||
#define TRACE_VALUE_TYPE_DOUBLE (4)
|
||||
#define TRACE_VALUE_TYPE_COPY_STRING (7)
|
||||
|
||||
union TraceValue {
|
||||
bool as_bool;
|
||||
unsigned long long as_uint;
|
||||
long long as_int;
|
||||
double as_double;
|
||||
const void* as_pointer;
|
||||
const char* as_string;
|
||||
};
|
||||
|
||||
void XRayBrowserTraceReport(struct XRayTraceCapture* capture) {
|
||||
|
||||
const void* cat_enabled = ppb_trace_event_interface->GetCategoryEnabled(
|
||||
"xray");
|
||||
struct XRaySymbolTable* symbols = XRayGetSymbolTable(capture);
|
||||
|
||||
int32_t thread_id = XRayGetSavedThreadID(capture);
|
||||
|
||||
int head = XRayFrameGetHead(capture);
|
||||
int frame = XRayFrameGetTail(capture);
|
||||
while(frame != head) {
|
||||
|
||||
struct XRayTimestampPair start_time = XRayFrameGetStartTimestampPair(
|
||||
capture, frame);
|
||||
struct XRayTimestampPair end_time = XRayFrameGetEndTimestampPair(
|
||||
capture, frame);
|
||||
|
||||
double pdiff = (end_time.pepper - start_time.pepper);
|
||||
double odiff = (end_time.xray - start_time.xray);
|
||||
double scale_a = pdiff / odiff;
|
||||
double scale_b = ((double)end_time.pepper) - (scale_a * end_time.xray);
|
||||
printf("Xray timestamp calibration frame %d: %f %f\n",
|
||||
frame, scale_a, scale_b);
|
||||
|
||||
int start = XRayFrameGetTraceStartIndex(capture, frame);
|
||||
int end = XRayFrameGetTraceEndIndex(capture, frame);
|
||||
|
||||
struct XRayTraceBufferEntry** stack_base = XRayMalloc(
|
||||
sizeof(struct XRayTraceBufferEntry*) * (XRAY_TRACE_STACK_SIZE + 1));
|
||||
struct XRayTraceBufferEntry** stack_top = stack_base;
|
||||
*stack_top = NULL;
|
||||
|
||||
uint32_t num_args = 0;
|
||||
const char* arg_names[] = {"annotation"};
|
||||
uint8_t arg_types[] = {TRACE_VALUE_TYPE_COPY_STRING};
|
||||
uint64_t arg_values[] = {0};
|
||||
char annotation[XRAY_TRACE_ANNOTATION_LENGTH];
|
||||
|
||||
int i;
|
||||
for(i = start; i != end; i = XRayTraceNextEntry(capture, i)) {
|
||||
if (XRayTraceIsAnnotation(capture, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t depth = XRAY_EXTRACT_DEPTH(
|
||||
XRayTraceGetEntry(capture, i)->depth_addr);
|
||||
|
||||
while(*stack_top &&
|
||||
XRAY_EXTRACT_DEPTH((*stack_top)->depth_addr) >= depth) {
|
||||
struct XRayTraceBufferEntry* e = *(stack_top--);
|
||||
ppb_trace_event_interface->AddTraceEventWithThreadIdAndTimestamp(
|
||||
'E', cat_enabled,
|
||||
XRayGetName(symbols, e),
|
||||
0, thread_id,
|
||||
(scale_a * e->end_tick) + scale_b,
|
||||
0, NULL, NULL, NULL, 0
|
||||
);
|
||||
}
|
||||
|
||||
num_args = 0;
|
||||
struct XRayTraceBufferEntry* e = XRayTraceGetEntry(capture, i);
|
||||
uint32_t annotation_index = e->annotation_index;
|
||||
if (annotation_index) {
|
||||
XRayTraceCopyToString(capture, annotation_index, annotation);
|
||||
|
||||
union TraceValue val;
|
||||
val.as_string = (const char*)annotation;
|
||||
|
||||
arg_values[0] = val.as_uint;
|
||||
num_args = 1;
|
||||
}
|
||||
|
||||
ppb_trace_event_interface->AddTraceEventWithThreadIdAndTimestamp(
|
||||
'B', cat_enabled,
|
||||
XRayGetName(symbols, e),
|
||||
0, thread_id,
|
||||
(scale_a * e->start_tick) + scale_b,
|
||||
num_args, arg_names, arg_types, arg_values, 0
|
||||
);
|
||||
|
||||
*(++stack_top) = e;
|
||||
}
|
||||
|
||||
while(*stack_top) {
|
||||
struct XRayTraceBufferEntry* e = *(stack_top--);
|
||||
ppb_trace_event_interface->AddTraceEventWithThreadIdAndTimestamp(
|
||||
'E', cat_enabled,
|
||||
XRayGetName(symbols, e),
|
||||
0, thread_id,
|
||||
(scale_a * e->end_tick) + scale_b,
|
||||
0, NULL, NULL, NULL, 0
|
||||
);
|
||||
}
|
||||
|
||||
frame = XRayFrameGetNext(capture, frame);
|
||||
XRayFree(stack_base);
|
||||
}
|
||||
}
|
||||
|
||||
void XRayRegisterBrowserInterface(PPB_GetInterface interface) {
|
||||
ppb_trace_event_interface = (PPB_Trace_Event_Dev*)interface(
|
||||
PPB_TRACE_EVENT_DEV_INTERFACE);
|
||||
assert(ppb_trace_event_interface);
|
||||
}
|
||||
|
||||
#endif /* XRAY */
|
||||
#endif /* XRAY_DISABLE_BROWSER_INTEGRATION */
|
25
hermit/usr/xray/demangle.c
Normal file
25
hermit/usr/xray/demangle.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file. */
|
||||
|
||||
#include "xray/xray_priv.h"
|
||||
|
||||
/* Note name demangling requires linking against libstdc++ */
|
||||
/* If your platform does not support __cxa_demangle, re-compile XRay with: */
|
||||
/* -DXRAY_NO_DEMANGLE */
|
||||
|
||||
#if !defined(XRAY_NO_DEMANGLE)
|
||||
extern
|
||||
char* __cxa_demangle(const char* __mangled_name, char* __output_buffer,
|
||||
size_t* __length, int* __status);
|
||||
#endif
|
||||
|
||||
const char* XRayDemangle(char* demangle, size_t size, const char* symbol) {
|
||||
#if !defined(XRAY_NO_DEMANGLE)
|
||||
int stat;
|
||||
__cxa_demangle(symbol, demangle, &size, &stat);
|
||||
if (stat == 0)
|
||||
return demangle;
|
||||
#endif
|
||||
return symbol;
|
||||
}
|
205
hermit/usr/xray/hashtable.c
Normal file
205
hermit/usr/xray/hashtable.c
Normal file
|
@ -0,0 +1,205 @@
|
|||
/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file. */
|
||||
|
||||
|
||||
/* Hashtable for XRay */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "xray/xray_priv.h"
|
||||
|
||||
#if defined(XRAY)
|
||||
|
||||
struct XRayHashTableEntry {
|
||||
void* data;
|
||||
uint32_t key;
|
||||
};
|
||||
|
||||
|
||||
struct XRayHashTable {
|
||||
int capacity;
|
||||
int count;
|
||||
struct XRayHashTableEntry* array;
|
||||
};
|
||||
|
||||
|
||||
XRAY_NO_INSTRUMENT void XRayHashTableGrow(struct XRayHashTable* table);
|
||||
XRAY_NO_INSTRUMENT uint32_t XRayHashTableHashKey(uint32_t key);
|
||||
XRAY_NO_INSTRUMENT void XRayHashTableInit(struct XRayHashTable* table,
|
||||
int32_t capacity);
|
||||
|
||||
#define HASH_HISTO 1024
|
||||
int g_hash_histo[HASH_HISTO];
|
||||
|
||||
|
||||
/* Hashes a 32bit key into a 32bit value. */
|
||||
uint32_t XRayHashTableHashKey(uint32_t x) {
|
||||
uint32_t y = x * 7919;
|
||||
uint32_t z;
|
||||
size_t c;
|
||||
uint8_t* s = (uint8_t*)&y;
|
||||
/* based on djb2 hash function */
|
||||
uint32_t h = 5381;
|
||||
for (c = 0; c < sizeof(y); ++c) {
|
||||
z = s[c];
|
||||
h = ((h << 5) + h) + z;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
|
||||
int XRayHashTableGetCapacity(struct XRayHashTable* table) {
|
||||
return table->capacity;
|
||||
}
|
||||
|
||||
|
||||
int XRayHashTableGetCount(struct XRayHashTable* table) {
|
||||
return table->count;
|
||||
}
|
||||
|
||||
|
||||
/* Looks up key in hashtable and returns blind data. */
|
||||
void* XRayHashTableLookup(struct XRayHashTable* table, uint32_t key) {
|
||||
uint32_t h = XRayHashTableHashKey(key);
|
||||
uint32_t m = table->capacity - 1;
|
||||
uint32_t j = h & m;
|
||||
uint32_t i;
|
||||
int z = 1;
|
||||
for (i = 0; i < m; ++i) {
|
||||
/* An empty entry means the {key, data} isn't in the table. */
|
||||
if (NULL == table->array[j].data) {
|
||||
++g_hash_histo[0];
|
||||
return NULL;
|
||||
}
|
||||
/* Search for address */
|
||||
if (table->array[j].key == key) {
|
||||
if (z >= HASH_HISTO)
|
||||
z = HASH_HISTO - 1;
|
||||
++g_hash_histo[z];
|
||||
return table->array[j].data;
|
||||
}
|
||||
j = (j + 1) & m;
|
||||
++z;
|
||||
}
|
||||
/* Table was full, and there wasn't a match. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Inserts key & data into hash table. No duplicates. */
|
||||
void* XRayHashTableInsert(struct XRayHashTable* table,
|
||||
void* data, uint32_t key) {
|
||||
uint32_t h = XRayHashTableHashKey(key);
|
||||
uint32_t m = table->capacity - 1;
|
||||
uint32_t j = h & m;
|
||||
uint32_t i;
|
||||
for (i = 0; i < m; ++i) {
|
||||
/* Take the first empty entry. */
|
||||
/* (the key,data isn't already in the table) */
|
||||
if (NULL == table->array[j].data) {
|
||||
void* ret;
|
||||
float ratio;
|
||||
table->array[j].data = data;
|
||||
table->array[j].key = key;
|
||||
++table->count;
|
||||
ret = data;
|
||||
ratio = (float)table->count / (float)table->capacity;
|
||||
/* Double the capacity of the symtable if we've hit the ratio. */
|
||||
if (ratio > XRAY_SYMBOL_TABLE_MAX_RATIO)
|
||||
XRayHashTableGrow(table);
|
||||
return ret;
|
||||
}
|
||||
/* If the key is already present, return the data in the table. */
|
||||
if (table->array[j].key == key) {
|
||||
return table->array[j].data;
|
||||
}
|
||||
j = (j + 1) & m;
|
||||
}
|
||||
/* Table was full */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void* XRayHashTableAtIndex(struct XRayHashTable* table, int i) {
|
||||
if ((i < 0) || (i >= table->capacity))
|
||||
return NULL;
|
||||
return table->array[i].data;
|
||||
}
|
||||
|
||||
|
||||
/* Grows the hash table by doubling its capacity, */
|
||||
/* then re-inserts all the elements into the new table. */
|
||||
void XRayHashTableGrow(struct XRayHashTable* table) {
|
||||
struct XRayHashTableEntry* old_array = table->array;
|
||||
int old_capacity = table->capacity;
|
||||
int new_capacity = old_capacity * 2;
|
||||
int i;
|
||||
printf("XRay: Growing a hash table...\n");
|
||||
XRayHashTableInit(table, new_capacity);
|
||||
for (i = 0; i < old_capacity; ++i) {
|
||||
void* data = old_array[i].data;
|
||||
if (NULL != data) {
|
||||
uint32_t key = old_array[i].key;
|
||||
XRayHashTableInsert(table, data, key);
|
||||
}
|
||||
}
|
||||
XRayFree(old_array);
|
||||
}
|
||||
|
||||
|
||||
void XRayHashTableInit(struct XRayHashTable* table, int32_t capacity) {
|
||||
size_t bytes;
|
||||
if (0 != (capacity & (capacity - 1))) {
|
||||
printf("Xray: Hash table capacity should be a power of 2!\n");
|
||||
/* Round capacity up to next power of 2 */
|
||||
/* see http://aggregate.org/MAGIC/ */
|
||||
capacity--;
|
||||
capacity |= capacity >> 1;
|
||||
capacity |= capacity >> 2;
|
||||
capacity |= capacity >> 4;
|
||||
capacity |= capacity >> 8;
|
||||
capacity |= capacity >> 16;
|
||||
capacity++;
|
||||
}
|
||||
bytes = sizeof(table->array[0]) * capacity;
|
||||
table->capacity = capacity;
|
||||
table->count = 0;
|
||||
table->array = (struct XRayHashTableEntry*)XRayMalloc(bytes);
|
||||
}
|
||||
|
||||
|
||||
/* Creates & inializes hash table. */
|
||||
struct XRayHashTable* XRayHashTableCreate(int capacity) {
|
||||
struct XRayHashTable* table;
|
||||
table = (struct XRayHashTable*)XRayMalloc(sizeof(*table));
|
||||
XRayHashTableInit(table, capacity);
|
||||
memset(&g_hash_histo[0], 0, sizeof(g_hash_histo[0]) * HASH_HISTO);
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
/* Prints hash table performance to file; for debugging. */
|
||||
void XRayHashTableHisto(FILE* f) {
|
||||
int i;
|
||||
for (i = 0; i < HASH_HISTO; ++i) {
|
||||
if (0 != g_hash_histo[i])
|
||||
fprintf(f, "hash_iterations[%d] = %d\n", i, g_hash_histo[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Frees hash table. */
|
||||
/* Note: Does not free what the hash table entries point to. */
|
||||
void XRayHashTableFree(struct XRayHashTable* table) {
|
||||
XRayFree(table->array);
|
||||
table->capacity = 0;
|
||||
table->count = 0;
|
||||
table->array = NULL;
|
||||
XRayFree(table);
|
||||
}
|
||||
|
||||
#endif /* XRAY */
|
||||
|
96
hermit/usr/xray/parsesymbols.c
Normal file
96
hermit/usr/xray/parsesymbols.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file. */
|
||||
|
||||
|
||||
/* XRay -- a simple profiler for Native Client */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "xray/xray_priv.h"
|
||||
|
||||
#if defined(XRAY)
|
||||
|
||||
struct XRaySymbol* XRaySymbolTableCreateEntry(struct XRaySymbolTable* symtab,
|
||||
char* line) {
|
||||
uint32_t addr;
|
||||
unsigned int uiaddr;
|
||||
char symbol_text[XRAY_LINE_SIZE];
|
||||
char* parsed_symbol;
|
||||
char* newln;
|
||||
if (2 != sscanf(line, "%x %1023s", &uiaddr, symbol_text))
|
||||
return NULL;
|
||||
if (uiaddr > 0x07FFFFFF) {
|
||||
fprintf(stderr, "While parsing the mapfile, XRay encountered:\n");
|
||||
fprintf(stderr, "%s\n", line);
|
||||
fprintf(stderr,
|
||||
"XRay only works with code addresses 0x00000000 - 0x07FFFFFF\n");
|
||||
fprintf(stderr, "All functions must reside in this address space.\n");
|
||||
exit(-1);
|
||||
}
|
||||
addr = (uint32_t)uiaddr;
|
||||
parsed_symbol = strstr(line, symbol_text);
|
||||
newln = strstr(parsed_symbol, "\n");
|
||||
if (NULL != newln) {
|
||||
*newln = 0;
|
||||
}
|
||||
return XRaySymbolTableAddByName(symtab, parsed_symbol, addr);
|
||||
}
|
||||
|
||||
|
||||
void XRaySymbolTableParseMapfile(struct XRaySymbolTable* symtab,
|
||||
const char* mapfile) {
|
||||
FILE* f;
|
||||
char line[XRAY_LINE_SIZE];
|
||||
bool in_text = false;
|
||||
bool in_link_once = false;
|
||||
int in_link_once_counter = 0;
|
||||
int num_symbols = 0;
|
||||
|
||||
printf("XRay: opening mapfile %s\n", mapfile);
|
||||
f = fopen(mapfile, "rt");
|
||||
if (0 == f) {
|
||||
fprintf(stderr, "XRay: failed to open %s\n", mapfile);
|
||||
return;
|
||||
}
|
||||
printf("XRay: parsing...\n");
|
||||
while (NULL != fgets(line, XRAY_LINE_SIZE, f)) {
|
||||
if (line == strstr(line, " .text ")) {
|
||||
in_text = true;
|
||||
continue;
|
||||
}
|
||||
if (line == strstr(line, " .gnu.linkonce.t.")) {
|
||||
in_link_once = true;
|
||||
in_link_once_counter = 0;
|
||||
continue;
|
||||
}
|
||||
if (line == strstr(line, " .text.")) {
|
||||
in_link_once = true;
|
||||
in_link_once_counter = 0;
|
||||
continue;
|
||||
}
|
||||
if (line == strstr(line, " 0x")) {
|
||||
if (in_text) {
|
||||
XRaySymbolTableCreateEntry(symtab, line);
|
||||
++num_symbols;
|
||||
} else if (in_link_once) {
|
||||
if (in_link_once_counter != 0) {
|
||||
if (NULL != XRaySymbolTableCreateEntry(symtab, line))
|
||||
++num_symbols;
|
||||
} else {
|
||||
++in_link_once_counter;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
in_text = false;
|
||||
in_link_once = false;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
printf("XRay: parsed %d symbols into symbol table\n", num_symbols);
|
||||
}
|
||||
|
||||
#endif // XRAY
|
209
hermit/usr/xray/report.c
Normal file
209
hermit/usr/xray/report.c
Normal file
|
@ -0,0 +1,209 @@
|
|||
/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file. */
|
||||
|
||||
|
||||
/* XRay -- a simple profiler for Native Client */
|
||||
|
||||
#include <alloca.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "xray/xray_priv.h"
|
||||
|
||||
#if defined(XRAY)
|
||||
|
||||
struct XRayTotal {
|
||||
int index;
|
||||
int frame;
|
||||
uint64_t ticks;
|
||||
};
|
||||
|
||||
|
||||
/* Dumps the trace report for a given frame. */
|
||||
void XRayTraceReport(struct XRayTraceCapture* capture,
|
||||
FILE* f,
|
||||
int frame,
|
||||
char* label,
|
||||
float percent_cutoff,
|
||||
int ticks_cutoff) {
|
||||
int index;
|
||||
int start;
|
||||
int end;
|
||||
float total;
|
||||
char space[257];
|
||||
struct XRaySymbolTable* symbols = XRayGetSymbolTable(capture);
|
||||
memset(space, ' ', 256);
|
||||
space[256] = 0;
|
||||
if (NULL == f) {
|
||||
f = stdout;
|
||||
}
|
||||
fprintf(f,
|
||||
"====================================================================\n");
|
||||
if (NULL != label)
|
||||
fprintf(f, "label %s\n", label);
|
||||
fprintf(f, "\n");
|
||||
fprintf(f,
|
||||
" Address Ticks Percent Function [annotation...]\n");
|
||||
fprintf(f,
|
||||
"--------------------------------------------------------------------\n");
|
||||
total = XRayFrameGetTotalTicks(capture, frame);
|
||||
start = XRayFrameGetTraceStartIndex(capture, frame);
|
||||
end = XRayFrameGetTraceEndIndex(capture, frame);
|
||||
index = start;
|
||||
while (index != end) {
|
||||
if (!XRayTraceIsAnnotation(capture, index)) {
|
||||
const char* symbol_name;
|
||||
char annotation[XRAY_TRACE_ANNOTATION_LENGTH];
|
||||
struct XRayTraceBufferEntry* e = XRayTraceGetEntry(capture, index);
|
||||
uint32_t depth = XRAY_EXTRACT_DEPTH(e->depth_addr);
|
||||
uint32_t addr = XRAY_EXTRACT_ADDR(e->depth_addr);
|
||||
uint32_t annotation_index = e->annotation_index;
|
||||
uint64_t ticks =
|
||||
e->end_tick > e->start_tick ? e->end_tick - e->start_tick : 0;
|
||||
float percent = 100.0f * (float)ticks / total;
|
||||
if (percent >= percent_cutoff && ticks >= ticks_cutoff) {
|
||||
struct XRaySymbol* symbol;
|
||||
symbol = XRaySymbolTableLookup(symbols, addr);
|
||||
symbol_name = XRaySymbolGetName(symbol);
|
||||
if (0 != annotation_index) {
|
||||
XRayTraceCopyToString(capture, annotation_index, annotation);
|
||||
} else {
|
||||
strcpy(annotation, "");
|
||||
}
|
||||
fprintf(f, "0x%08X %12" PRIu64 " %5.1f %s%s %s\n",
|
||||
(unsigned int)addr, ticks, percent,
|
||||
&space[256 - depth], symbol_name, annotation);
|
||||
}
|
||||
}
|
||||
index = XRayTraceNextEntry(capture, index);
|
||||
}
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
|
||||
int qcompare(const void* a, const void* b) {
|
||||
struct XRayTotal* ia = (struct XRayTotal*)a;
|
||||
struct XRayTotal* ib = (struct XRayTotal*)b;
|
||||
if (ib->ticks > ia->ticks)
|
||||
return 1;
|
||||
else if (ib->ticks < ia->ticks)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Dumps a frame report */
|
||||
void XRayFrameReport(struct XRayTraceCapture* capture, FILE* f) {
|
||||
int i;
|
||||
int head = XRayFrameGetHead(capture);
|
||||
int frame = XRayFrameGetTail(capture);
|
||||
int counter = 0;
|
||||
int total_capture = 0;
|
||||
struct XRayTotal* totals;
|
||||
totals = (struct XRayTotal*)
|
||||
alloca(XRayFrameGetCount(capture) * sizeof(struct XRayTotal));
|
||||
fprintf(f, "\n");
|
||||
fprintf(f,
|
||||
"Frame# Total Ticks Capture size Annotations Label\n");
|
||||
fprintf(f,
|
||||
"--------------------------------------------------------------------\n");
|
||||
while (frame != head) {
|
||||
uint64_t total_ticks = XRayFrameGetTotalTicks(capture, frame);
|
||||
int capture_size = XRayFrameGetTraceCount(capture, frame);
|
||||
int annotation_count = XRayFrameGetAnnotationCount(capture, frame);
|
||||
bool valid = XRayFrameIsValid(capture, frame);
|
||||
char label[XRAY_MAX_LABEL];
|
||||
XRayFrameMakeLabel(capture, counter, label);
|
||||
fprintf(f, " %3d %s %12" PRIu64 " %10d %10d %s\n",
|
||||
counter,
|
||||
valid ? " " : "*",
|
||||
total_ticks,
|
||||
capture_size,
|
||||
annotation_count,
|
||||
label);
|
||||
totals[counter].index = counter;
|
||||
totals[counter].frame = frame;
|
||||
totals[counter].ticks = total_ticks;
|
||||
total_capture += capture_size;
|
||||
++counter;
|
||||
frame = XRayFrameGetNext(capture, frame);
|
||||
}
|
||||
fprintf(f,
|
||||
"--------------------------------------------------------------------\n");
|
||||
fprintf(f,
|
||||
"XRay: %d frame(s) %d total capture(s)\n", counter, total_capture);
|
||||
fprintf(f, "\n");
|
||||
/* Sort and take average of the median cut */
|
||||
qsort(totals, counter, sizeof(struct XRayTotal), qcompare);
|
||||
fprintf(f, "\n");
|
||||
fprintf(f, "Sorted by total ticks (most expensive first):\n");
|
||||
fprintf(f, "\n");
|
||||
fprintf(f,
|
||||
"Frame# Total Ticks Capture size Annotations Label\n");
|
||||
fprintf(f,
|
||||
"--------------------------------------------------------------------\n");
|
||||
for (i = 0; i < counter; ++i) {
|
||||
int index = totals[i].index;
|
||||
int frame = totals[i].frame;
|
||||
uint64_t total_ticks = XRayFrameGetTotalTicks(capture, frame);
|
||||
int capture_size = XRayFrameGetTraceCount(capture, frame);
|
||||
int annotation_count = XRayFrameGetAnnotationCount(capture, frame);
|
||||
char label[XRAY_MAX_LABEL];
|
||||
XRayFrameMakeLabel(capture, index, label);
|
||||
fprintf(f, " %3d %12" PRIu64 " %10d %10d %s\n",
|
||||
index,
|
||||
total_ticks,
|
||||
capture_size,
|
||||
annotation_count,
|
||||
label);
|
||||
}
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
|
||||
/* Dump a frame report followed by trace report(s) for each frame. */
|
||||
void XRayReport(struct XRayTraceCapture* capture,
|
||||
FILE* f,
|
||||
float percent_cutoff,
|
||||
int ticks_cutoff) {
|
||||
int head = XRayFrameGetHead(capture);
|
||||
int frame = XRayFrameGetTail(capture);
|
||||
int counter = 0;
|
||||
XRayFrameReport(capture, f);
|
||||
fprintf(f, "\n");
|
||||
while (frame != head) {
|
||||
char label[XRAY_MAX_LABEL];
|
||||
fprintf(f, "\n");
|
||||
XRayFrameMakeLabel(capture, counter, label);
|
||||
XRayTraceReport(capture, f, frame, label, percent_cutoff, ticks_cutoff);
|
||||
++counter;
|
||||
frame = XRayFrameGetNext(capture, frame);
|
||||
}
|
||||
fprintf(f,
|
||||
"====================================================================\n");
|
||||
#if defined(XRAY_OUTPUT_HASH_COLLISIONS)
|
||||
XRayHashTableHisto(capture, f);
|
||||
#endif
|
||||
fflush(f);
|
||||
}
|
||||
|
||||
/* Write a profile report to text file. */
|
||||
void XRaySaveReport(struct XRayTraceCapture* capture,
|
||||
const char* filename,
|
||||
float percent_cutoff,
|
||||
int ticks_cutoff) {
|
||||
FILE* f;
|
||||
f = fopen(filename, "wt");
|
||||
if (NULL != f) {
|
||||
XRayReport(capture, f, percent_cutoff, ticks_cutoff);
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* XRAY */
|
94
hermit/usr/xray/stringpool.c
Normal file
94
hermit/usr/xray/stringpool.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file. */
|
||||
|
||||
|
||||
/* XRay string pool */
|
||||
|
||||
/* String pool holds a large pile of strings. */
|
||||
/* It is up to higher level data structures to avoid duplicates. */
|
||||
/* It is up to higher level data structures to provide fast lookups. */
|
||||
|
||||
/* _GNU_SOURCE must be defined prior to the inclusion of string.h
|
||||
* so that strnlen is available with glibc */
|
||||
#define _GNU_SOURCE
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "xray/xray_priv.h"
|
||||
|
||||
#if defined(XRAY)
|
||||
|
||||
struct XRayStringPoolNode {
|
||||
struct XRayStringPoolNode* next;
|
||||
char strings[XRAY_STRING_POOL_NODE_SIZE];
|
||||
};
|
||||
|
||||
|
||||
struct XRayStringPool {
|
||||
struct XRayStringPoolNode* head;
|
||||
struct XRayStringPoolNode* current;
|
||||
int index;
|
||||
};
|
||||
|
||||
|
||||
static struct XRayStringPoolNode* XRayStringPoolAllocNode() {
|
||||
struct XRayStringPoolNode* s;
|
||||
s = (struct XRayStringPoolNode *)XRayMalloc(sizeof(*s));
|
||||
s->next = NULL;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
static int XRayStringPoolCurrentNodeSpaceAvail(struct XRayStringPool* pool) {
|
||||
int i = pool->index;
|
||||
return (XRAY_STRING_POOL_NODE_SIZE - i) - 1;
|
||||
}
|
||||
|
||||
|
||||
/* Append a string to the string pool. */
|
||||
char* XRayStringPoolAppend(struct XRayStringPool* pool, const char* src) {
|
||||
/* Add +1 to STRING_POOL_NODE_SIZE to detect large strings */
|
||||
/* Add +1 to strnlen result to account for string termination */
|
||||
int n = strnlen(src, XRAY_STRING_POOL_NODE_SIZE + 1) + 1;
|
||||
int a = XRayStringPoolCurrentNodeSpaceAvail(pool);
|
||||
char* dst;
|
||||
/* Don't accept strings larger than the pool node. */
|
||||
if (n >= (XRAY_STRING_POOL_NODE_SIZE - 1))
|
||||
return NULL;
|
||||
/* If string doesn't fit, alloc a new node. */
|
||||
if (n > a) {
|
||||
pool->current->next = XRayStringPoolAllocNode();
|
||||
pool->current = pool->current->next;
|
||||
pool->index = 0;
|
||||
}
|
||||
/* Copy string and return a pointer to copy. */
|
||||
dst = &pool->current->strings[pool->index];
|
||||
strcpy(dst, src);
|
||||
pool->index += n;
|
||||
return dst;
|
||||
}
|
||||
|
||||
|
||||
/* Create & initialize a string pool instance. */
|
||||
struct XRayStringPool* XRayStringPoolCreate() {
|
||||
struct XRayStringPool* pool;
|
||||
pool = (struct XRayStringPool*)XRayMalloc(sizeof(*pool));
|
||||
pool->head = XRayStringPoolAllocNode();
|
||||
pool->current = pool->head;
|
||||
return pool;
|
||||
}
|
||||
|
||||
|
||||
/* Free a string pool. */
|
||||
void XRayStringPoolFree(struct XRayStringPool* pool) {
|
||||
struct XRayStringPoolNode* n = pool->head;
|
||||
while (NULL != n) {
|
||||
struct XRayStringPoolNode* c = n;
|
||||
n = n->next;
|
||||
XRayFree(c);
|
||||
}
|
||||
XRayFree(pool);
|
||||
}
|
||||
|
||||
#endif /* XRAY */
|
||||
|
200
hermit/usr/xray/symtable.c
Normal file
200
hermit/usr/xray/symtable.c
Normal file
|
@ -0,0 +1,200 @@
|
|||
/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file. */
|
||||
|
||||
/* XRay symbol table */
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined(__GLIBC__)
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include "xray/xray_priv.h"
|
||||
#define PNACL_STRING_OFFSET (0x10000000)
|
||||
|
||||
#if defined(XRAY)
|
||||
|
||||
bool g_symtable_debug = false;
|
||||
|
||||
struct XRayFrameInfo {
|
||||
int times_called;
|
||||
int total_ticks;
|
||||
};
|
||||
|
||||
|
||||
struct XRaySymbol {
|
||||
const char* name;
|
||||
struct XRayFrameInfo frames[XRAY_MAX_FRAMES];
|
||||
};
|
||||
|
||||
|
||||
struct XRaySymbolPoolNode {
|
||||
struct XRaySymbolPoolNode* next;
|
||||
struct XRaySymbol symbols[XRAY_SYMBOL_POOL_NODE_SIZE];
|
||||
};
|
||||
|
||||
|
||||
struct XRaySymbolPool {
|
||||
struct XRaySymbolPoolNode* head;
|
||||
struct XRaySymbolPoolNode* current;
|
||||
int index;
|
||||
};
|
||||
|
||||
|
||||
struct XRaySymbolTable {
|
||||
int num_symbols;
|
||||
struct XRayHashTable* hash_table;
|
||||
struct XRayStringPool* string_pool;
|
||||
struct XRaySymbolPool* symbol_pool;
|
||||
};
|
||||
|
||||
|
||||
const char* XRaySymbolGetName(struct XRaySymbol* symbol) {
|
||||
return (NULL == symbol) ? "(null)" : symbol->name;
|
||||
}
|
||||
|
||||
|
||||
struct XRaySymbol* XRaySymbolCreate(struct XRaySymbolPool* sympool,
|
||||
const char* name)
|
||||
{
|
||||
struct XRaySymbol* symbol;
|
||||
symbol = XRaySymbolPoolAlloc(sympool);
|
||||
symbol->name = name;
|
||||
return symbol;
|
||||
}
|
||||
|
||||
|
||||
struct XRaySymbol* XRaySymbolPoolAlloc(struct XRaySymbolPool* sympool) {
|
||||
struct XRaySymbol* symbol;
|
||||
if (sympool->index >= XRAY_SYMBOL_POOL_NODE_SIZE) {
|
||||
struct XRaySymbolPoolNode* new_pool;
|
||||
new_pool = (struct XRaySymbolPoolNode*)XRayMalloc(sizeof(*new_pool));
|
||||
sympool->current->next = new_pool;
|
||||
sympool->current = new_pool;
|
||||
sympool->index = 0;
|
||||
}
|
||||
symbol = &sympool->current->symbols[sympool->index];
|
||||
++sympool->index;
|
||||
return symbol;
|
||||
}
|
||||
|
||||
|
||||
struct XRaySymbolPool* XRaySymbolPoolCreate() {
|
||||
struct XRaySymbolPool* sympool;
|
||||
struct XRaySymbolPoolNode* node;
|
||||
sympool = (struct XRaySymbolPool*)XRayMalloc(sizeof(*sympool));
|
||||
node = (struct XRaySymbolPoolNode*)XRayMalloc(sizeof(*node));
|
||||
sympool->head = node;
|
||||
sympool->current = node;
|
||||
sympool->index = 0;
|
||||
return sympool;
|
||||
}
|
||||
|
||||
|
||||
void XRaySymbolPoolFree(struct XRaySymbolPool* pool) {
|
||||
struct XRaySymbolPoolNode* n = pool->head;
|
||||
while (NULL != n) {
|
||||
struct XRaySymbolPoolNode* c = n;
|
||||
n = n->next;
|
||||
XRayFree(c);
|
||||
}
|
||||
XRayFree(pool);
|
||||
}
|
||||
|
||||
|
||||
int XRaySymbolTableGetCount(struct XRaySymbolTable* symtab) {
|
||||
return XRayHashTableGetCount(symtab->hash_table);
|
||||
}
|
||||
|
||||
|
||||
struct XRaySymbol* XRaySymbolTableAtIndex(struct XRaySymbolTable* symtab,
|
||||
int i) {
|
||||
return (struct XRaySymbol*)XRayHashTableAtIndex(symtab->hash_table, i);
|
||||
}
|
||||
|
||||
struct XRaySymbol* XRaySymbolTableAdd(struct XRaySymbolTable* symtab,
|
||||
struct XRaySymbol* symbol,
|
||||
uint32_t addr) {
|
||||
struct XRaySymbol* sym = (struct XRaySymbol*)
|
||||
XRayHashTableInsert(symtab->hash_table, symbol, addr);
|
||||
symtab->num_symbols = XRayHashTableGetCount(symtab->hash_table);
|
||||
return sym;
|
||||
}
|
||||
|
||||
struct XRaySymbol* XRaySymbolTableAddByName(struct XRaySymbolTable* symtab,
|
||||
const char* name, uint32_t addr) {
|
||||
char* recorded_name;
|
||||
struct XRaySymbol* symbol;
|
||||
char buffer[XRAY_LINE_SIZE];
|
||||
const char* demangled_name = XRayDemangle(buffer, XRAY_LINE_SIZE, name);
|
||||
/* record the demangled symbol name into the string pool */
|
||||
recorded_name = XRayStringPoolAppend(symtab->string_pool, demangled_name);
|
||||
if (g_symtable_debug)
|
||||
printf("adding symbol %s\n", recorded_name);
|
||||
/* construct a symbol and put it in the symbol table */
|
||||
symbol = XRaySymbolCreate(symtab->symbol_pool, recorded_name);
|
||||
return XRaySymbolTableAdd(symtab, symbol, addr);
|
||||
}
|
||||
|
||||
struct XRaySymbol* XRaySymbolTableLookup(struct XRaySymbolTable* symtab,
|
||||
uint32_t addr) {
|
||||
void *x = XRayHashTableLookup(symtab->hash_table, addr);
|
||||
struct XRaySymbol* r = (struct XRaySymbol*)x;
|
||||
|
||||
#if defined(__pnacl__)
|
||||
if (r == NULL) {
|
||||
/* Addresses are trimed to 24 bits for internal storage, so we need to
|
||||
* add this offset back in order to get the real address.
|
||||
*/
|
||||
addr |= PNACL_STRING_OFFSET;
|
||||
const char* name = (const char*)addr;
|
||||
struct XRaySymbol* symbol = XRaySymbolCreate(symtab->symbol_pool, name);
|
||||
r = XRaySymbolTableAdd(symtab, symbol, addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__GLIBC__)
|
||||
if (r == NULL) {
|
||||
Dl_info info;
|
||||
if (dladdr((const void*)addr, &info) != 0)
|
||||
if (info.dli_sname)
|
||||
r = XRaySymbolTableAddByName(symtab, info.dli_sname, addr);
|
||||
}
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
/* Returns total number of symbols in the table. */
|
||||
int XRaySymbolCount(struct XRaySymbolTable* symtab) {
|
||||
return symtab->num_symbols;
|
||||
}
|
||||
|
||||
|
||||
/* Creates and inializes a symbol table. */
|
||||
struct XRaySymbolTable* XRaySymbolTableCreate(int size) {
|
||||
struct XRaySymbolTable* symtab;
|
||||
symtab = (struct XRaySymbolTable*)XRayMalloc(sizeof(*symtab));
|
||||
symtab->num_symbols = 0;
|
||||
symtab->string_pool = XRayStringPoolCreate();
|
||||
symtab->hash_table = XRayHashTableCreate(size);
|
||||
symtab->symbol_pool = XRaySymbolPoolCreate();
|
||||
return symtab;
|
||||
}
|
||||
|
||||
|
||||
/* Frees a symbol table. */
|
||||
void XRaySymbolTableFree(struct XRaySymbolTable* symtab) {
|
||||
XRayStringPoolFree(symtab->string_pool);
|
||||
XRaySymbolPoolFree(symtab->symbol_pool);
|
||||
XRayHashTableFree(symtab->hash_table);
|
||||
symtab->num_symbols = 0;
|
||||
XRayFree(symtab);
|
||||
}
|
||||
|
||||
#endif /* XRAY */
|
780
hermit/usr/xray/xray.c
Normal file
780
hermit/usr/xray/xray.c
Normal file
|
@ -0,0 +1,780 @@
|
|||
/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file. */
|
||||
|
||||
|
||||
/* XRay -- a simple profiler for Native Client */
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#include "xray/xray_priv.h"
|
||||
|
||||
#if defined(XRAY)
|
||||
|
||||
/* GTSC - Get Time Stamp Counter */
|
||||
#if defined(__amd64__) && !defined(XRAY_NO_RDTSC)
|
||||
XRAY_INLINE uint64_t RDTSC64();
|
||||
uint64_t RDTSC64() {
|
||||
uint64_t a, d;
|
||||
__asm__ __volatile__("rdtsc" : "=a" (a), "=d" (d));
|
||||
return ((uint64_t)a) | (((uint64_t)d) << 32);
|
||||
}
|
||||
#define GTSC(_x) _x = RDTSC64()
|
||||
#elif defined(__i386__) && !defined(XRAY_NO_RDTSC)
|
||||
#define GTSC(_x) __asm__ __volatile__ ("rdtsc" : "=A" (_x));
|
||||
#else
|
||||
XRAY_INLINE uint64_t GTOD();
|
||||
uint64_t GTOD() {
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec;
|
||||
}
|
||||
#define GTSC(_x) _x = GTOD();
|
||||
#endif
|
||||
|
||||
/* Use a TLS variable for cheap thread uid. */
|
||||
__thread struct XRayTraceCapture* g_xray_capture = NULL;
|
||||
__thread int g_xray_thread_id_placeholder = 0;
|
||||
|
||||
|
||||
struct XRayTraceStackEntry {
|
||||
uint32_t depth_addr;
|
||||
uint64_t tsc;
|
||||
uint32_t dest;
|
||||
uint32_t annotation_index;
|
||||
};
|
||||
|
||||
|
||||
struct XRayTraceFrameEntry {
|
||||
/* Indices into global tracebuffer */
|
||||
int start;
|
||||
int end;
|
||||
uint64_t start_tsc;
|
||||
uint64_t end_tsc;
|
||||
uint64_t total_ticks;
|
||||
int annotation_count;
|
||||
bool valid;
|
||||
|
||||
#ifndef XRAY_DISABLE_BROWSER_INTEGRATION
|
||||
struct XRayTimestampPair start_time;
|
||||
struct XRayTimestampPair end_time;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
struct XRayTraceFrame {
|
||||
struct XRayTraceFrameEntry* entry;
|
||||
int head;
|
||||
int tail;
|
||||
int count;
|
||||
};
|
||||
|
||||
|
||||
struct XRayTraceCapture {
|
||||
/* Common variables share cache line */
|
||||
bool recording;
|
||||
uint32_t stack_depth;
|
||||
uint32_t max_stack_depth;
|
||||
int buffer_index;
|
||||
int buffer_size;
|
||||
int disabled;
|
||||
int annotation_count;
|
||||
struct XRaySymbolTable* symbols;
|
||||
bool initialized;
|
||||
uint32_t annotation_filter;
|
||||
uint32_t guard0;
|
||||
struct XRayTraceStackEntry stack[XRAY_TRACE_STACK_SIZE] XRAY_ALIGN64;
|
||||
uint32_t guard1;
|
||||
uint32_t guard2;
|
||||
char annotation[XRAY_ANNOTATION_STACK_SIZE] XRAY_ALIGN64;
|
||||
uint32_t guard3;
|
||||
struct XRayTraceBufferEntry* buffer;
|
||||
struct XRayTraceFrame frame;
|
||||
|
||||
#ifndef XRAY_DISABLE_BROWSER_INTEGRATION
|
||||
int32_t thread_id;
|
||||
#endif
|
||||
} XRAY_ALIGN64;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__pnacl__)
|
||||
XRAY_NO_INSTRUMENT void __pnacl_profile_func_enter(const char* fname);
|
||||
XRAY_NO_INSTRUMENT void __pnacl_profile_func_exit(const char* fname);
|
||||
#else
|
||||
XRAY_NO_INSTRUMENT void __cyg_profile_func_enter(void* this_fn,
|
||||
void* call_site);
|
||||
XRAY_NO_INSTRUMENT void __cyg_profile_func_exit(void* this_fn,
|
||||
void* call_site);
|
||||
#endif
|
||||
|
||||
XRAY_INLINE int XRayTraceDecrementIndexInline(
|
||||
struct XRayTraceCapture* capture, int index);
|
||||
XRAY_INLINE int XRayTraceIncrementIndexInline(
|
||||
struct XRayTraceCapture* capture, int index);
|
||||
|
||||
|
||||
XRAY_NO_INSTRUMENT void __xray_profile_append_annotation(
|
||||
struct XRayTraceCapture* capture,
|
||||
struct XRayTraceStackEntry* se,
|
||||
struct XRayTraceBufferEntry* be);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Asserts that the guard values haven't changed. */
|
||||
void XRayCheckGuards(struct XRayTraceCapture* capture) {
|
||||
assert(capture->guard0 == XRAY_GUARD_VALUE_0x12345678);
|
||||
assert(capture->guard1 == XRAY_GUARD_VALUE_0x12345678);
|
||||
assert(capture->guard2 == XRAY_GUARD_VALUE_0x87654321);
|
||||
assert(capture->guard3 == XRAY_GUARD_VALUE_0x12345678);
|
||||
}
|
||||
|
||||
/* Decrements the trace index, wrapping around if needed. */
|
||||
int XRayTraceDecrementIndexInline(
|
||||
struct XRayTraceCapture* capture, int index) {
|
||||
--index;
|
||||
if (index < 0)
|
||||
index = capture->buffer_size - 1;
|
||||
return index;
|
||||
}
|
||||
|
||||
/* Increments the trace index, wrapping around if needed. */
|
||||
int XRayTraceIncrementIndexInline(
|
||||
struct XRayTraceCapture* capture, int index) {
|
||||
++index;
|
||||
if (index >= capture->buffer_size)
|
||||
index = 0;
|
||||
return index;
|
||||
}
|
||||
|
||||
/* Returns true if the trace entry is an annotation string. */
|
||||
bool XRayTraceIsAnnotation(
|
||||
struct XRayTraceCapture* capture, int index) {
|
||||
struct XRayTraceBufferEntry* be = &capture->buffer[index];
|
||||
char* dst = (char*)be;
|
||||
return 0 == *dst;
|
||||
}
|
||||
|
||||
int XRayTraceIncrementIndex(struct XRayTraceCapture* capture, int index) {
|
||||
return XRayTraceIncrementIndexInline(capture, index);
|
||||
}
|
||||
|
||||
int XRayTraceDecrementIndex(struct XRayTraceCapture* capture, int index) {
|
||||
return XRayTraceDecrementIndexInline(capture, index);
|
||||
}
|
||||
|
||||
/* The entry in the tracebuffer at index is an annotation string. */
|
||||
/* Calculate the next index value representing the next trace entry. */
|
||||
int XRayTraceSkipAnnotation(struct XRayTraceCapture* capture, int index) {
|
||||
/* Annotations are strings embedded in the trace buffer. */
|
||||
/* An annotation string can span multiple trace entries. */
|
||||
/* Skip over the string by looking for zero termination. */
|
||||
assert(capture);
|
||||
assert(XRayTraceIsAnnotation(capture, index));
|
||||
bool done = false;
|
||||
int start_index = 1;
|
||||
int i;
|
||||
while (!done) {
|
||||
char* str = (char*) &capture->buffer[index];
|
||||
const int num = sizeof(capture->buffer[index]);
|
||||
for (i = start_index; i < num; ++i) {
|
||||
if (0 == str[i]) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
index = XRayTraceIncrementIndexInline(capture, index);
|
||||
start_index = 0;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
struct XRayTraceBufferEntry* XRayTraceGetEntry(
|
||||
struct XRayTraceCapture* capture, int index) {
|
||||
return &capture->buffer[index];
|
||||
}
|
||||
|
||||
/* Starting at index, return the index into the trace buffer */
|
||||
/* for the next trace entry. Index can wrap (ringbuffer) */
|
||||
int XRayTraceNextEntry(struct XRayTraceCapture* capture, int index) {
|
||||
if (XRayTraceIsAnnotation(capture, index))
|
||||
index = XRayTraceSkipAnnotation(capture, index);
|
||||
else
|
||||
index = XRayTraceIncrementIndexInline(capture, index);
|
||||
return index;
|
||||
}
|
||||
|
||||
int XRayFrameGetTraceStartIndex(struct XRayTraceCapture* capture, int frame) {
|
||||
assert(capture);
|
||||
assert(capture->initialized);
|
||||
assert(!capture->recording);
|
||||
return capture->frame.entry[frame].start;
|
||||
}
|
||||
|
||||
int XRayFrameGetTraceEndIndex(struct XRayTraceCapture* capture, int frame) {
|
||||
assert(capture);
|
||||
assert(capture->initialized);
|
||||
assert(!capture->recording);
|
||||
return capture->frame.entry[frame].end;
|
||||
}
|
||||
|
||||
/* Not very accurate, annotation strings will also be counted as "entries" */
|
||||
int XRayFrameGetTraceCount(
|
||||
struct XRayTraceCapture* capture, int frame) {
|
||||
assert(true == capture->initialized);
|
||||
assert(frame >= 0);
|
||||
assert(frame < capture->frame.count);
|
||||
assert(!capture->recording);
|
||||
int start = capture->frame.entry[frame].start;
|
||||
int end = capture->frame.entry[frame].end;
|
||||
int num;
|
||||
if (start < end)
|
||||
num = end - start;
|
||||
else
|
||||
num = capture->buffer_size - (start - end);
|
||||
return num;
|
||||
}
|
||||
|
||||
/* Append a string to trace buffer. */
|
||||
void XRayTraceAppendString(struct XRayTraceCapture* capture, char* src) {
|
||||
int index = capture->buffer_index;
|
||||
bool done = false;
|
||||
int start_index = 1;
|
||||
int s = 0;
|
||||
int i;
|
||||
char* dst = (char*)&capture->buffer[index];
|
||||
const int num = sizeof(capture->buffer[index]);
|
||||
dst[0] = 0;
|
||||
while (!done) {
|
||||
for (i = start_index; i < num; ++i) {
|
||||
dst[i] = src[s];
|
||||
if (0 == src[s]) {
|
||||
dst[i] = 0;
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
++s;
|
||||
}
|
||||
index = XRayTraceIncrementIndexInline(capture, index);
|
||||
dst = (char*)&capture->buffer[index];
|
||||
start_index = 0;
|
||||
}
|
||||
capture->buffer_index = index;
|
||||
}
|
||||
|
||||
/* Copies annotation from trace buffer to output string. */
|
||||
int XRayTraceCopyToString(
|
||||
struct XRayTraceCapture* capture, int index, char* dst) {
|
||||
assert(XRayTraceIsAnnotation(capture, index));
|
||||
bool done = false;
|
||||
int i;
|
||||
int d = 0;
|
||||
int start_index = 1;
|
||||
while (!done) {
|
||||
char* src = (char*) &capture->buffer[index];
|
||||
const int num = sizeof(capture->buffer[index]);
|
||||
for (i = start_index; i < num; ++i) {
|
||||
dst[d] = src[i];
|
||||
if (0 == src[i]) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
++d;
|
||||
}
|
||||
index = XRayTraceIncrementIndexInline(capture, index);
|
||||
start_index = 0;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
|
||||
/* Generic memory malloc for XRay */
|
||||
/* validates pointer returned by malloc */
|
||||
/* memsets memory block to zero */
|
||||
void* XRayMalloc(size_t t) {
|
||||
void* data;
|
||||
data = calloc(1, t);
|
||||
if (NULL == data) {
|
||||
printf("XRay: malloc(%d) failed, panic shutdown!\n", t);
|
||||
exit(-1);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
/* Generic memory free for XRay */
|
||||
void XRayFree(void* data) {
|
||||
assert(NULL != data);
|
||||
free(data);
|
||||
}
|
||||
|
||||
|
||||
/* Main profile capture function that is called at the start */
|
||||
/* of every instrumented function. This function is implicitly */
|
||||
/* called when code is compilied with the -finstrument-functions option */
|
||||
#if defined(__pnacl__)
|
||||
void __pnacl_profile_func_enter(const char* this_fn) {
|
||||
#else
|
||||
void __cyg_profile_func_enter(void* this_fn, void* call_site) {
|
||||
#endif
|
||||
struct XRayTraceCapture* capture = g_xray_capture;
|
||||
if (capture && capture->recording) {
|
||||
uint32_t depth = capture->stack_depth;
|
||||
if (depth < capture->max_stack_depth) {
|
||||
struct XRayTraceStackEntry* se = &capture->stack[depth];
|
||||
uint32_t addr = (uint32_t)(uintptr_t)this_fn;
|
||||
se->depth_addr = XRAY_PACK_DEPTH_ADDR(depth, addr);
|
||||
se->dest = capture->buffer_index;
|
||||
se->annotation_index = 0;
|
||||
GTSC(se->tsc);
|
||||
capture->buffer_index =
|
||||
XRayTraceIncrementIndexInline(capture, capture->buffer_index);
|
||||
}
|
||||
++capture->stack_depth;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Main profile capture function that is called at the exit of */
|
||||
/* every instrumented function. This function is implicity called */
|
||||
/* when the code is compiled with the -finstrument-functions option */
|
||||
#if defined(__pnacl__)
|
||||
void __pnacl_profile_func_exit(const char* this_fn) {
|
||||
#else
|
||||
void __cyg_profile_func_exit(void* this_fn, void* call_site) {
|
||||
#endif
|
||||
struct XRayTraceCapture* capture = g_xray_capture;
|
||||
if (capture && capture->recording) {
|
||||
--capture->stack_depth;
|
||||
if (capture->stack_depth < capture->max_stack_depth) {
|
||||
uint32_t depth = capture->stack_depth;
|
||||
struct XRayTraceStackEntry* se = &capture->stack[depth];
|
||||
uint32_t buffer_index = se->dest;
|
||||
uint64_t tsc;
|
||||
struct XRayTraceBufferEntry* be = &capture->buffer[buffer_index];
|
||||
GTSC(tsc);
|
||||
be->depth_addr = se->depth_addr;
|
||||
be->start_tick = se->tsc;
|
||||
be->end_tick = tsc;
|
||||
be->annotation_index = 0;
|
||||
if (0 != se->annotation_index)
|
||||
__xray_profile_append_annotation(capture, se, be);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef XRAY_DISABLE_BROWSER_INTEGRATION
|
||||
void XRayGetTSC(uint64_t* tsc) {
|
||||
GTSC(*tsc);
|
||||
}
|
||||
|
||||
int32_t XRayGetSavedThreadID(struct XRayTraceCapture* capture) {
|
||||
return capture->thread_id;
|
||||
}
|
||||
|
||||
struct XRayTimestampPair XRayFrameGetStartTimestampPair(
|
||||
struct XRayTraceCapture* capture, int frame) {
|
||||
return capture->frame.entry[frame].start_time;
|
||||
}
|
||||
|
||||
struct XRayTimestampPair XRayFrameGetEndTimestampPair(
|
||||
struct XRayTraceCapture* capture, int frame) {
|
||||
return capture->frame.entry[frame].end_time;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Special case appending annotation string to trace buffer */
|
||||
/* this function should only ever be called from __cyg_profile_func_exit() */
|
||||
void __xray_profile_append_annotation(struct XRayTraceCapture* capture,
|
||||
struct XRayTraceStackEntry* se,
|
||||
struct XRayTraceBufferEntry* be) {
|
||||
struct XRayTraceStackEntry* parent = se - 1;
|
||||
int start = parent->annotation_index;
|
||||
be->annotation_index = capture->buffer_index;
|
||||
char* str = &capture->annotation[start];
|
||||
XRayTraceAppendString(capture, str);
|
||||
*str = 0;
|
||||
++capture->annotation_count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Annotates the trace buffer. no filtering. */
|
||||
void __XRayAnnotate(const char* fmt, ...) {
|
||||
va_list args;
|
||||
struct XRayTraceCapture* capture = g_xray_capture;
|
||||
/* Only annotate functions recorded in the trace buffer. */
|
||||
if (capture && capture->initialized) {
|
||||
if (0 == capture->disabled) {
|
||||
if (capture->recording) {
|
||||
char buffer[1024];
|
||||
int r;
|
||||
va_start(args, fmt);
|
||||
r = vsnprintf(buffer, sizeof(buffer), fmt, args);
|
||||
va_end(args);
|
||||
{
|
||||
/* Get current string ptr */
|
||||
int depth = capture->stack_depth - 1;
|
||||
struct XRayTraceStackEntry* se = &capture->stack[depth];
|
||||
if (0 == se->annotation_index) {
|
||||
struct XRayTraceStackEntry* parent = se - 1;
|
||||
se->annotation_index = parent->annotation_index;
|
||||
}
|
||||
char* dst = &capture->annotation[se->annotation_index];
|
||||
strcpy(dst, buffer);
|
||||
int len = strlen(dst);
|
||||
se->annotation_index += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Annotates the trace buffer with user strings. Can be filtered. */
|
||||
void __XRayAnnotateFiltered(const uint32_t filter, const char* fmt, ...) {
|
||||
va_list args;
|
||||
struct XRayTraceCapture* capture = g_xray_capture;
|
||||
if (capture && capture->initialized) {
|
||||
if (0 != (filter & capture->annotation_filter)) {
|
||||
if (0 == capture->disabled) {
|
||||
if (capture->recording) {
|
||||
char buffer[XRAY_TRACE_ANNOTATION_LENGTH];
|
||||
int r;
|
||||
va_start(args, fmt);
|
||||
r = vsnprintf(buffer, sizeof(buffer), fmt, args);
|
||||
va_end(args);
|
||||
{
|
||||
/* get current string ptr */
|
||||
int depth = capture->stack_depth - 1;
|
||||
struct XRayTraceStackEntry* se = &capture->stack[depth];
|
||||
if (0 == se->annotation_index) {
|
||||
struct XRayTraceStackEntry* parent = se - 1;
|
||||
se->annotation_index = parent->annotation_index;
|
||||
}
|
||||
char* dst = &capture->annotation[se->annotation_index];
|
||||
strcpy(dst, buffer);
|
||||
int len = strlen(dst);
|
||||
se->annotation_index += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Allows user to specify annotation filter value, a 32 bit mask. */
|
||||
void XRaySetAnnotationFilter(struct XRayTraceCapture* capture,
|
||||
uint32_t filter) {
|
||||
capture->annotation_filter = filter;
|
||||
}
|
||||
|
||||
|
||||
/* Reset xray profiler. */
|
||||
void XRayReset(struct XRayTraceCapture* capture) {
|
||||
assert(capture);
|
||||
assert(capture->initialized);
|
||||
assert(!capture->recording);
|
||||
capture->buffer_index = 0;
|
||||
capture->stack_depth = 0;
|
||||
capture->disabled = 0;
|
||||
capture->frame.head = 0;
|
||||
capture->frame.tail = 0;
|
||||
memset(capture->frame.entry, 0,
|
||||
sizeof(capture->frame.entry[0]) * capture->frame.count);
|
||||
memset(&capture->stack, 0,
|
||||
sizeof(capture->stack[0]) * XRAY_TRACE_STACK_SIZE);
|
||||
XRayCheckGuards(capture);
|
||||
}
|
||||
|
||||
|
||||
/* Change the maximum stack depth captures are made. */
|
||||
void XRaySetMaxStackDepth(struct XRayTraceCapture* capture, int stack_depth) {
|
||||
assert(capture);
|
||||
assert(capture->initialized);
|
||||
assert(!capture->recording);
|
||||
if (stack_depth < 1)
|
||||
stack_depth = 1;
|
||||
if (stack_depth >= XRAY_TRACE_STACK_SIZE)
|
||||
stack_depth = (XRAY_TRACE_STACK_SIZE - 1);
|
||||
capture->max_stack_depth = stack_depth;
|
||||
}
|
||||
|
||||
|
||||
int XRayFrameGetCount(struct XRayTraceCapture* capture) {
|
||||
return capture->frame.count;
|
||||
}
|
||||
|
||||
int XRayFrameGetTail(struct XRayTraceCapture* capture) {
|
||||
return capture->frame.tail;
|
||||
}
|
||||
|
||||
int XRayFrameGetHead(struct XRayTraceCapture* capture) {
|
||||
return capture->frame.head;
|
||||
}
|
||||
|
||||
int XRayFrameGetPrev(struct XRayTraceCapture* capture, int i) {
|
||||
i = i - 1;
|
||||
if (i < 0)
|
||||
i = capture->frame.count - 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
int XRayFrameGetNext(struct XRayTraceCapture* capture, int i) {
|
||||
i = i + 1;
|
||||
if (i >= capture->frame.count)
|
||||
i = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
bool XRayFrameIsValid(struct XRayTraceCapture* capture, int i) {
|
||||
return capture->frame.entry[i].valid;
|
||||
}
|
||||
|
||||
uint64_t XRayFrameGetTotalTicks(struct XRayTraceCapture* capture, int i) {
|
||||
return capture->frame.entry[i].total_ticks;
|
||||
}
|
||||
|
||||
int XRayFrameGetAnnotationCount(struct XRayTraceCapture* capture, int i) {
|
||||
return capture->frame.entry[i].annotation_count;
|
||||
}
|
||||
|
||||
void XRayFrameMakeLabel(struct XRayTraceCapture* capture,
|
||||
int counter,
|
||||
char* label) {
|
||||
snprintf(label, XRAY_MAX_LABEL, "@@@frame%d@@@", counter);
|
||||
}
|
||||
|
||||
|
||||
/* Scans the ring buffer going backwards to find last valid complete frame. */
|
||||
/* Will mark whether frames are valid or invalid during the traversal. */
|
||||
int XRayFrameFindTail(struct XRayTraceCapture* capture) {
|
||||
int head = capture->frame.head;
|
||||
int index = XRayFrameGetPrev(capture, head);
|
||||
int total_capture = 0;
|
||||
int last_valid_frame = index;
|
||||
/* Check for no captures */
|
||||
if (capture->frame.head == capture->frame.tail)
|
||||
return capture->frame.head;
|
||||
/* Go back and invalidate all captures that have been stomped. */
|
||||
while (index != head) {
|
||||
bool valid = capture->frame.entry[index].valid;
|
||||
if (valid) {
|
||||
total_capture += XRayFrameGetTraceCount(capture, index) + 1;
|
||||
if (total_capture < capture->buffer_size) {
|
||||
last_valid_frame = index;
|
||||
capture->frame.entry[index].valid = true;
|
||||
} else {
|
||||
capture->frame.entry[index].valid = false;
|
||||
}
|
||||
}
|
||||
index = XRayFrameGetPrev(capture, index);
|
||||
}
|
||||
return last_valid_frame;
|
||||
}
|
||||
|
||||
|
||||
/* Starts a new frame and enables capturing, and must be paired with */
|
||||
/* XRayEndFrame() Trace capturing only occurs on the thread which called */
|
||||
/* XRayBeginFrame() and each instance of capture can only trace one thread */
|
||||
/* at a time. */
|
||||
void XRayStartFrame(struct XRayTraceCapture* capture) {
|
||||
int i;
|
||||
assert(NULL == g_xray_capture);
|
||||
assert(capture->initialized);
|
||||
assert(!capture->recording);
|
||||
i = capture->frame.head;
|
||||
XRayCheckGuards(capture);
|
||||
/* Add a trace entry marker so we can detect wrap around stomping */
|
||||
struct XRayTraceBufferEntry* be = &capture->buffer[capture->buffer_index];
|
||||
be->depth_addr = XRAY_FRAME_MARKER;
|
||||
capture->buffer_index =
|
||||
XRayTraceIncrementIndex(capture, capture->buffer_index);
|
||||
/* Set start of the frame we're about to trace */
|
||||
capture->frame.entry[i].start = capture->buffer_index;
|
||||
capture->disabled = 0;
|
||||
capture->stack_depth = 1;
|
||||
|
||||
/* The trace stack[0] is reserved */
|
||||
memset(&capture->stack[0], 0, sizeof(capture->stack[0]));
|
||||
/* Annotation index 0 is reserved to indicate no annotation */
|
||||
capture->stack[0].annotation_index = 1;
|
||||
capture->annotation[0] = 0;
|
||||
capture->annotation[1] = 0;
|
||||
capture->annotation_count = 0;
|
||||
capture->recording = true;
|
||||
GTSC(capture->frame.entry[i].start_tsc);
|
||||
g_xray_capture = capture;
|
||||
|
||||
#ifndef XRAY_DISABLE_BROWSER_INTEGRATION
|
||||
capture->frame.entry[i].start_time = XRayGenerateTimestampsNow();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Ends a frame and disables capturing. Advances to the next frame. */
|
||||
/* Must be paired with XRayStartFrame(), and called from the same thread. */
|
||||
void XRayEndFrame(struct XRayTraceCapture* capture) {
|
||||
int i;
|
||||
assert(capture);
|
||||
assert(capture->initialized);
|
||||
assert(capture->recording);
|
||||
assert(g_xray_capture == capture);
|
||||
assert(0 == capture->disabled);
|
||||
assert(1 == capture->stack_depth);
|
||||
i = capture->frame.head;
|
||||
GTSC(capture->frame.entry[i].end_tsc);
|
||||
capture->frame.entry[i].total_ticks =
|
||||
capture->frame.entry[i].end_tsc - capture->frame.entry[i].start_tsc;
|
||||
capture->recording = NULL;
|
||||
capture->frame.entry[i].end = capture->buffer_index;
|
||||
capture->frame.entry[i].valid = true;
|
||||
capture->frame.entry[i].annotation_count = capture->annotation_count;
|
||||
capture->frame.head = XRayFrameGetNext(capture, capture->frame.head);
|
||||
/* If the table is filled, bump the tail. */
|
||||
if (capture->frame.head == capture->frame.tail)
|
||||
capture->frame.tail = XRayFrameGetNext(capture, capture->frame.tail);
|
||||
capture->frame.tail = XRayFrameFindTail(capture);
|
||||
/* Check that we didn't stomp over trace entry marker. */
|
||||
int marker = XRayTraceDecrementIndex(capture, capture->frame.entry[i].start);
|
||||
struct XRayTraceBufferEntry* be = &capture->buffer[marker];
|
||||
if (be->depth_addr != XRAY_FRAME_MARKER) {
|
||||
fprintf(stderr,
|
||||
"XRay: XRayStopFrame() detects insufficient trace buffer size!\n");
|
||||
XRayReset(capture);
|
||||
} else {
|
||||
/* Replace marker with an empty annotation string. */
|
||||
be->depth_addr = XRAY_NULL_ANNOTATION;
|
||||
XRayCheckGuards(capture);
|
||||
}
|
||||
g_xray_capture = NULL;
|
||||
|
||||
#ifndef XRAY_DISABLE_BROWSER_INTEGRATION
|
||||
capture->frame.entry[i].end_time = XRayGenerateTimestampsNow();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Get the last frame captured. Do not call while capturing. */
|
||||
/* (ie call outside of XRayStartFrame() / XRayStopFrame() pair) */
|
||||
int XRayGetLastFrame(struct XRayTraceCapture* capture) {
|
||||
assert(capture);
|
||||
assert(capture->initialized);
|
||||
assert(!capture->recording);
|
||||
assert(0 == capture->disabled);
|
||||
assert(1 == capture->stack_depth);
|
||||
int last_frame = XRayFrameGetPrev(capture, capture->frame.head);
|
||||
return last_frame;
|
||||
}
|
||||
|
||||
|
||||
/* Disables capturing until a paired XRayEnableCapture() is called */
|
||||
/* This call can be nested, but must be paired with an enable */
|
||||
/* (If you need to just exclude a specific function and not its */
|
||||
/* children, the XRAY_NO_INSTRUMENT modifier might be better) */
|
||||
/* Must be called from same thread as XRayBeginFrame() / XRayEndFrame() */
|
||||
void XRayDisableCapture(struct XRayTraceCapture* capture) {
|
||||
assert(capture);
|
||||
assert(capture == g_xray_capture);
|
||||
assert(capture->initialized);
|
||||
++capture->disabled;
|
||||
capture->recording = false;
|
||||
}
|
||||
|
||||
|
||||
/* Re-enables capture. Must be paired with XRayDisableCapture() */
|
||||
void XRayEnableCapture(struct XRayTraceCapture* capture) {
|
||||
assert(capture);
|
||||
assert(capture == g_xray_capture);
|
||||
assert(capture->initialized);
|
||||
assert(0 < capture->disabled);
|
||||
--capture->disabled;
|
||||
if (0 == capture->disabled) {
|
||||
capture->recording = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct XRaySymbolTable* XRayGetSymbolTable(struct XRayTraceCapture* capture) {
|
||||
return capture->symbols;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize XRay */
|
||||
struct XRayTraceCapture* XRayInit(int stack_depth,
|
||||
int buffer_size,
|
||||
int frame_count,
|
||||
const char* mapfilename) {
|
||||
struct XRayTraceCapture* capture;
|
||||
capture = (struct XRayTraceCapture*)XRayMalloc(
|
||||
sizeof(struct XRayTraceCapture));
|
||||
int adj_frame_count = frame_count + 1;
|
||||
size_t buffer_size_in_bytes =
|
||||
sizeof(capture->buffer[0]) * buffer_size;
|
||||
size_t frame_size_in_bytes =
|
||||
sizeof(capture->frame.entry[0]) * adj_frame_count;
|
||||
capture->buffer =
|
||||
(struct XRayTraceBufferEntry *)XRayMalloc(buffer_size_in_bytes);
|
||||
capture->frame.entry =
|
||||
(struct XRayTraceFrameEntry *)XRayMalloc(frame_size_in_bytes);
|
||||
capture->buffer_size = buffer_size;
|
||||
capture->frame.count = adj_frame_count;
|
||||
capture->frame.head = 0;
|
||||
capture->frame.tail = 0;
|
||||
capture->disabled = 0;
|
||||
capture->annotation_filter = 0xFFFFFFFF;
|
||||
capture->guard0 = XRAY_GUARD_VALUE_0x12345678;
|
||||
capture->guard1 = XRAY_GUARD_VALUE_0x12345678;
|
||||
capture->guard2 = XRAY_GUARD_VALUE_0x87654321;
|
||||
capture->guard3 = XRAY_GUARD_VALUE_0x12345678;
|
||||
capture->initialized = true;
|
||||
capture->recording = false;
|
||||
XRaySetMaxStackDepth(capture, stack_depth);
|
||||
XRayReset(capture);
|
||||
|
||||
/* Mapfile is optional; we don't need it for captures, only for reports. */
|
||||
capture->symbols =
|
||||
XRaySymbolTableCreate(XRAY_DEFAULT_SYMBOL_TABLE_SIZE);
|
||||
if (NULL != mapfilename)
|
||||
XRaySymbolTableParseMapfile(capture->symbols, mapfilename);
|
||||
|
||||
#ifndef XRAY_DISABLE_BROWSER_INTEGRATION
|
||||
/* Use the address of a thread local variable as a fake thread id. */
|
||||
capture->thread_id = (int32_t)(&g_xray_thread_id_placeholder);
|
||||
#endif
|
||||
|
||||
return capture;
|
||||
}
|
||||
|
||||
|
||||
/* Shut down and free memory used by XRay. */
|
||||
void XRayShutdown(struct XRayTraceCapture* capture) {
|
||||
assert(capture);
|
||||
assert(capture->initialized);
|
||||
assert(!capture->recording);
|
||||
XRayCheckGuards(capture);
|
||||
if (NULL != capture->symbols) {
|
||||
XRaySymbolTableFree(capture->symbols);
|
||||
}
|
||||
XRayFree(capture->frame.entry);
|
||||
XRayFree(capture->buffer);
|
||||
capture->initialized = false;
|
||||
XRayFree(capture);
|
||||
}
|
||||
|
||||
#endif /* XRAY */
|
117
hermit/usr/xray/xray.h
Normal file
117
hermit/usr/xray/xray.h
Normal file
|
@ -0,0 +1,117 @@
|
|||
/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file. */
|
||||
|
||||
/* XRay -- a simple profiler for Native Client */
|
||||
|
||||
|
||||
#ifndef LIBRARIES_XRAY_XRAY_H_
|
||||
#define LIBRARIES_XRAY_XRAY_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef XRAY_DISABLE_BROWSER_INTEGRATION
|
||||
#include "ppapi/c/ppb.h"
|
||||
#endif
|
||||
|
||||
#if defined(__arm__)
|
||||
#undef XRAY
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define XRAY_NO_INSTRUMENT __attribute__((no_instrument_function))
|
||||
#define XRAY_INLINE __attribute__((always_inline, no_instrument_function))
|
||||
|
||||
#if defined(XRAY)
|
||||
|
||||
/* Do not call __XRayAnnotate* directly; instead use the */
|
||||
/* XRayAnnotate() macros below. */
|
||||
XRAY_NO_INSTRUMENT void __XRayAnnotate(const char* str, ...)
|
||||
__attribute__ ((format(printf, 1, 2)));
|
||||
XRAY_NO_INSTRUMENT void __XRayAnnotateFiltered(const uint32_t filter,
|
||||
const char* str, ...) __attribute__ ((format(printf, 2, 3)));
|
||||
|
||||
/* This is the beginning of the public XRay API */
|
||||
|
||||
/* Ok if mapfilename is NULL, no symbols will be loaded. On glibc builds,
|
||||
* XRay will also attempt to populate the symbol table with dladdr()
|
||||
*/
|
||||
XRAY_NO_INSTRUMENT struct XRayTraceCapture* XRayInit(int stack_size,
|
||||
int buffer_size,
|
||||
int frame_count,
|
||||
const char* mapfilename);
|
||||
XRAY_NO_INSTRUMENT void XRayShutdown(struct XRayTraceCapture* capture);
|
||||
XRAY_NO_INSTRUMENT void XRayStartFrame(struct XRayTraceCapture* capture);
|
||||
XRAY_NO_INSTRUMENT void XRayEndFrame(struct XRayTraceCapture* capture);
|
||||
XRAY_NO_INSTRUMENT void XRaySetAnnotationFilter(
|
||||
struct XRayTraceCapture* capture, uint32_t filter);
|
||||
XRAY_NO_INSTRUMENT void XRaySaveReport(struct XRayTraceCapture* capture,
|
||||
const char* filename,
|
||||
float percent_cutoff,
|
||||
int cycle_cutoff);
|
||||
XRAY_NO_INSTRUMENT void XRayReport(struct XRayTraceCapture* capture,
|
||||
FILE* f,
|
||||
float percent_cutoff,
|
||||
int ticks_cutoff);
|
||||
|
||||
#ifndef XRAY_DISABLE_BROWSER_INTEGRATION
|
||||
XRAY_NO_INSTRUMENT void XRayBrowserTraceReport(
|
||||
struct XRayTraceCapture* capture);
|
||||
XRAY_NO_INSTRUMENT void XRayRegisterBrowserInterface(
|
||||
PPB_GetInterface get_browser_interface);
|
||||
#endif /* XRAY_DISABLE_BROWSER_INTEGRATION */
|
||||
|
||||
|
||||
#if defined(XRAY_ANNOTATE)
|
||||
#define XRayAnnotate(...) __XRayAnnotate(__VA_ARGS__)
|
||||
#define XRayAnnotateFiltered(...) __XRayAnnotateFiltered(__VA_ARGS__)
|
||||
#else
|
||||
#define XRayAnnotate(...)
|
||||
#define XRayAnnotateFiltered(...)
|
||||
#endif
|
||||
/* This is the end of the public XRay API */
|
||||
|
||||
#else /* defined(XRAY) */
|
||||
|
||||
/* Builds that don't define XRAY will use these 'null' functions instead. */
|
||||
|
||||
#define XRayAnnotate(...)
|
||||
#define XRayAnnotateFiltered(...)
|
||||
|
||||
inline struct XRayTraceCapture* XRayInit(int stack_size,
|
||||
int buffer_size,
|
||||
int frame_count,
|
||||
const char* mapfilename) {
|
||||
return NULL;
|
||||
}
|
||||
inline void XRayShutdown(struct XRayTraceCapture* capture) {}
|
||||
inline void XRayStartFrame(struct XRayTraceCapture* capture) {}
|
||||
inline void XRayEndFrame(struct XRayTraceCapture* capture) {}
|
||||
inline void XRaySetAnnotationFilter(struct XRayTraceCapture* capture,
|
||||
uint32_t filter) {}
|
||||
inline void XRaySaveReport(struct XRayTraceCapture* capture,
|
||||
const char* filename,
|
||||
float percent_cutoff,
|
||||
int cycle_cutoff) {}
|
||||
inline void XRayReport(struct XRayTraceCapture* capture,
|
||||
FILE* f,
|
||||
float percent_cutoff,
|
||||
int ticks_cutoff) {}
|
||||
|
||||
#ifndef XRAY_DISABLE_BROWSER_INTEGRATION
|
||||
inline void XRayBrowserTraceReport(struct XRayTraceCapture* capture) {}
|
||||
inline void XRayRegisterBrowserInterface(
|
||||
PPB_GetInterface get_browser_interface) {}
|
||||
#endif /* XRAY_DISABLE_BROWSER_INTEGRATION */
|
||||
|
||||
|
||||
#endif /* defined(XRAY) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBRARIES_XRAY_XRAY_H_ */
|
BIN
hermit/usr/xray/xray.odt
Normal file
BIN
hermit/usr/xray/xray.odt
Normal file
Binary file not shown.
207
hermit/usr/xray/xray_priv.h
Normal file
207
hermit/usr/xray/xray_priv.h
Normal file
|
@ -0,0 +1,207 @@
|
|||
/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file. */
|
||||
|
||||
/* XRay -- a simple profiler for Native Client */
|
||||
|
||||
/* This header file is the private internal interface. */
|
||||
|
||||
#ifndef LIBRARIES_XRAY_XRAY_PRIV_H_
|
||||
#define LIBRARIES_XRAY_XRAY_PRIV_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "xray/xray.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(XRAY)
|
||||
|
||||
#define XRAY_FORCE_INLINE __attribute__((always_inline, no_instrument_function))
|
||||
|
||||
#define XRAY_TRACE_STACK_SIZE (256)
|
||||
#define XRAY_TRACE_ANNOTATION_LENGTH (2048)
|
||||
#define XRAY_TRACE_BUFFER_SIZE (1048576)
|
||||
#define XRAY_ANNOTATION_STACK_SIZE ((XRAY_TRACE_STACK_SIZE) * \
|
||||
(XRAY_TRACE_ANNOTATION_LENGTH))
|
||||
#define XRAY_STRING_POOL_NODE_SIZE (32768)
|
||||
#define XRAY_FRAME_MARKER (0xFFFFFFFF)
|
||||
#define XRAY_NULL_ANNOTATION (0x0)
|
||||
#define XRAY_FUNCTION_ALIGNMENT_BITS (4)
|
||||
#define XRAY_ADDR_MASK (0xFFFFFF00)
|
||||
#define XRAY_ADDR_SHIFT (4)
|
||||
#define XRAY_DEPTH_MASK (0x000000FF)
|
||||
#define XRAY_SYMBOL_TABLE_MAX_RATIO (0.66f)
|
||||
#define XRAY_LINE_SIZE (1024)
|
||||
#define XRAY_MAX_FRAMES (60)
|
||||
#define XRAY_MAX_LABEL (64)
|
||||
#define XRAY_DEFAULT_SYMBOL_TABLE_SIZE (4096)
|
||||
#define XRAY_SYMBOL_POOL_NODE_SIZE (1024)
|
||||
#define XRAY_GUARD_VALUE_0x12345678 (0x12345678)
|
||||
#define XRAY_GUARD_VALUE_0x87654321 (0x87654321)
|
||||
#define XRAY_EXTRACT_ADDR(x) (((x) & XRAY_ADDR_MASK) >> XRAY_ADDR_SHIFT)
|
||||
#define XRAY_EXTRACT_DEPTH(x) ((x) & XRAY_DEPTH_MASK)
|
||||
#define XRAY_PACK_ADDR(x) (((x) << XRAY_ADDR_SHIFT) & XRAY_ADDR_MASK)
|
||||
#define XRAY_PACK_DEPTH(x) ((x) & XRAY_DEPTH_MASK)
|
||||
#define XRAY_PACK_DEPTH_ADDR(d, a) (XRAY_PACK_DEPTH(d) | XRAY_PACK_ADDR(a))
|
||||
#define XRAY_ALIGN64 __attribute((aligned(64)))
|
||||
|
||||
struct XRayStringPool;
|
||||
struct XRayHashTable;
|
||||
struct XRaySymbolPool;
|
||||
struct XRaySymbol;
|
||||
struct XRaySymbolTable;
|
||||
struct XRayTraceCapture;
|
||||
|
||||
struct XRayTraceBufferEntry {
|
||||
uint32_t depth_addr;
|
||||
uint32_t annotation_index;
|
||||
uint64_t start_tick;
|
||||
uint64_t end_tick;
|
||||
};
|
||||
|
||||
|
||||
/* Important: don't instrument xray itself, so use */
|
||||
/* XRAY_NO_INSTRUMENT on all xray functions */
|
||||
|
||||
XRAY_NO_INSTRUMENT char* XRayStringPoolAppend(struct XRayStringPool* pool,
|
||||
const char* src);
|
||||
XRAY_NO_INSTRUMENT struct XRayStringPool* XRayStringPoolCreate();
|
||||
XRAY_NO_INSTRUMENT void XRayStringPoolFree(struct XRayStringPool* pool);
|
||||
|
||||
XRAY_NO_INSTRUMENT void* XRayHashTableLookup(struct XRayHashTable* table,
|
||||
uint32_t addr);
|
||||
XRAY_NO_INSTRUMENT void* XRayHashTableInsert(struct XRayHashTable* table,
|
||||
void* data, uint32_t addr);
|
||||
XRAY_NO_INSTRUMENT void* XRayHashTableAtIndex(
|
||||
struct XRayHashTable* table, int i);
|
||||
XRAY_NO_INSTRUMENT int XRayHashTableGetCapacity(struct XRayHashTable* table);
|
||||
XRAY_NO_INSTRUMENT int XRayHashTableGetCount(struct XRayHashTable* table);
|
||||
XRAY_NO_INSTRUMENT struct XRayHashTable* XRayHashTableCreate(int capacity);
|
||||
XRAY_NO_INSTRUMENT void XRayHashTableFree(struct XRayHashTable* table);
|
||||
XRAY_NO_INSTRUMENT void XRayHashTableHisto(FILE* f);
|
||||
|
||||
XRAY_NO_INSTRUMENT struct XRaySymbol* XRaySymbolPoolAlloc(
|
||||
struct XRaySymbolPool* sympool);
|
||||
XRAY_NO_INSTRUMENT struct XRaySymbolPool* XRaySymbolPoolCreate();
|
||||
XRAY_NO_INSTRUMENT void XRaySymbolPoolFree(struct XRaySymbolPool* sympool);
|
||||
|
||||
XRAY_NO_INSTRUMENT const char* XRayDemangle(char* demangle, size_t buffersize,
|
||||
const char* symbol);
|
||||
|
||||
XRAY_NO_INSTRUMENT const char* XRaySymbolGetName(struct XRaySymbol* symbol);
|
||||
XRAY_NO_INSTRUMENT struct XRaySymbol* XRaySymbolCreate(
|
||||
struct XRaySymbolPool* sympool, const char* name);
|
||||
XRAY_NO_INSTRUMENT void XRaySymbolFree(struct XRaySymbol* symbol);
|
||||
XRAY_NO_INSTRUMENT int XRaySymbolCount(struct XRaySymbolTable* symtab);
|
||||
|
||||
XRAY_NO_INSTRUMENT struct XRaySymbol* XRaySymbolTableCreateEntry(
|
||||
struct XRaySymbolTable* symtab, char* line);
|
||||
XRAY_NO_INSTRUMENT void XRaySymbolTableParseMapfile(
|
||||
struct XRaySymbolTable* symbols, const char* mapfilename);
|
||||
|
||||
XRAY_NO_INSTRUMENT struct XRaySymbol* XRaySymbolTableAddByName(
|
||||
struct XRaySymbolTable* symtab, const char* name, uint32_t addr);
|
||||
|
||||
XRAY_NO_INSTRUMENT int XRaySymbolTableGetCount(struct XRaySymbolTable* symtab);
|
||||
XRAY_NO_INSTRUMENT struct XRaySymbol* XRaySymbolTableLookup(
|
||||
struct XRaySymbolTable* symbols, uint32_t addr);
|
||||
XRAY_NO_INSTRUMENT struct XRaySymbol* XRaySymbolTableAtIndex(
|
||||
struct XRaySymbolTable* symbols, int i);
|
||||
XRAY_NO_INSTRUMENT struct XRaySymbolTable* XRaySymbolTableCreate(int size);
|
||||
XRAY_NO_INSTRUMENT void XRaySymbolTableFree(struct XRaySymbolTable* symbtab);
|
||||
|
||||
XRAY_NO_INSTRUMENT struct XRaySymbolTable* XRayGetSymbolTable(
|
||||
struct XRayTraceCapture* capture);
|
||||
|
||||
XRAY_NO_INSTRUMENT void XRayCheckGuards(struct XRayTraceCapture* capture);
|
||||
|
||||
XRAY_NO_INSTRUMENT struct XRayTraceBufferEntry* XRayTraceGetEntry(
|
||||
struct XRayTraceCapture* capture, int index);
|
||||
XRAY_NO_INSTRUMENT int XRayTraceIncrementIndex(
|
||||
struct XRayTraceCapture* capture, int i);
|
||||
XRAY_NO_INSTRUMENT int XRayTraceDecrementIndex(
|
||||
struct XRayTraceCapture* capture, int i);
|
||||
XRAY_NO_INSTRUMENT bool XRayTraceIsAnnotation(
|
||||
struct XRayTraceCapture* capture, int index);
|
||||
XRAY_NO_INSTRUMENT void XRayTraceAppendString(
|
||||
struct XRayTraceCapture* capture, char* src);
|
||||
XRAY_NO_INSTRUMENT int XRayTraceCopyToString(
|
||||
struct XRayTraceCapture* capture, int index, char* dst);
|
||||
XRAY_NO_INSTRUMENT int XRayTraceSkipAnnotation(
|
||||
struct XRayTraceCapture* capture, int index);
|
||||
XRAY_NO_INSTRUMENT int XRayTraceNextEntry(
|
||||
struct XRayTraceCapture* capture, int index);
|
||||
|
||||
XRAY_NO_INSTRUMENT void XRayFrameMakeLabel(struct XRayTraceCapture* capture,
|
||||
int counter,
|
||||
char* label);
|
||||
XRAY_NO_INSTRUMENT int XRayFrameFindTail(struct XRayTraceCapture* capture);
|
||||
|
||||
XRAY_NO_INSTRUMENT int XRayFrameGetCount(struct XRayTraceCapture* capture);
|
||||
XRAY_NO_INSTRUMENT int XRayFrameGetHead(struct XRayTraceCapture* capture);
|
||||
XRAY_NO_INSTRUMENT int XRayFrameGetTail(struct XRayTraceCapture* capture);
|
||||
XRAY_NO_INSTRUMENT int XRayFrameGetNext(
|
||||
struct XRayTraceCapture* capture, int index);
|
||||
XRAY_NO_INSTRUMENT uint64_t XRayFrameGetTotalTicks(
|
||||
struct XRayTraceCapture* capture, int frame);
|
||||
XRAY_NO_INSTRUMENT int XRayFrameGetTraceCount(
|
||||
struct XRayTraceCapture* capture, int frame);
|
||||
XRAY_NO_INSTRUMENT int XRayFrameGetTraceStartIndex(
|
||||
struct XRayTraceCapture* capture, int frame);
|
||||
XRAY_NO_INSTRUMENT int XRayFrameGetTraceEndIndex(
|
||||
struct XRayTraceCapture* capture, int frame);
|
||||
XRAY_NO_INSTRUMENT int XRayFrameGetAnnotationCount(
|
||||
struct XRayTraceCapture* capture, int frame);
|
||||
XRAY_NO_INSTRUMENT bool XRayFrameIsValid(
|
||||
struct XRayTraceCapture* capture, int frame);
|
||||
|
||||
|
||||
XRAY_NO_INSTRUMENT void XRayTraceReport(struct XRayTraceCapture* capture,
|
||||
FILE* f,
|
||||
int frame,
|
||||
char* label,
|
||||
float percent_cutoff,
|
||||
int ticks_cutoff);
|
||||
XRAY_NO_INSTRUMENT void XRayFrameReport(struct XRayTraceCapture* capture,
|
||||
FILE* f);
|
||||
|
||||
XRAY_NO_INSTRUMENT void* XRayMalloc(size_t t);
|
||||
XRAY_NO_INSTRUMENT void XRayFree(void* data);
|
||||
|
||||
XRAY_NO_INSTRUMENT void XRaySetMaxStackDepth(
|
||||
struct XRayTraceCapture* capture, int stack_depth);
|
||||
XRAY_NO_INSTRUMENT int XRayGetLastFrame(struct XRayTraceCapture* capture);
|
||||
XRAY_NO_INSTRUMENT void XRayDisableCapture(struct XRayTraceCapture* capture);
|
||||
XRAY_NO_INSTRUMENT void XRayEnableCapture(struct XRayTraceCapture* capture);
|
||||
XRAY_NO_INSTRUMENT void XRayLoadMapfile(
|
||||
struct XRayTraceCapture* capture, const char* mapfilename);
|
||||
|
||||
struct XRayTimestampPair {
|
||||
uint64_t xray; /* internal xray timestamp */
|
||||
int64_t pepper; /* corresponding timestamp from PPAPI interface */
|
||||
};
|
||||
|
||||
#ifndef XRAY_DISABLE_BROWSER_INTEGRATION
|
||||
XRAY_NO_INSTRUMENT void XRayGetTSC(uint64_t* tsc);
|
||||
XRAY_NO_INSTRUMENT int32_t XRayGetSavedThreadID(
|
||||
struct XRayTraceCapture* capture);
|
||||
XRAY_NO_INSTRUMENT struct XRayTimestampPair XRayFrameGetStartTimestampPair(
|
||||
struct XRayTraceCapture* capture, int frame);
|
||||
XRAY_NO_INSTRUMENT struct XRayTimestampPair XRayFrameGetEndTimestampPair(
|
||||
struct XRayTraceCapture* capture, int frame);
|
||||
XRAY_NO_INSTRUMENT struct XRayTimestampPair XRayGenerateTimestampsNow(void);
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* defined(XRAY) */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LIBRARIES_XRAY_XRAY_PRIV_H_ */
|
Loading…
Add table
Reference in a new issue