1 // 2 // Copyright 2019 Ettus Research, a National Instruments Brand 3 // 4 // SPDX-License-Identifier: GPL-3.0-or-later 5 // 6 7 #include "x300_claim.hpp" 8 #include "x300_fw_common.h" 9 #include <uhd/utils/platform.hpp> 10 #include <chrono> 11 #include <thread> 12 13 using namespace uhd; 14 using namespace uhd::usrp::x300; 15 16 /*********************************************************************** 17 * claimer logic 18 **********************************************************************/ 19 claimer_loop(wb_iface::sptr iface)20void uhd::usrp::x300::claimer_loop(wb_iface::sptr iface) 21 { 22 claim(iface); 23 std::this_thread::sleep_for(std::chrono::seconds(1)); 24 } 25 claim_status(wb_iface::sptr iface)26claim_status_t uhd::usrp::x300::claim_status(wb_iface::sptr iface) 27 { 28 claim_status_t claim_status = CLAIMED_BY_OTHER; // Default to most restrictive 29 auto timeout_time = std::chrono::steady_clock::now() + std::chrono::seconds(1); 30 while (std::chrono::steady_clock::now() < timeout_time) { 31 // If timed out, then device is definitely unclaimed 32 if (iface->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_STATUS)) == 0) { 33 claim_status = UNCLAIMED; 34 break; 35 } 36 37 // otherwise check claim src to determine if another thread with the same src has 38 // claimed the device 39 uint32_t hash = iface->peek32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_SRC)); 40 if (hash == 0) { 41 // A non-zero claim status and an empty hash means the claim might 42 // be in the process of being released. This is possible because 43 // older firmware takes a long time to update the status. Wait and 44 // check status again. 45 std::this_thread::sleep_for(std::chrono::milliseconds(5)); 46 continue; 47 } 48 claim_status = (hash == get_process_hash() ? CLAIMED_BY_US : CLAIMED_BY_OTHER); 49 break; 50 } 51 return claim_status; 52 } 53 claim(wb_iface::sptr iface)54void uhd::usrp::x300::claim(wb_iface::sptr iface) 55 { 56 iface->poke32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_TIME), uint32_t(time(NULL))); 57 iface->poke32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_SRC), get_process_hash()); 58 } 59 try_to_claim(wb_iface::sptr iface,long timeout_ms)60bool uhd::usrp::x300::try_to_claim(wb_iface::sptr iface, long timeout_ms) 61 { 62 const auto timeout_time = 63 std::chrono::steady_clock::now() + std::chrono::milliseconds(timeout_ms); 64 while (1) { 65 claim_status_t status = claim_status(iface); 66 if (status == UNCLAIMED) { 67 claim(iface); 68 // It takes the claimer 10ms to update status, so wait 20ms before verifying 69 // claim 70 std::this_thread::sleep_for(std::chrono::milliseconds(20)); 71 continue; 72 } 73 if (status == CLAIMED_BY_US) { 74 break; 75 } 76 if (std::chrono::steady_clock::now() > timeout_time) { 77 // Another process owns the device - give up 78 return false; 79 } 80 std::this_thread::sleep_for(std::chrono::milliseconds(100)); 81 } 82 return true; 83 } 84 release(wb_iface::sptr iface)85void uhd::usrp::x300::release(wb_iface::sptr iface) 86 { 87 iface->poke32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_TIME), 0); 88 iface->poke32(X300_FW_SHMEM_ADDR(X300_FW_SHMEM_CLAIM_SRC), 0); 89 } 90