| #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 |