diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_common.h b/srsenb/hdr/stack/mac/nr/sched_nr_common.h index 75d7ad1aa..701fb1d31 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_common.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_common.h @@ -44,6 +44,46 @@ struct sched_params { using rbgmask_t = srsran::bounded_bitset; +struct resource_guard { +public: + resource_guard() = default; + resource_guard(const resource_guard& other) = delete; + resource_guard(resource_guard&& other) = delete; + resource_guard& operator=(const resource_guard& other) = delete; + resource_guard& operator=(resource_guard&& other) = delete; + bool busy() const { return flag; } + + struct token { + token() = default; + token(resource_guard& parent) : flag(parent.busy() ? nullptr : &parent.flag) + { + if (flag != nullptr) { + *flag = true; + } + } + token(token&&) noexcept = default; + token& operator=(token&&) noexcept = default; + void release() { flag.reset(); } + bool owns_token() const { return flag != nullptr; } + bool empty() const { return flag == nullptr; } + + private: + struct release_deleter { + void operator()(bool* ptr) + { + if (ptr != nullptr) { + srsran_assert(*ptr == true, "resource token: detected inconsistency token state"); + *ptr = false; + } + } + }; + std::unique_ptr flag; + }; + +private: + bool flag = false; +}; + } // namespace sched_nr_impl } // namespace srsenb diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h index 16688f11c..327d89d3e 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_ue.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_ue.h @@ -30,11 +30,11 @@ class slot_ue { public: slot_ue() = default; - explicit slot_ue(bool& busy_signal, tti_point tti_rx_, uint32_t cc); + explicit slot_ue(resource_guard::token ue_token, tti_point tti_rx_, uint32_t cc); ~slot_ue(); slot_ue(slot_ue&&) noexcept = default; slot_ue& operator=(slot_ue&&) noexcept = default; - bool empty() const { return busy_signal == nullptr; } + bool empty() const { return ue_token.empty(); } void release(); tti_point tti_rx; @@ -51,10 +51,7 @@ public: harq_proc* h_ul = nullptr; private: - struct noop { - void operator()(bool* ptr) {} - }; - std::unique_ptr busy_signal; + resource_guard::token ue_token; }; class ue_carrier @@ -77,8 +74,8 @@ public: private: const sched_nr_ue_cfg* cfg = nullptr; - bool busy{false}; - tti_point last_tti_rx; + resource_guard busy; + tti_point last_tti_rx; srsran::deque > pending_feedback; }; diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index 9d3d0dbef..5e8d3b570 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -15,8 +15,8 @@ namespace srsenb { namespace sched_nr_impl { -slot_ue::slot_ue(bool& busy_signal_, tti_point tti_rx_, uint32_t cc_) : - busy_signal(&busy_signal_), tti_rx(tti_rx_), cc(cc_) +slot_ue::slot_ue(resource_guard::token ue_token_, tti_point tti_rx_, uint32_t cc_) : + ue_token(std::move(ue_token_)), tti_rx(tti_rx_), cc(cc_) {} slot_ue::~slot_ue() @@ -26,9 +26,7 @@ slot_ue::~slot_ue() void slot_ue::release() { - if (busy_signal != nullptr) { - *busy_signal = false; - } + ue_token.release(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -48,12 +46,11 @@ void ue_carrier::push_feedback(srsran::move_callback callback slot_ue ue_carrier::try_reserve(tti_point tti_rx, const sched_nr_ue_cfg& uecfg_) { - slot_ue sfu = (busy) ? slot_ue() : slot_ue(busy, tti_rx, cc); + slot_ue sfu(busy, tti_rx, cc); if (sfu.empty()) { return sfu; } // successfully acquired. Process any CC-specific pending feedback - busy = true; if (cfg != &uecfg_) { set_cfg(uecfg_); } diff --git a/srsenb/src/stack/mac/nr/sched_nr_worker.cc b/srsenb/src/stack/mac/nr/sched_nr_worker.cc index ad8089844..50ed4d71f 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_worker.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_worker.cc @@ -111,8 +111,13 @@ sched_worker_manager::sched_worker_manager(ue_map_t& ue_db_, const sched_params& sched_worker_manager::~sched_worker_manager() { - for (uint32_t sf = 0; sf < slot_ctxts.size(); ++sf) { - sem_destroy(&slot_ctxts[sf]->sf_sem); + // acquire all slot worker contexts + for (auto& slot_ctxt : slot_ctxts) { + sem_wait(&slot_ctxt->sf_sem); + } + // destroy all slot worker contexts + for (auto& slot_ctxt : slot_ctxts) { + sem_destroy(&slot_ctxt->sf_sem); } } diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index d60a3b265..75c2d7522 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -20,6 +20,7 @@ struct task_job_manager { std::mutex mutex; std::condition_variable cond_var; int tasks = 0; + int res_count = 0; int pdsch_count = 0; int max_tasks = std::numeric_limits::max() / 2; @@ -35,6 +36,7 @@ struct task_job_manager { { std::unique_lock lock(mutex); TESTASSERT(res.dl_res.data.size() <= 1); + res_count++; pdsch_count += res.dl_res.data.size(); if (tasks-- >= max_tasks or tasks == 0) { cond_var.notify_one(); @@ -47,6 +49,7 @@ struct task_job_manager { cond_var.wait(lock); } } + void print_results() const { printf("TESTER: %f PDSCH/{slot,cc} were allocated\n", pdsch_count / (double)res_count); } }; void sched_nr_cfg_serialized_test() @@ -66,7 +69,7 @@ void sched_nr_cfg_serialized_test() uecfg.carriers[0].active = true; sched.ue_cfg(0x46, uecfg); - for (uint32_t nof_ttis = 0; nof_ttis < 1000; ++nof_ttis) { + for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti(nof_ttis % 10240); sched.new_tti(tti); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { @@ -77,7 +80,7 @@ void sched_nr_cfg_serialized_test() } } - printf("TESTER: %f PDSCH/slot were allocated\n", tasks.pdsch_count / (double)max_nof_ttis); + tasks.print_results(); } void sched_nr_cfg_parallel_cc_test() @@ -114,7 +117,7 @@ void sched_nr_cfg_parallel_cc_test() tasks.wait_task_finish(); - printf("TESTER: %f PDSCH/slot were allocated\n", tasks.pdsch_count / (double)max_nof_ttis); + tasks.print_results(); } void sched_nr_cfg_parallel_sf_test() @@ -141,8 +144,8 @@ void sched_nr_cfg_parallel_sf_test() for (uint32_t nof_ttis = 0; nof_ttis < max_nof_ttis; ++nof_ttis) { tti_point tti(nof_ttis % 10240); sched.new_tti(tti); - tasks.start_task(); for (uint32_t cc = 0; cc < cells_cfg.size(); ++cc) { + tasks.start_task(); srsran::get_background_workers().push_task([cc, &sched, tti, &tasks]() { sched_nr_res_t res; TESTASSERT(sched.generate_sched_result(tti, cc, res) == SRSRAN_SUCCESS); @@ -153,7 +156,7 @@ void sched_nr_cfg_parallel_sf_test() tasks.wait_task_finish(); - printf("TESTER: %f PDSCH/slot were allocated\n", tasks.pdsch_count / (double)max_nof_ttis); + tasks.print_results(); } } // namespace srsenb @@ -169,5 +172,5 @@ int main() srsenb::sched_nr_cfg_serialized_test(); srsenb::sched_nr_cfg_parallel_cc_test(); - // srsenb::sched_nr_cfg_parallel_sf_test(); + srsenb::sched_nr_cfg_parallel_sf_test(); } \ No newline at end of file