From 81bd7896940dcd39181d0aee331e08abe4df1655 Mon Sep 17 00:00:00 2001 From: Brent Stapleton Date: Fri, 30 Aug 2019 14:46:33 -0700 Subject: rfnoc: ctrlport: Fixing timeouts for timed commands When issuing a timed command, if there is no room in the command FIFO and there is a timed command queue'd up, wait for a long time before timing out. --- host/lib/include/uhdlib/rfnoc/chdr_types.hpp | 6 ++++++ host/lib/rfnoc/ctrlport_endpoint.cpp | 30 +++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-) (limited to 'host') diff --git a/host/lib/include/uhdlib/rfnoc/chdr_types.hpp b/host/lib/include/uhdlib/rfnoc/chdr_types.hpp index b5725710b..8bb345b32 100644 --- a/host/lib/include/uhdlib/rfnoc/chdr_types.hpp +++ b/host/lib/include/uhdlib/rfnoc/chdr_types.hpp @@ -313,6 +313,12 @@ public: // Functions deserialize(buff, num_elems, conv_byte_order); } + // Return whether or not we have a valid timestamp + bool has_timestamp() const + { + return bool(timestamp); + } + //! Comparison operator (==) bool operator==(const ctrl_payload& rhs) const; diff --git a/host/lib/rfnoc/ctrlport_endpoint.cpp b/host/lib/rfnoc/ctrlport_endpoint.cpp index 3374a707b..43bbf815c 100644 --- a/host/lib/rfnoc/ctrlport_endpoint.cpp +++ b/host/lib/rfnoc/ctrlport_endpoint.cpp @@ -11,7 +11,9 @@ #include #include #include +#include #include +#include #include @@ -27,6 +29,8 @@ namespace { constexpr size_t ASYNC_MESSAGE_SIZE = 6; //! Default completion timeout for transactions constexpr double DEFAULT_TIMEOUT = 0.1; +//! Long timeout for when we wait on a timed command +constexpr double MASSIVE_TIMEOUT = 10.0; //! Default value for whether ACKs are always required constexpr bool DEFAULT_FORCE_ACKS = false; } // namespace @@ -229,7 +233,7 @@ public: resp_status = RESP_SIZEERR; } // Pop the request from the queue - _req_queue.pop(); + _req_queue.pop_front(); // Push the response into the response queue _resp_queue.push(std::make_tuple(rx_ctrl, resp_status)); _resp_ready_cond.notify_one(); @@ -246,7 +250,7 @@ public: _resp_queue.push(std::make_tuple(resp, RESP_DROPPED)); _resp_ready_cond.notify_one(); // Pop the request from the queue - _req_queue.pop(); + _req_queue.pop_front(); }; // Peek at the request queue to check the expected sequence number @@ -346,6 +350,17 @@ private: return steady_clock::now() + (static_cast(std::ceil(duration / 1e-6)) * 1us); } + //! Returns whether or not we have a timed command queued + bool check_timed_in_queue() const + { + for (auto pyld : _req_queue) { + if (pyld.has_timestamp()) { + return true; + } + } + return false; + } + //! Sends a request control packet to a remote device const ctrl_payload send_request_packet(ctrl_opcode_t op_code, uint32_t address, @@ -394,13 +409,18 @@ private: - (ASYNC_MESSAGE_SIZE * _max_outstanding_async_msgs)); }; if (!buff_not_full()) { - if (not _buff_free_cond.wait_until(lock, timeout_time, buff_not_full)) { + // If we're sending a timed command or if we have a timed command in the + // queue, use the MASSIVE_TIMEOUT instead + auto timed_timeout = (check_timed_in_queue() + ? start_timeout(MASSIVE_TIMEOUT) + : timeout_time); + if (not _buff_free_cond.wait_until(lock, timed_timeout, buff_not_full)) { throw uhd::op_timeout( "Control operation timed out waiting for space in command buffer"); } } _buff_occupied += pyld_size; - _req_queue.push(tx_ctrl); + _req_queue.push_back(tx_ctrl); // Send the payload as soon as there is room in the buffer _handle_send(tx_ctrl, _policy.timeout); @@ -497,7 +517,7 @@ private: //! A condition variable that hold the "downstream buffer is free" condition std::condition_variable _buff_free_cond; //! A queue that holds all outstanding requests - std::queue _req_queue; + std::deque _req_queue; //! A queue that holds all outstanding responses and their status std::queue> _resp_queue; //! A condition variable that hold the "response is available" condition -- cgit v1.2.3