op_header.cpp
Go to the documentation of this file.00001
00013 #include <cstring>
00014 #include <iostream>
00015 #include <cstdlib>
00016 #include <iomanip>
00017 #include <set>
00018 #include <sstream>
00019 #include <cstring>
00020
00021 #include <sys/types.h>
00022 #include <sys/stat.h>
00023 #include <fcntl.h>
00024 #include <unistd.h>
00025
00026 #include "op_config.h"
00027 #include "op_exception.h"
00028 #include "odb.h"
00029 #include "op_cpu_type.h"
00030 #include "op_file.h"
00031 #include "op_header.h"
00032 #include "op_events.h"
00033 #include "string_manip.h"
00034 #include "format_output.h"
00035 #include "xml_utils.h"
00036 #include "cverb.h"
00037
00038 using namespace std;
00039
00040 extern verbose vbfd;
00041
00042 void op_check_header(opd_header const & h1, opd_header const & h2,
00043 string const & filename)
00044 {
00045 if (h1.mtime != h2.mtime) {
00046 ostringstream os;
00047 os << "header timestamps are different ("
00048 << h1.mtime << ", " << h2.mtime << ") for "
00049 << filename << "\n";
00050 throw op_fatal_error(os.str());
00051 }
00052
00053 if (h1.is_kernel != h2.is_kernel) {
00054 ostringstream os;
00055 os << "header is_kernel flags are different for "
00056 << filename << "\n";
00057 throw op_fatal_error(os.str());
00058 }
00059
00060
00061
00062
00063
00064
00065 }
00066
00067
00068 namespace {
00069
00070 set<string> warned_files;
00071
00072 }
00073
00074 bool is_jit_sample(string const & filename)
00075 {
00076
00077 string suf = ".jo";
00078
00079 string::size_type pos;
00080 pos = filename.rfind(suf);
00081
00082 if (pos != string::npos && pos == filename.size() - suf.size())
00083 return true;
00084 else
00085 return false;
00086 }
00087
00088 void check_mtime(string const & file, opd_header const & header)
00089 {
00090 u64 newmtime = op_get_mtime(file.c_str());
00091
00092 if (newmtime == header.mtime)
00093 return;
00094
00095 if (warned_files.find(file) != warned_files.end())
00096 return;
00097
00098 warned_files.insert(file);
00099
00100
00101 if (!header.mtime) {
00102
00103
00104
00105 if (is_jit_sample(file)) {
00106 cverb << vbfd << "warning: could not check that the binary file "
00107 << file << " has not been modified since "
00108 "the profile was taken. Results may be inaccurate.\n";
00109 } else {
00110 cerr << "warning: could not check that the binary file "
00111 << file << " has not been modified since "
00112 "the profile was taken. Results may be inaccurate.\n";
00113 }
00114 } else {
00115 static bool warned_already = false;
00116
00117 cerr << "warning: the last modified time of the binary file "
00118 "does not match that of the sample file for " << file
00119 << "\n";
00120
00121 if (!warned_already) {
00122 cerr << "Either this is the wrong binary or the binary "
00123 "has been modified since the sample file was created.\n";
00124 warned_already = true;
00125 }
00126 }
00127 }
00128
00129
00130 opd_header const read_header(string const & sample_filename)
00131 {
00132 int fd = open(sample_filename.c_str(), O_RDONLY);
00133 if (fd < 0)
00134 throw op_fatal_error("Can't open sample file:" +
00135 sample_filename);
00136
00137 opd_header header;
00138 if (read(fd, &header, sizeof(header)) != sizeof(header)) {
00139 close(fd);
00140 throw op_fatal_error("Can't read sample file header:" +
00141 sample_filename);
00142 }
00143
00144 if (memcmp(header.magic, OPD_MAGIC, sizeof(header.magic))) {
00145 close(fd);
00146 throw op_fatal_error("Invalid sample file, "
00147 "bad magic number: " +
00148 sample_filename);
00149 }
00150
00151 close(fd);
00152
00153 return header;
00154 }
00155
00156
00157 namespace {
00158
00159 string const op_print_event(op_cpu cpu_type, u32 type, u32 um, u32 count)
00160 {
00161 string str;
00162
00163 if (cpu_type == CPU_TIMER_INT) {
00164 str += "Profiling through timer interrupt";
00165 return str;
00166 }
00167
00168 struct op_event * event = op_find_event(cpu_type, type, um);
00169
00170 if (!event) {
00171 event = op_find_event_any(cpu_type, type);
00172 if (!event) {
00173 cerr << "Could not locate event " << int(type) << endl;
00174 str = "Unknown event";
00175 return str;
00176 }
00177 }
00178
00179 char const * um_desc = 0;
00180
00181 for (size_t i = 0; i < event->unit->num; ++i) {
00182 if (event->unit->um[i].value == um)
00183 um_desc = event->unit->um[i].desc;
00184 }
00185
00186 str += string("Counted ") + event->name;
00187 str += string(" events (") + event->desc + ")";
00188
00189 if (cpu_type != CPU_RTC) {
00190 str += " with a unit mask of 0x";
00191
00192 ostringstream ss;
00193 ss << hex << setw(2) << setfill('0') << unsigned(um);
00194 str += ss.str();
00195
00196 str += " (";
00197 str += um_desc ? um_desc : "multiple flags";
00198 str += ")";
00199 }
00200
00201 str += " count " + op_lexical_cast<string>(count);
00202 return str;
00203 }
00204
00205 string const op_xml_print_event(op_cpu cpu_type, u32 type, u32 um, u32 count)
00206 {
00207 string unit_mask;
00208
00209 if (cpu_type == CPU_TIMER_INT || cpu_type == CPU_RTC)
00210 return xml_utils::get_timer_setup((size_t)count);
00211
00212 struct op_event * event = op_find_event(cpu_type, type, um);
00213 if (!event) {
00214 event = op_find_event_any(cpu_type, type);
00215 if (!event) {
00216 cerr << "Could not locate event " << int(type) << endl;
00217 return "";
00218 }
00219 }
00220
00221 if (cpu_type != CPU_RTC) {
00222 ostringstream str_out;
00223 str_out << um;
00224 unit_mask = str_out.str();
00225 }
00226
00227 return xml_utils::get_event_setup(string(event->name),
00228 (size_t)count, unit_mask);
00229 }
00230
00231 }
00232
00233 string const describe_header(opd_header const & header)
00234 {
00235 op_cpu cpu = static_cast<op_cpu>(header.cpu_type);
00236
00237 if (want_xml)
00238 return op_xml_print_event(cpu, header.ctr_event,
00239 header.ctr_um, header.ctr_count);
00240 else
00241 return op_print_event(cpu, header.ctr_event,
00242 header.ctr_um, header.ctr_count);
00243 }
00244
00245
00246 string const describe_cpu(opd_header const & header)
00247 {
00248 op_cpu cpu = static_cast<op_cpu>(header.cpu_type);
00249
00250 string str;
00251 if (want_xml) {
00252 string cpu_name = op_get_cpu_name(cpu);
00253
00254 str = xml_utils::get_profile_header(cpu_name, header.cpu_speed);
00255 } else {
00256 str += string("CPU: ") + op_get_cpu_type_str(cpu);
00257 if (header.cpu_speed > 0) {
00258 ostringstream ss;
00259
00260 str += ", speed ";
00261 ss << header.cpu_speed;
00262 str += ss.str() + " MHz (estimated)";
00263 }
00264 }
00265 return str;
00266 }