153 lines
3.7 KiB
C++
153 lines
3.7 KiB
C++
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <inttypes.h>
|
|
#include "gtrace.h"
|
|
|
|
// A buffer of zeros
|
|
static char zeros[Gtrace::kGtraceEntriesPerBlock * sizeof(Gtrace::trace_entry)];
|
|
|
|
Gtrace::Gtrace() {
|
|
gtrace_file_ = NULL;
|
|
ftrace_ = NULL;
|
|
fnames_ = NULL;
|
|
start_sec_ = 0;
|
|
pdate_ = 0;
|
|
ptime_ = 0;
|
|
num_entries_ = 0;
|
|
blockno_ = 1;
|
|
current_pid_ = 0;
|
|
}
|
|
|
|
Gtrace::~Gtrace() {
|
|
if (ftrace_) {
|
|
// Extend the trace file to a multiple of 8k. Otherwise gtracepost64
|
|
// complains.
|
|
long pos = ftell(ftrace_);
|
|
long pos_end = (pos + 0x1fff) & ~0x1fff;
|
|
if (pos_end > pos) {
|
|
char ch = 0;
|
|
fseek(ftrace_, pos_end - 1, SEEK_SET);
|
|
fwrite(&ch, 1, 1, ftrace_);
|
|
}
|
|
fclose(ftrace_);
|
|
}
|
|
if (fnames_)
|
|
fclose(fnames_);
|
|
}
|
|
|
|
void Gtrace::Open(const char *gtrace_file, uint32_t pdate, uint32_t ptime)
|
|
{
|
|
ftrace_ = fopen(gtrace_file, "w");
|
|
if (ftrace_ == NULL) {
|
|
perror(gtrace_file);
|
|
exit(1);
|
|
}
|
|
gtrace_file_ = gtrace_file;
|
|
|
|
pdate_ = pdate;
|
|
ptime_ = ptime;
|
|
sprintf(gname_file_, "gname_%x_%06x.txt", pdate, ptime);
|
|
fnames_ = fopen(gname_file_, "w");
|
|
if (fnames_ == NULL) {
|
|
perror(gname_file_);
|
|
exit(1);
|
|
}
|
|
fprintf(fnames_, "# File# Proc# Line# Name\n");
|
|
}
|
|
|
|
void Gtrace::WriteFirstHeader(uint32_t start_sec, uint32_t pid)
|
|
{
|
|
first_header fh;
|
|
current_pid_ = pid;
|
|
start_sec_ = start_sec;
|
|
FillFirstHeader(start_sec, pid, &fh);
|
|
fwrite(&fh, sizeof(fh), 1, ftrace_);
|
|
num_entries_ = 8;
|
|
}
|
|
|
|
void Gtrace::FillFirstHeader(uint32_t start_sec, uint32_t pid,
|
|
first_header *fh) {
|
|
int cpu = 0;
|
|
int max_files = 16;
|
|
int max_procedures = 12;
|
|
|
|
fh->common.blockno = 0;
|
|
fh->common.entry_width = 8;
|
|
fh->common.block_tic = kBaseTic;
|
|
fh->common.block_time = start_sec;
|
|
//fh->common.usec_cpu = (start_usec << 8) | (cpu & 0xff);
|
|
fh->common.usec_cpu = cpu & 0xff;
|
|
fh->common.pid = pid;
|
|
fh->common.bug_count = 0;
|
|
fh->common.zero_count = 0;
|
|
|
|
fh->tic = kBaseTic + 1;
|
|
fh->one = 1;
|
|
fh->tics_per_second = kTicsPerSecond;
|
|
fh->trace_time = start_sec;
|
|
fh->version = 5;
|
|
fh->file_proc = (max_files << 8) | max_procedures;
|
|
fh->pdate = pdate_;
|
|
fh->ptime = ptime_;
|
|
}
|
|
|
|
void Gtrace::WriteBlockHeader(uint32_t cycle, uint32_t pid)
|
|
{
|
|
int cpu = 0;
|
|
block_header bh;
|
|
|
|
bh.blockno = blockno_++;
|
|
bh.entry_width = 8;
|
|
bh.block_tic = cycle + kBaseTic;
|
|
bh.block_time = start_sec_ + cycle / kTicsPerSecond;
|
|
//bh.usec_cpu = (start_usec << 8) | (cpu & 0xff);
|
|
bh.usec_cpu = cpu & 0xff;
|
|
bh.pid = pid;
|
|
bh.bug_count = 0;
|
|
bh.zero_count = 0;
|
|
fwrite(&bh, sizeof(bh), 1, ftrace_);
|
|
}
|
|
|
|
void Gtrace::AddGtraceRecord(int filenum, int procnum, uint32_t cycle, uint32_t pid,
|
|
int is_exit)
|
|
{
|
|
trace_entry entry;
|
|
|
|
if (current_pid_ != pid) {
|
|
current_pid_ = pid;
|
|
|
|
// We are switching to a new process id, so pad the current block
|
|
// with zeros.
|
|
int num_zeros = (kGtraceEntriesPerBlock - num_entries_) * sizeof(entry);
|
|
fwrite(zeros, num_zeros, 1, ftrace_);
|
|
WriteBlockHeader(cycle, pid);
|
|
num_entries_ = 4;
|
|
}
|
|
|
|
// If the current block is full, write out a new block header
|
|
if (num_entries_ == kGtraceEntriesPerBlock) {
|
|
WriteBlockHeader(cycle, pid);
|
|
num_entries_ = 4;
|
|
}
|
|
|
|
entry.cycle = cycle + kBaseTic;
|
|
entry.event = (filenum << 13) | (procnum << 1) | is_exit;
|
|
fwrite(&entry, sizeof(entry), 1, ftrace_);
|
|
num_entries_ += 1;
|
|
}
|
|
|
|
void Gtrace::AddProcEntry(int filenum, int procnum, uint32_t cycle, uint32_t pid)
|
|
{
|
|
AddGtraceRecord(filenum, procnum, cycle, pid, 0);
|
|
}
|
|
|
|
void Gtrace::AddProcExit(int filenum, int procnum, uint32_t cycle, uint32_t pid)
|
|
{
|
|
AddGtraceRecord(filenum, procnum, cycle, pid, 1);
|
|
}
|
|
|
|
void Gtrace::AddProcedure(int filenum, int procnum, const char *proc_name)
|
|
{
|
|
fprintf(fnames_, "%d %d %d %s\n", filenum, procnum, procnum, proc_name);
|
|
}
|