diff --git a/srsenb/hdr/stack/enb_stack_lte.h b/srsenb/hdr/stack/enb_stack_lte.h index 90480ba6f..a8ad9473d 100644 --- a/srsenb/hdr/stack/enb_stack_lte.h +++ b/srsenb/hdr/stack/enb_stack_lte.h @@ -38,11 +38,12 @@ #include "enb_stack_base.h" #include "srsenb/hdr/enb.h" +#include "srslte/common/multiqueue.h" #include "srslte/interfaces/enb_interfaces.h" namespace srsenb { -class enb_stack_lte final : public enb_stack_base, public stack_interface_phy_lte +class enb_stack_lte final : public enb_stack_base, public stack_interface_phy_lte, public thread { public: enb_stack_lte(srslte::logger* logger_); @@ -86,16 +87,18 @@ public: // Radio-Link status void rl_failure(uint16_t rnti) final { mac.rl_failure(rnti); } void rl_ok(uint16_t rnti) final { mac.rl_ok(rnti); } - void tti_clock() final - { - timers.step_all(); - mac.tti_clock(); - } + void tti_clock() override; private: + static const int STACK_MAIN_THREAD_PRIO = -1; // Use default high-priority below UHD + // thread loop + void run_thread() override; + void stop_impl(); + void tti_clock_impl(); + + // args stack_args_t args = {}; rrc_cfg_t rrc_cfg = {}; - bool started = false; srsenb::mac mac; srslte::mac_pcap mac_pcap; @@ -118,6 +121,19 @@ private: // RAT-specific interfaces phy_interface_stack_lte* phy = nullptr; + + // state + bool started = false; + // NOTE: we use this struct instead of a std::function bc lambdas can't capture by move in C++11 + struct task_t { + std::function func; + srslte::unique_byte_buffer_t pdu; + task_t() = default; + explicit task_t(std::function f_) : func(std::move(f_)) {} + void operator()() { func(this); } + }; + srslte::multiqueue_handler pending_tasks; + int enb_queue_id = -1, sync_queue_id = -1; }; } // namespace srsenb diff --git a/srsenb/src/stack/enb_stack_lte.cc b/srsenb/src/stack/enb_stack_lte.cc index b44dfc608..e8d43404a 100644 --- a/srsenb/src/stack/enb_stack_lte.cc +++ b/srsenb/src/stack/enb_stack_lte.cc @@ -28,7 +28,9 @@ using namespace srslte; namespace srsenb { -enb_stack_lte::enb_stack_lte(srslte::logger* logger_) : logger(logger_), pdcp(&pdcp_log), timers(128) {} +enb_stack_lte::enb_stack_lte(srslte::logger* logger_) : logger(logger_), pdcp(&pdcp_log), timers(128), thread("STACK") +{ +} enb_stack_lte::~enb_stack_lte() { @@ -46,6 +48,7 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_, ph if (init(args_, rrc_cfg_)) { return SRSLTE_ERROR; } + return SRSLTE_SUCCESS; } @@ -127,31 +130,56 @@ int enb_stack_lte::init(const stack_args_t& args_, const rrc_cfg_t& rrc_cfg_) >pu_log, args.embms.enable); + enb_queue_id = pending_tasks.add_queue(); + sync_queue_id = pending_tasks.add_queue(); + started = true; + start(STACK_MAIN_THREAD_PRIO); return SRSLTE_SUCCESS; } +void enb_stack_lte::tti_clock() +{ + pending_tasks.push(sync_queue_id, task_t{[this](task_t*) { tti_clock_impl(); }}); +} + +void enb_stack_lte::tti_clock_impl() +{ + timers.step_all(); + mac.tti_clock(); +} + void enb_stack_lte::stop() { if (started) { - s1ap.stop(); - gtpu.stop(); - mac.stop(); - usleep(50000); - - rlc.stop(); - pdcp.stop(); - rrc.stop(); - - usleep(10000); - if (args.pcap.enable) { - mac_pcap.close(); - } - started = false; + pending_tasks.push(enb_queue_id, task_t{[this](task_t*) { stop_impl(); }}); + wait_thread_finish(); } } +void enb_stack_lte::stop_impl() +{ + // stop listening to events + pending_tasks.erase_queue(sync_queue_id); + pending_tasks.erase_queue(enb_queue_id); + + s1ap.stop(); + gtpu.stop(); + mac.stop(); + usleep(50000); + + rlc.stop(); + pdcp.stop(); + rrc.stop(); + + usleep(10000); + if (args.pcap.enable) { + mac_pcap.close(); + } + started = false; +} + bool enb_stack_lte::get_metrics(stack_metrics_t* metrics) { mac.get_metrics(metrics->mac); @@ -160,4 +188,14 @@ bool enb_stack_lte::get_metrics(stack_metrics_t* metrics) return true; } +void enb_stack_lte::run_thread() +{ + while (started) { + task_t task{}; + if (pending_tasks.wait_pop(&task) >= 0) { + task(); + } + } +} + } // namespace srsenb