• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  #include <stdio.h>
2  #include <stdlib.h>
3  #include <inttypes.h>
4  #include "gtrace.h"
5  
6  // A buffer of zeros
7  static char zeros[Gtrace::kGtraceEntriesPerBlock * sizeof(Gtrace::trace_entry)];
8  
Gtrace()9  Gtrace::Gtrace() {
10    gtrace_file_ = NULL;
11    ftrace_ = NULL;
12    fnames_ = NULL;
13    start_sec_ = 0;
14    pdate_ = 0;
15    ptime_ = 0;
16    num_entries_ = 0;
17    blockno_ = 1;
18    current_pid_ = 0;
19  }
20  
~Gtrace()21  Gtrace::~Gtrace() {
22    if (ftrace_) {
23      // Extend the trace file to a multiple of 8k. Otherwise gtracepost64
24      // complains.
25      long pos = ftell(ftrace_);
26      long pos_end = (pos + 0x1fff) & ~0x1fff;
27      if (pos_end > pos) {
28        char ch = 0;
29        fseek(ftrace_, pos_end - 1, SEEK_SET);
30        fwrite(&ch, 1, 1, ftrace_);
31      }
32      fclose(ftrace_);
33    }
34    if (fnames_)
35      fclose(fnames_);
36  }
37  
Open(const char * gtrace_file,uint32_t pdate,uint32_t ptime)38  void Gtrace::Open(const char *gtrace_file, uint32_t pdate, uint32_t ptime)
39  {
40    ftrace_ = fopen(gtrace_file, "w");
41    if (ftrace_ == NULL) {
42      perror(gtrace_file);
43      exit(1);
44    }
45    gtrace_file_ = gtrace_file;
46  
47    pdate_ = pdate;
48    ptime_ = ptime;
49    sprintf(gname_file_, "gname_%x_%06x.txt", pdate, ptime);
50    fnames_ = fopen(gname_file_, "w");
51    if (fnames_ == NULL) {
52      perror(gname_file_);
53      exit(1);
54    }
55    fprintf(fnames_, "# File# Proc# Line# Name\n");
56  }
57  
WriteFirstHeader(uint32_t start_sec,uint32_t pid)58  void Gtrace::WriteFirstHeader(uint32_t start_sec, uint32_t pid)
59  {
60    first_header fh;
61    current_pid_ = pid;
62    start_sec_ = start_sec;
63    FillFirstHeader(start_sec, pid, &fh);
64    fwrite(&fh, sizeof(fh), 1, ftrace_);
65    num_entries_ = 8;
66  }
67  
FillFirstHeader(uint32_t start_sec,uint32_t pid,first_header * fh)68  void Gtrace::FillFirstHeader(uint32_t start_sec, uint32_t pid,
69                               first_header *fh) {
70    int cpu = 0;
71    int max_files = 16;
72    int max_procedures = 12;
73  
74    fh->common.blockno = 0;
75    fh->common.entry_width = 8;
76    fh->common.block_tic = kBaseTic;
77    fh->common.block_time = start_sec;
78    //fh->common.usec_cpu = (start_usec << 8) | (cpu & 0xff);
79    fh->common.usec_cpu = cpu & 0xff;
80    fh->common.pid = pid;
81    fh->common.bug_count = 0;
82    fh->common.zero_count = 0;
83  
84    fh->tic = kBaseTic + 1;
85    fh->one = 1;
86    fh->tics_per_second = kTicsPerSecond;
87    fh->trace_time = start_sec;
88    fh->version = 5;
89    fh->file_proc = (max_files << 8) | max_procedures;
90    fh->pdate = pdate_;
91    fh->ptime = ptime_;
92  }
93  
WriteBlockHeader(uint32_t cycle,uint32_t pid)94  void Gtrace::WriteBlockHeader(uint32_t cycle, uint32_t pid)
95  {
96    int cpu = 0;
97    block_header bh;
98  
99    bh.blockno = blockno_++;
100    bh.entry_width = 8;
101    bh.block_tic = cycle + kBaseTic;
102    bh.block_time = start_sec_ + cycle / kTicsPerSecond;
103    //bh.usec_cpu = (start_usec << 8) | (cpu & 0xff);
104    bh.usec_cpu = cpu & 0xff;
105    bh.pid = pid;
106    bh.bug_count = 0;
107    bh.zero_count = 0;
108    fwrite(&bh, sizeof(bh), 1, ftrace_);
109  }
110  
AddGtraceRecord(int filenum,int procnum,uint32_t cycle,uint32_t pid,int is_exit)111  void Gtrace::AddGtraceRecord(int filenum, int procnum, uint32_t cycle, uint32_t pid,
112                               int is_exit)
113  {
114    trace_entry	entry;
115  
116    if (current_pid_ != pid) {
117      current_pid_ = pid;
118  
119      // We are switching to a new process id, so pad the current block
120      // with zeros.
121      int num_zeros = (kGtraceEntriesPerBlock - num_entries_) * sizeof(entry);
122      fwrite(zeros, num_zeros, 1, ftrace_);
123      WriteBlockHeader(cycle, pid);
124      num_entries_ = 4;
125    }
126  
127    // If the current block is full, write out a new block header
128    if (num_entries_ == kGtraceEntriesPerBlock) {
129      WriteBlockHeader(cycle, pid);
130      num_entries_ = 4;
131    }
132  
133    entry.cycle = cycle + kBaseTic;
134    entry.event = (filenum << 13) | (procnum << 1) | is_exit;
135    fwrite(&entry, sizeof(entry), 1, ftrace_);
136    num_entries_ += 1;
137  }
138  
AddProcEntry(int filenum,int procnum,uint32_t cycle,uint32_t pid)139  void Gtrace::AddProcEntry(int filenum, int procnum, uint32_t cycle, uint32_t pid)
140  {
141    AddGtraceRecord(filenum, procnum, cycle, pid, 0);
142  }
143  
AddProcExit(int filenum,int procnum,uint32_t cycle,uint32_t pid)144  void Gtrace::AddProcExit(int filenum, int procnum, uint32_t cycle, uint32_t pid)
145  {
146    AddGtraceRecord(filenum, procnum, cycle, pid, 1);
147  }
148  
AddProcedure(int filenum,int procnum,const char * proc_name)149  void Gtrace::AddProcedure(int filenum, int procnum, const char *proc_name)
150  {
151    fprintf(fnames_, "%d %d %d %s\n", filenum, procnum, procnum, proc_name);
152  }
153