diff --git a/include/srsran/ran/csi_rs/csi_meas_config.h b/include/srsran/ran/csi_rs/csi_meas_config.h index 3893f8b349..fed5593540 100644 --- a/include/srsran/ran/csi_rs/csi_meas_config.h +++ b/include/srsran/ran/csi_rs/csi_meas_config.h @@ -281,10 +281,10 @@ struct csi_aperiodic_trigger_state { bool operator!=(const csi_aperiodic_trigger_state& rhs) const { return !(rhs == *this); } }; -/// Used to configure the UE with a list of aperiodic trigger states. Each codepoint of the DCI field "CSI request" is -/// associated with one trigger state. +/// \brief Used to configure the UE with a list of aperiodic trigger states. Each codepoint of the DCI field +/// "CSI request" is associated with one trigger state. List size ranges from 0 to MAX_NOF_CSI_APERIODIC_TRIGGERS. /// \remark TS 38.331, \c CSI-AperiodicTriggerStateList. -using csi_aperiodic_trigger_state_list = static_vector; +using csi_aperiodic_trigger_state_list = std::vector; /// See TS 38.331, \c CSI-SemiPersistentOnPUSCH-TriggerState. struct csi_semi_persistent_on_pusch_trigger_state { @@ -322,7 +322,7 @@ struct csi_meas_config { std::vector csi_report_cfg_list; /// Size of CSI request field in DCI (bits). See TS 38.214, clause 5.2.1.5.1. std::optional report_trigger_size; - std::optional aperiodic_trigger_state_list; + csi_aperiodic_trigger_state_list aperiodic_trigger_state_list; std::optional semi_persistent_on_pusch_trigger_state_list; bool operator==(const csi_meas_config& rhs) const diff --git a/lib/du/du_high/du_manager/converters/asn1_csi_meas_config_helpers.cpp b/lib/du/du_high/du_manager/converters/asn1_csi_meas_config_helpers.cpp index 742001fd85..4fb13a65e9 100644 --- a/lib/du/du_high/du_manager/converters/asn1_csi_meas_config_helpers.cpp +++ b/lib/du/du_high/du_manager/converters/asn1_csi_meas_config_helpers.cpp @@ -1273,15 +1273,15 @@ void srsran::srs_du::calculate_csi_meas_config_diff(asn1::rrc_nr::csi_meas_cfg_s out.report_trigger_size = dest.report_trigger_size.value(); } - if ((dest.aperiodic_trigger_state_list.has_value() and not src.aperiodic_trigger_state_list.has_value()) or - (dest.aperiodic_trigger_state_list.has_value() and src.aperiodic_trigger_state_list.has_value() and + if ((not dest.aperiodic_trigger_state_list.empty() and src.aperiodic_trigger_state_list.empty()) or + (not dest.aperiodic_trigger_state_list.empty() and not src.aperiodic_trigger_state_list.empty() and dest.aperiodic_trigger_state_list != src.aperiodic_trigger_state_list)) { out.aperiodic_trigger_state_list_present = true; auto& ap_trigger_state_list = out.aperiodic_trigger_state_list.set_setup(); - for (const auto& trigger_state : dest.aperiodic_trigger_state_list.value()) { + for (const auto& trigger_state : dest.aperiodic_trigger_state_list) { ap_trigger_state_list.push_back(make_asn1_aperiodic_trigger_state(trigger_state)); } - } else if (src.aperiodic_trigger_state_list.has_value() and not dest.aperiodic_trigger_state_list.has_value()) { + } else if (not src.aperiodic_trigger_state_list.empty() and dest.aperiodic_trigger_state_list.empty()) { out.aperiodic_trigger_state_list_present = true; out.aperiodic_trigger_state_list.set_release(); } diff --git a/lib/scheduler/config/sched_config_manager.cpp b/lib/scheduler/config/sched_config_manager.cpp index 731462cbc4..164f5c8fdd 100644 --- a/lib/scheduler/config/sched_config_manager.cpp +++ b/lib/scheduler/config/sched_config_manager.cpp @@ -58,12 +58,15 @@ void ue_config_delete_event::reset() } } +// class: sched_config_manager + sched_config_manager::sched_config_manager(const scheduler_config& sched_cfg, scheduler_metrics_handler& metrics_handler_) : expert_params(sched_cfg.expert_params), metrics_handler(metrics_handler_), config_notifier(sched_cfg.config_notifier), - logger(srslog::fetch_basic_logger("SCHED")) + logger(srslog::fetch_basic_logger("SCHED")), + ues_to_rem(MAX_NOF_DU_UES) { std::fill(ue_to_cell_group_index.begin(), ue_to_cell_group_index.end(), INVALID_DU_CELL_GROUP_INDEX); } @@ -89,6 +92,9 @@ ue_config_update_event sched_config_manager::add_ue(const sched_ue_creation_requ { srsran_assert(cfg_req.ue_index < MAX_NOF_DU_UES, "Invalid ue_index={}", cfg_req.ue_index); + // See if there are any pending events to process out of the critical path. + flush_ues_to_rem(); + // Ensure PCell exists. if (not cfg_req.cfg.cells.has_value() or cfg_req.cfg.cells->empty()) { logger.warning("ue={} rnti={}: Discarding invalid UE creation request. Cause: PCell config not provided", @@ -142,6 +148,9 @@ ue_config_update_event sched_config_manager::update_ue(const sched_ue_reconfigur { srsran_assert(cfg_req.ue_index < MAX_NOF_DU_UES, "Invalid ue_index={}", cfg_req.ue_index); + // See if there are any pending events to process out of the critical path. + flush_ues_to_rem(); + // Check if UE already exists. const du_cell_group_index_t group_idx = ue_to_cell_group_index[cfg_req.ue_index].load(std::memory_order_relaxed); if (group_idx == INVALID_DU_CELL_GROUP_INDEX) { @@ -171,6 +180,9 @@ ue_config_delete_event sched_config_manager::remove_ue(du_ue_index_t ue_index) { srsran_assert(ue_index < MAX_NOF_DU_UES, "Invalid ue_index={}", ue_index); + // See if there are any pending events to process out of the critical path. + flush_ues_to_rem(); + // Check if UE already exists. const du_cell_group_index_t group_idx = ue_to_cell_group_index[ue_index].load(std::memory_order_relaxed); if (group_idx == INVALID_DU_CELL_GROUP_INDEX) { @@ -203,7 +215,10 @@ void sched_config_manager::handle_ue_config_complete(du_ue_index_t ue_index, std } // Stores new UE config and deletes old config. - ue_cfg_list[ue_index] = std::move(next_cfg); + ue_cfg_list[ue_index].swap(next_cfg); + if (not ues_to_rem.try_push(std::move(next_cfg))) { + logger.warning("Failed to offload UE config removal. Performance may be affected"); + } // Notifies MAC that event is complete. config_notifier.on_ue_config_complete(ue_index, true); @@ -224,7 +239,11 @@ void sched_config_manager::handle_ue_delete_complete(du_ue_index_t ue_index) du_cell_index_t pcell_idx = ue_cfg_list[ue_index]->pcell_common_cfg().cell_index; // Deletes UE config. + auto old_ue_cfg = std::move(ue_cfg_list[ue_index]); ue_cfg_list[ue_index].reset(); + if (not ues_to_rem.try_push(std::move(old_ue_cfg))) { + logger.warning("Failed to offload UE config removal. Performance may be affected"); + } // Remove UE from metrics. cell_metrics_handler& cell_metrics = metrics_handler.at(pcell_idx); @@ -236,3 +255,12 @@ void sched_config_manager::handle_ue_delete_complete(du_ue_index_t ue_index) // Notifies MAC that event is complete. config_notifier.on_ue_delete_response(ue_index); } + +void sched_config_manager::flush_ues_to_rem() +{ + // Note: This should be called by a thread outside of the critical path. + + // clear the UEs to rem. + while (ues_to_rem.try_pop()) { + } +} diff --git a/lib/scheduler/config/sched_config_manager.h b/lib/scheduler/config/sched_config_manager.h index 231e9c0517..333e43a0bf 100644 --- a/lib/scheduler/config/sched_config_manager.h +++ b/lib/scheduler/config/sched_config_manager.h @@ -11,6 +11,8 @@ #pragma once #include "ue_configuration.h" +#include "srsran/adt/concurrent_queue.h" +#include "srsran/adt/mpmc_queue.h" #include "srsran/adt/noop_functor.h" #include "srsran/scheduler/config/scheduler_config.h" #include "srsran/srslog/logger.h" @@ -127,6 +129,8 @@ class sched_config_manager friend class ue_config_update_event; friend class ue_config_delete_event; + void flush_ues_to_rem(); + void handle_ue_config_complete(du_ue_index_t ue_index, std::unique_ptr next_cfg); void handle_ue_delete_complete(du_ue_index_t ue_index); @@ -140,8 +144,14 @@ class sched_config_manager std::array, MAX_NOF_DU_UES> ue_cfg_list; - /// Mapping of UEs to DU Cell Groups. + // Mapping of UEs to DU Cell Groups. std::array, MAX_NOF_DU_UES> ue_to_cell_group_index; + + // Cached UE configurations to be reused. + concurrent_queue, + concurrent_queue_policy::lockfree_mpmc, + concurrent_queue_wait_policy::non_blocking> + ues_to_rem; }; } // namespace srsran diff --git a/lib/scheduler/pdcch_scheduling/pdcch_slot_resource_allocator.cpp b/lib/scheduler/pdcch_scheduling/pdcch_slot_resource_allocator.cpp index 3aea01677d..30140f7ef2 100644 --- a/lib/scheduler/pdcch_scheduling/pdcch_slot_resource_allocator.cpp +++ b/lib/scheduler/pdcch_scheduling/pdcch_slot_resource_allocator.cpp @@ -15,6 +15,12 @@ using namespace srsran; +pdcch_slot_allocator::pdcch_slot_allocator() +{ + dfs_tree.reserve(MAX_DL_PDCCH_PDUS_PER_SLOT + MAX_UL_PDCCH_PDUS_PER_SLOT); + saved_dfs_tree.reserve(MAX_DL_PDCCH_PDUS_PER_SLOT + MAX_UL_PDCCH_PDUS_PER_SLOT); +} + pdcch_slot_allocator::~pdcch_slot_allocator() {} void pdcch_slot_allocator::clear() diff --git a/lib/scheduler/pdcch_scheduling/pdcch_slot_resource_allocator.h b/lib/scheduler/pdcch_scheduling/pdcch_slot_resource_allocator.h index 99cf6db01b..8e2a9b7e77 100644 --- a/lib/scheduler/pdcch_scheduling/pdcch_slot_resource_allocator.h +++ b/lib/scheduler/pdcch_scheduling/pdcch_slot_resource_allocator.h @@ -42,6 +42,7 @@ class pdcch_slot_allocator unsigned record_index; }; + pdcch_slot_allocator(); ~pdcch_slot_allocator(); /// Erase the current PDCCH allocations and stored context for this slot. diff --git a/tests/unittests/du_manager/serving_cell_config_converter_test.cpp b/tests/unittests/du_manager/serving_cell_config_converter_test.cpp index e630b96d84..e4205955bc 100644 --- a/tests/unittests/du_manager/serving_cell_config_converter_test.cpp +++ b/tests/unittests/du_manager/serving_cell_config_converter_test.cpp @@ -1125,11 +1125,10 @@ TEST(serving_cell_config_converter_test, test_custom_csi_meas_cfg_conversion) dest_csi_meas_cfg.report_trigger_size = 2; - dest_csi_meas_cfg.aperiodic_trigger_state_list.emplace(); auto associated_report_cfg_info_list = csi_associated_report_config_info{.report_cfg_id = static_cast(1), .res_for_channel = csi_associated_report_config_info::csi_ssb_resource_set{1}}; - dest_csi_meas_cfg.aperiodic_trigger_state_list.value().push_back( + dest_csi_meas_cfg.aperiodic_trigger_state_list.push_back( csi_aperiodic_trigger_state{.associated_report_cfg_info_list = {associated_report_cfg_info_list}}); dest_csi_meas_cfg.semi_persistent_on_pusch_trigger_state_list.emplace();