diff options
-rw-r--r-- | host/lib/include/uhdlib/transport/rx_streamer_impl.hpp | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/host/lib/include/uhdlib/transport/rx_streamer_impl.hpp b/host/lib/include/uhdlib/transport/rx_streamer_impl.hpp index 00ce558b8..79c196f3f 100644 --- a/host/lib/include/uhdlib/transport/rx_streamer_impl.hpp +++ b/host/lib/include/uhdlib/transport/rx_streamer_impl.hpp @@ -257,6 +257,38 @@ private: const int32_t timeout_ms, const size_t buffer_offset_bytes = 0) { + // A request to read zero samples should effectively be a no-op. + // However, in 2af10ee9, a change was made to increase the probability + // but not guarantee that calling recv() after a radio overflow event + // would return the overflow condition to the user. That change + // introduced a side effect that a read of zero samples (assuming there + // were no samples available) would block for the entirety of the + // timeout period and then return ERROR_CODE_TIMEOUT in the RX metadata + // for the read. (Prior to this change, there was an explicit check for + // a read of zero samples, which would return to the caller + // immediately.) This of course is undesirable--a request to read zero + // samples should always be fulfilled immediately, regardless of the + // availability of samples. Furthermore, reading zero samples is + // conventionally used to surface any stream errors, and it's that + // behavior we would like to preserve. + // + // This change to call get_recv_buffs() with a zero timeout when + // nsamps_per_buff is zero is an attempt to achieve the best of both + // worlds. The call to get_recv_buffs() will surface any stream errors, + // but using a timeout of 0 means that we'll return as quickly as + // possible (with a maximum latency of 1ms; see + // rx_streamer_zero_copy.hpp, line 219 or so). If there's any stream + // error, it'll be returned in the metadata. However, if the stream + // error is ERROR_CODE_TIMEOUT, we'll simply swallow the error, thus + // preserving the old behavior. + if (nsamps_per_buff == 0) { + _zero_copy_streamer.get_recv_buffs(_in_buffs, metadata, eov_positions, 0); + if (metadata.error_code == rx_metadata_t::ERROR_CODE_TIMEOUT) { + metadata.error_code = rx_metadata_t::ERROR_CODE_NONE; + } + return 0; + } + if (_buff_samps_remaining == 0) { // Current set of buffers has expired, get the next one _buff_samps_remaining = _zero_copy_streamer.get_recv_buffs( |