From a75db1286dd34cc10ebf32f6694307f30ca28496 Mon Sep 17 00:00:00 2001 From: Daniel Agar Date: Mon, 26 Aug 2024 13:24:39 -0400 Subject: [PATCH] logger: automatically limit buffer size to largest available free chunk (NuttX only) --- src/modules/logger/log_writer_file.cpp | 40 +++++++++++++++++++++----- src/modules/logger/log_writer_file.h | 6 ++-- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/modules/logger/log_writer_file.cpp b/src/modules/logger/log_writer_file.cpp index 50d5cf7f45..2001baf2f6 100644 --- a/src/modules/logger/log_writer_file.cpp +++ b/src/modules/logger/log_writer_file.cpp @@ -42,9 +42,11 @@ #include #include #include -#ifdef __PX4_NUTTX -#include -#endif /* __PX4_NUTTX */ + +#if defined(__PX4_NUTTX) +# include +# include +#endif // __PX4_NUTTX using namespace time_literals; @@ -60,11 +62,13 @@ LogWriterFile::LogWriterFile(size_t buffer_size) //We always write larger chunks (orb messages) to the buffer, so the buffer //needs to be larger than the minimum write chunk (300 is somewhat arbitrary) { - math::max(buffer_size, _min_write_chunk + 300), + buffer_size, + _min_write_chunk + 300, perf_alloc(PC_ELAPSED, "logger_sd_write"), perf_alloc(PC_ELAPSED, "logger_sd_fsync")}, { 300, // buffer size for the mission log (can be kept fairly small) + 1, perf_alloc(PC_ELAPSED, "logger_sd_write_mission"), perf_alloc(PC_ELAPSED, "logger_sd_fsync_mission")} } { @@ -590,9 +594,12 @@ const char *log_type_str(LogType type) return "unknown"; } -LogWriterFile::LogFileBuffer::LogFileBuffer(size_t log_buffer_size, perf_counter_t perf_write, - perf_counter_t perf_fsync) - : _buffer_size(log_buffer_size), _perf_write(perf_write), _perf_fsync(perf_fsync) +LogWriterFile::LogFileBuffer::LogFileBuffer(size_t log_buffer_desired_size, size_t log_buffer_min_size, + perf_counter_t perf_write, perf_counter_t perf_fsync) : + _buffer_size(log_buffer_desired_size), + _buffer_size_min(log_buffer_min_size), + _perf_write(perf_write), + _perf_fsync(perf_fsync) { } @@ -660,6 +667,25 @@ bool LogWriterFile::LogFileBuffer::start_log(const char *filename) } if (_buffer == nullptr) { + _buffer_size = math::max(_buffer_size, _buffer_size_min); + +#if defined(__PX4_NUTTX) + struct mallinfo alloc_info = mallinfo(); + + // reduced to largest available free chunk, but leave at least 1 kB available + static constexpr ssize_t one_kb = 1024; + const ssize_t reduced_buffer_size = math::max((alloc_info.mxordblk - one_kb) / one_kb * one_kb, + (ssize_t)_buffer_size_min); + + if ((reduced_buffer_size > 0) && ((ssize_t)_buffer_size > reduced_buffer_size)) { + PX4_WARN("requested buffer size %dB limited to available %dB (available plus 1 kB margin)", + _buffer_size, reduced_buffer_size); + + _buffer_size = reduced_buffer_size; + } + +#endif // __PX4_NUTTX + _buffer = (uint8_t *) px4_cache_aligned_alloc(_buffer_size); if (_buffer == nullptr) { diff --git a/src/modules/logger/log_writer_file.h b/src/modules/logger/log_writer_file.h index 757f69de25..7654878938 100644 --- a/src/modules/logger/log_writer_file.h +++ b/src/modules/logger/log_writer_file.h @@ -169,7 +169,8 @@ private: class LogFileBuffer { public: - LogFileBuffer(size_t log_buffer_size, perf_counter_t perf_write, perf_counter_t perf_fsync); + LogFileBuffer(size_t log_buffer_desired_size, size_t log_buffer_min_size, + perf_counter_t perf_write, perf_counter_t perf_fsync); ~LogFileBuffer(); @@ -203,7 +204,8 @@ private: bool _should_run = false; px4::atomic_bool _had_write_error{false}; private: - const size_t _buffer_size; + size_t _buffer_size; + const size_t _buffer_size_min; int _fd = -1; uint8_t *_buffer = nullptr; size_t _head = 0; ///< next position to write to