• 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