blob: fcbf3a38134b3fc0454b2861562803c1da2cd5b6 [file] [log] [blame]
#include "tlbmc/sensors/hwmon_input_device.h"
#include <array>
#include <cstddef>
#include <exception>
#include <fstream>
#include <ios>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include "absl/functional/any_invocable.h"
#include "absl/log/log.h"
#include "boost/asio.hpp" // NOLINT: boost::asio is commonly used in BMC
#include "boost/asio/error.hpp" // NOLINT
#include "boost/asio/random_access_file.hpp" // NOLINT: boost::asio is commonly used in BMC
#include "boost/filesystem.hpp" // NOLINT: boost::filesystem is commonly used in BMC
#include "boost/filesystem/operations.hpp" // NOLINT
#include "boost/system/detail/error_code.hpp" // NOLINT: boost::asio is commonly used in BMC
namespace milotic_tlbmc {
HwmonInputDevice::HwmonInputDevice(
const std::shared_ptr<boost::asio::io_context>& io_context,
std::string_view input_dev_path)
: io_context_(io_context), input_dev_path_(input_dev_path) {
// Prod kernel doesn't support io_uring yet. To make continuous build and test
// happy, we disable io_uring and use synchronous file read.
// On BMC kernel, io_uring will be supported by default.
// On cloudtop or workstation, add `--test_strategy=local` to your blaze
// command to enable io_uring.
try {
// Explicitly specify the O_NONBLOCK flag to avoid blocking the input file
// reading, needed for some kernel versions. (b/421908876)
io_uring_input_device_ = std::make_shared<boost::asio::random_access_file>(
*io_context_, input_dev_path_,
boost::asio::random_access_file::read_only |
static_cast<boost::asio::random_access_file::flags>(O_NONBLOCK));
} catch (const std::exception& e) {
io_uring_input_device_ = nullptr;
LOG(WARNING) << "Failed to create io_uring based random_access_file for "
<< input_dev_path_ << ": " << e.what()
<< " . Fall back to ifstream.";
ifstream_input_device_ = std::ifstream(input_dev_path_);
}
}
HwmonInputDevice::~HwmonInputDevice() {
ifstream_input_device_.close();
if (io_uring_input_device_) {
boost::asio::post(*io_context_,
[io_uring_input_device = io_uring_input_device_] {
io_uring_input_device->close();
});
}
}
void HwmonInputDevice::ReadAndProcess(
absl::AnyInvocable<void(const boost::system::error_code&, size_t)> callback,
std::array<char, 128>& read_buffer) {
if (io_uring_input_device_ != nullptr) {
io_uring_input_device_->async_read_some_at(
0, boost::asio::buffer(read_buffer),
[callback = std::move(callback)](const boost::system::error_code& error,
size_t bytes_read) mutable {
callback(error, bytes_read);
});
return;
}
ifstream_input_device_.read(read_buffer.data(),
static_cast<std::streamsize>(read_buffer.size()));
callback(boost::system::error_code(), read_buffer.size());
}
} // namespace milotic_tlbmc