diff options
author | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-11-19 08:25:47 -0600 |
---|---|---|
committer | michael-west <michael.west@ettus.com> | 2020-12-04 12:05:02 -0800 |
commit | f970d46c56687d2570cc671733ff7736f9ae778b (patch) | |
tree | 7cf9ba018248729550efb1f54dbdaf7fa92d6adb | |
parent | de3b48e89f2f9711b4b97c080d5c35baba45f573 (diff) | |
download | uhd-f970d46c56687d2570cc671733ff7736f9ae778b.tar.gz uhd-f970d46c56687d2570cc671733ff7736f9ae778b.tar.bz2 uhd-f970d46c56687d2570cc671733ff7736f9ae778b.zip |
multi_usrp_rfnoc: Serialize make_rfnoc_device
In certain execution environments (e.g. NI's LabVIEW), the instantiation
of multi_usrp objects may execute in parallel in two different
threads. As the RFNoC block instances are shared between the multi_usrp
instances, there is a risk that threads racing to configure the initial
state of the Tx and Rx chains may operate on inconsistent or incomplete
views of the state of the RFNoC blocks that make up the chain, leaving
them in an invalid state that leads to client-facing errors.
This commit serializes calls to make_rfnoc_device to prevent creating
multiple multi_usrp objects in parallel. It also creates a map of
existing multi_usrp devices and returns the existing multi_usrp
object if it exists.
-rw-r--r-- | host/lib/usrp/multi_usrp_rfnoc.cpp | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/host/lib/usrp/multi_usrp_rfnoc.cpp b/host/lib/usrp/multi_usrp_rfnoc.cpp index 71aca0856..0bef5cfcb 100644 --- a/host/lib/usrp/multi_usrp_rfnoc.cpp +++ b/host/lib/usrp/multi_usrp_rfnoc.cpp @@ -2543,7 +2543,30 @@ multi_usrp::sptr make_rfnoc_device( detail::rfnoc_device::sptr rfnoc_device, const uhd::device_addr_t& dev_addr) { auto graph = uhd::rfnoc::detail::make_rfnoc_graph(rfnoc_device, dev_addr); - return std::make_shared<multi_usrp_rfnoc>(graph, dev_addr); + + // The serialization of this function is intended to protect against + // multiple threads instantiating multi_usrp objects for the same + // device in parallel. + static std::mutex _map_mutex; + static std::map<std::weak_ptr<rfnoc_graph>, + std::weak_ptr<multi_usrp>, + std::owner_less<std::weak_ptr<rfnoc_graph>>> + graph_to_musrp; + multi_usrp::sptr musrp; + + // Check if a multi_usrp was already created for this device + std::lock_guard<std::mutex> lock(_map_mutex); + if (graph_to_musrp.count(graph) and not graph_to_musrp[graph].expired()) { + musrp = graph_to_musrp[graph].lock(); + if (musrp) { + return musrp; + } + } + + // Create a new musrp + musrp = std::make_shared<multi_usrp_rfnoc>(graph, dev_addr); + graph_to_musrp[graph] = musrp; + return musrp; } }}} // namespace uhd::rfnoc::detail |