Commit 66663604 authored by Michael Ott's avatar Michael Ott
Browse files

Revert "Check for errors when opening file descriptors for additional sensors...

Revert "Check for errors when opening file descriptors for additional sensors in a group and obtaining IDs" as it also has some unintended changes from the supermucng branch

This reverts commit 37e9f37a.
parent 37e9f37a
......@@ -2,11 +2,12 @@
* PerfSensorGroup.cpp
*
* Created on: 04.08.2018
* Author: Micha Mueller, Carla Guillen
* Author: Micha Mueller
*/
#include "PerfSensorGroup.h"
#include "timestamp.h"
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/perf_event.h>
......@@ -18,8 +19,6 @@
//the read group data will have this format
struct read_format {
uint64_t nr;
uint64_t time_enabled; /* if PERF_FORMAT_TOTAL_TIME_ENABLED */
uint64_t time_running; /* if PERF_FORMAT_TOTAL_TIME_RUNNING */
struct {
uint64_t value;
uint64_t id;
......@@ -28,14 +27,9 @@ struct read_format {
PerfSensorGroup::PerfSensorGroup(const std::string& name) :
SensorGroupTemplate(name),
_sensorGroupLeader(false),
_cpuId(0),
_group_fd(-1),
_bufSize(0),
_latest_time_enabled (0),
_latest_time_running(0),
_lastValid(true),
_maxCorrection(20){
_fd(-1),
_bufSize(0) {
_buf = nullptr;
}
......@@ -48,21 +42,7 @@ PerfSensorGroup::~PerfSensorGroup() {
void PerfSensorGroup::init(boost::asio::io_service& io) {
SensorGroupTemplate::init(io);
/* Allocate buffer to read in later. Reading struct has the following format:
*
* struct read_format {
* u64 nr; // The number of events
* u64 time_enabled; // if PERF_FORMAT_TOTAL_TIME_ENABLED
* u64 time_running; // if PERF_FORMAT_TOTAL_TIME_RUNNING
* struct {
* u64 value; // The value of the event
* u64 id; // if PERF_FORMAT_ID
* } values[nr];
* };
*
* Therefore we require 16 byte per sensor plus an additional 8*3 byte
*/
std::size_t bufSize = _sensors.size() * 16 + 24;
std::size_t bufSize = _sensors.size() * 16 + 8;
if (!_buf) {
_buf = new char[bufSize];
_bufSize = bufSize;
......@@ -71,11 +51,6 @@ void PerfSensorGroup::init(boost::asio::io_service& io) {
_buf = new char[bufSize];
_bufSize = bufSize;
}
if(!_sensorGroupLeader) {
//only the sensorGroupLeader needs a timer
_timer = nullptr;
}
}
void PerfSensorGroup::start() {
......@@ -89,7 +64,7 @@ void PerfSensorGroup::start() {
//open perf-counters
struct perf_event_attr pe;
PerfSBPtr pc = _sensors[0];
PerfSensorBase* pc = _sensors[0];
memset(&pe, 0, sizeof(struct perf_event_attr));
pe.size = sizeof(struct perf_event_attr);
......@@ -97,19 +72,19 @@ void PerfSensorGroup::start() {
pe.config = pc->getConfig();
pe.disabled = 1;
pe.exclude_kernel = 0;
pe.exclude_hv = 0;
pe.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID | PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING;
pe.exclude_hv = 1;
pe.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
//perf_event_open() group leader
_group_fd = syscall(__NR_perf_event_open, &pe, -1, _cpuId, -1, 0);
if (_group_fd == -1) {
LOG(error) << "Failed to open performance-counter group \"" << _groupName << "\":" << strerror(errno);
return;
}
ioctl(_group_fd, PERF_EVENT_IOC_ID, &id);
_fd = syscall(__NR_perf_event_open, &pe, -1, _cpuId, -1, 0);
ioctl(_fd, PERF_EVENT_IOC_ID, &id);
//store ids to make them distinguishable when reading
_ids.push_back(id);
if (_fd == -1) {
LOG(error) << "Failed to open performance-counter group \"" << _groupName << "\"";
return;
}
LOG(debug) << " " << _groupName << "::" << pc->getName() << " opened with ID " << std::to_string(id);
pe.disabled = 0;
......@@ -120,127 +95,77 @@ void PerfSensorGroup::start() {
pe.type = pc->getType();
pe.config = pc->getConfig();
fd = syscall(__NR_perf_event_open, &pe, -1, _cpuId, _group_fd, 0);
fd = syscall(__NR_perf_event_open, &pe, -1, _cpuId, _fd, 0);
//store id, so that we can match counters with values later (see read())
if (fd != -1) {
int rc;
if ((rc = ioctl(fd, PERF_EVENT_IOC_ID, &id)) == 0) {
_ids.push_back(id);
_fds.push_back(fd);
LOG(debug) << " " << _groupName << "::" << pc->getName() << " opened with ID " << std::to_string(id);
} else {
LOG(debug) << " " << _groupName << "::" << pc->getName() << " errro obtaining ID: " << strerror(rc);
}
} else {
LOG(debug) << " " << _groupName << "::" << pc->getName() << " errro opening perf file descriptor: " << strerror(errno);
}
ioctl(fd, PERF_EVENT_IOC_ID, &id);
_ids.push_back(id);
LOG(debug) << " " << _groupName << "::" << pc->getName() << " opened with ID " << std::to_string(id);
}
ioctl(_group_fd, PERF_EVENT_IOC_RESET, 0);
ioctl(_group_fd, PERF_EVENT_IOC_ENABLE, 0);
ioctl(_fd, PERF_EVENT_IOC_RESET, 0);
ioctl(_fd, PERF_EVENT_IOC_ENABLE, 0);
_keepRunning = 1;
if (_sensorGroupLeader) {
_pendingTasks++;
_timer->async_wait(std::bind(&PerfSensorGroup::readAsync, this));
}
_pendingTasks++;
_timer->async_wait(std::bind(&PerfSensorGroup::readAsync, this));
LOG(info) << "Sensorgroup " << _groupName << " started.";
}
void PerfSensorGroup::stop() {
_keepRunning = 0;
if(_group_fd != -1) {
for(auto& fd : _fds) {
close(fd);
}
_ids.clear();
_fds.clear();
close(_group_fd);
_group_fd = -1;
if(_fd != -1) {
close(_fd);
_fd = -1;
}
LOG(info) << "Sensorgroup " << _groupName << " stopped.";
}
void PerfSensorGroup::read() {
uint64_t timestamp = getTimestamp();
reading_t reading;
reading.timestamp = getTimestamp();
struct read_format* rf = (struct read_format*) _buf;
unsigned long long count;
if (::read(_group_fd, _buf, _bufSize) < 0) {
if (::read(_fd, _buf, _bufSize) < 0) {
LOG(error) << "Sensorgroup" << _groupName << " could not read value";
return;
}
double correction = 1;
bool validMeasurement=true;
uint64_t time_enabled=calculateIntervalValue(_latest_time_enabled, rf->time_enabled, ULLONG_MAX );
uint64_t time_running=calculateIntervalValue(_latest_time_running, rf->time_running, ULLONG_MAX );
//store latest times
_latest_time_enabled = rf->time_enabled;
_latest_time_running = rf->time_running;
if(time_running){
correction = static_cast<double>(time_enabled)/time_running;
} else {
LOG(info) << "PerfSensorGroup: Group: " << _groupName << " could not be measured. Time running==0";
validMeasurement = false;
}
if(correction > _maxCorrection || correction < 1 ){
LOG(info) << "PerfCounterGroup: Group: " << _groupName << " could not be measured. Correction factor ==" << correction;
validMeasurement = false;
}
if(!validMeasurement){
_lastValid=false;
return;
}
//iterate over all values returned by ::read()
for (unsigned i = 0; i < rf->nr; i++) {
uint64_t val = rf->values[i].value;
//iterate over all counters and find the one with matching id
for (unsigned j = 0; j < _sensors.size(); j++) {
if (rf->values[i].id == _ids[j]) {
#ifdef DEBUG
LOG(debug) << _groupName << "::" << _sensors[j]->getName() << ": \"" << val << "\"";
#endif
if(_lastValid){
//storeReading takes care of delta computation and applies correction value on the result
_sensors[j]->storeReading(val, timestamp, correction, PerfSensorBase::MAXCOUNTERVALUE);
reading_t lV = _sensors[j]->getLatestValue();
if (val >= lV.value) {
reading.value = val - lV.value;
} else {
//Before we can compute correct values again after an invalid reading we have to update the lastRawValue first
_sensors[j]->setLastRaw(val);
//the counter overflow since last read
//according to perf_event_open() man-page u64 (=64bit) is used for event values
//--> unsigned long long is usually also 64bit
reading.value = val + (ULLONG_MAX - lV.value);
}
#ifdef DEBUG
LOG(debug) << _groupName << "::" << _sensors[j]->getName() << ": \"" << reading.value << "\"";
#endif
_sensors[j]->storeReading(reading, _cacheIndex);
break;
}
}
}
if(validMeasurement){ //set valid for the next time to read
_lastValid = true;
}
_cacheIndex = (_cacheIndex + 1) % _cacheSize;
}
void PerfSensorGroup::readAsync() {
uint64_t now = getTimestamp();
read();
if(_sensorGroupLeader) {
for(const auto& g : _fellowSensorGroups) {
g->read();
}
}
if (_timer && _keepRunning) {
_timer->expires_at(timestamp2ptime(nextReadingTime()));
uint64_t next = now + MS_TO_NS(_interval);
_timer->expires_at(timestamp2ptime(next));
_pendingTasks++;
_timer->async_wait(std::bind(&PerfSensorGroup::readAsync, this));
}
_pendingTasks--;
}
uint64_t PerfSensorGroup::calculateIntervalValue(uint64_t previous, uint64_t current, uint64_t maxValue){
if(previous > current) { //overflow
return current + (maxValue - previous);
}
return current - previous;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment