97 lines
2.1 KiB
C
97 lines
2.1 KiB
C
|
#include <time.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <caml/mlvalues.h>
|
||
|
|
||
|
static int trail_initialized = 0;
|
||
|
static FILE *trail_index = NULL;
|
||
|
static FILE *trail_trace = NULL;
|
||
|
static uint32_t trail_next_atom = 0;
|
||
|
|
||
|
typedef struct {
|
||
|
uint32_t atom;
|
||
|
uint32_t sp;
|
||
|
uint64_t time;
|
||
|
} event_t;
|
||
|
|
||
|
#define TRAIL_BUFFER_SIZE 4096
|
||
|
static int trail_buffer_index = 0;
|
||
|
static event_t trail_buffer[TRAIL_BUFFER_SIZE];
|
||
|
|
||
|
static uint64_t trail_gettime(void)
|
||
|
{
|
||
|
struct timespec tp;
|
||
|
//clock_gettime(CLOCK_MONOTONIC_COARSE, &tp);
|
||
|
clock_gettime(CLOCK_MONOTONIC, &tp);
|
||
|
return tp.tv_sec * 1000000000 + tp.tv_nsec;
|
||
|
}
|
||
|
|
||
|
static void trail_flush(void)
|
||
|
{
|
||
|
fwrite(trail_buffer, sizeof(event_t), trail_buffer_index, trail_trace);
|
||
|
trail_buffer_index = 0;
|
||
|
}
|
||
|
|
||
|
static void trail_atexit(void)
|
||
|
{
|
||
|
trail_flush();
|
||
|
fclose(trail_index);
|
||
|
fclose(trail_trace);
|
||
|
}
|
||
|
|
||
|
static void trail_initialize(void)
|
||
|
{
|
||
|
char *trace_file = getenv("CAMTRAIL_FILE");
|
||
|
if (trace_file)
|
||
|
{
|
||
|
char index_file[1024];
|
||
|
strncpy(index_file, trace_file, 1023);
|
||
|
strncat(index_file, ".idx", 1023);
|
||
|
index_file[1023] = '\0';
|
||
|
trail_index = fopen(index_file, "wb");
|
||
|
trail_trace = fopen(trace_file, "wb");
|
||
|
atexit(&trail_atexit);
|
||
|
}
|
||
|
trail_initialized = 1;
|
||
|
}
|
||
|
|
||
|
static uint32_t trail_alloc_atom(value name)
|
||
|
{
|
||
|
uint32_t *buffer = (uint32_t*)String_val(name);
|
||
|
uint32_t result = 1024 + trail_next_atom;
|
||
|
trail_next_atom += 1;
|
||
|
*(uint32_t*)name = result;
|
||
|
|
||
|
uint32_t length = caml_string_length(name);
|
||
|
fwrite(&length, 4, 1, trail_index);
|
||
|
fwrite(buffer, length, 1, trail_index);
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
static event_t *trail_next_event(void)
|
||
|
{
|
||
|
if (trail_buffer_index == TRAIL_BUFFER_SIZE)
|
||
|
{
|
||
|
trail_flush();
|
||
|
trail_buffer_index = 0;
|
||
|
}
|
||
|
return &trail_buffer[trail_buffer_index++];
|
||
|
}
|
||
|
|
||
|
CAMLprim value camtrail_enter(value name)
|
||
|
{
|
||
|
if (!trail_initialized) trail_initialize();
|
||
|
if (!trail_trace) return Val_unit;
|
||
|
|
||
|
uint32_t atom = *(uint32_t*)String_val(name);
|
||
|
if (!atom) atom = trail_alloc_atom(name);
|
||
|
event_t *event = trail_next_event();
|
||
|
event->atom = atom;
|
||
|
event->sp = (uintptr_t)(void*)&name;
|
||
|
event->time = trail_gettime();
|
||
|
|
||
|
return Val_unit;
|
||
|
}
|