mirror of
https://github.com/hermitcore/libhermit.git
synced 2025-03-09 00:00:03 +01:00
163 lines
4.8 KiB
C
163 lines
4.8 KiB
C
![]() |
/* 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 */
|