diff --git a/srsenb/hdr/phy/phy_common.h b/srsenb/hdr/phy/phy_common.h index 9f4df4a1c..a4a20fff0 100644 --- a/srsenb/hdr/phy/phy_common.h +++ b/srsenb/hdr/phy/phy_common.h @@ -35,7 +35,7 @@ #include "srslte/phy/channel/channel.h" #include "srslte/radio/radio.h" #include -#include +#include #include namespace srsenb { @@ -44,7 +44,6 @@ class phy_common { public: explicit phy_common(uint32_t nof_workers); - ~phy_common(); void set_nof_workers(uint32_t nof_workers); @@ -53,8 +52,20 @@ public: void reset(); void stop(); - void - worker_end(uint32_t tx_mutex_cnt, cf_t* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time); + /** + * TTI transmission semaphore, used for ensuring that PHY workers transmit following start order + */ + srslte::tti_semaphore semaphore; + + /** + * Performs common end worker transmission tasks such as transmission and stack TTI execution + * + * @param tx_sem_id Semaphore identifier, the worker thread pointer is used + * @param buffer baseband IQ sample buffer + * @param nof_samples number of samples to transmit + * @param tx_time timestamp to transmit samples + */ + void worker_end(void* tx_sem_id, cf_t* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time); // Common objects phy_args_t params = {}; @@ -146,8 +157,6 @@ public: private: phy_cell_cfg_list_t cell_list; - std::vector tx_sem; - bool is_first_tx = false; uint32_t nof_workers = 0; uint32_t max_workers = 0; diff --git a/srsenb/src/phy/phy_common.cc b/srsenb/src/phy/phy_common.cc index 2985c1271..8fc76ddb7 100644 --- a/srsenb/src/phy/phy_common.cc +++ b/srsenb/src/phy/phy_common.cc @@ -46,21 +46,10 @@ using namespace asn1::rrc; namespace srsenb { -phy_common::phy_common(uint32_t max_workers_) : tx_sem(max_workers_), cell_list(), ue_db() +phy_common::phy_common(uint32_t max_workers_) : cell_list(), ue_db() { params.max_prach_offset_us = 20; max_workers = max_workers_; - - for (uint32_t i = 0; i < max_workers; i++) { - sem_init(&tx_sem[i], 0, 0); // All semaphores start blocked - } -} - -phy_common::~phy_common() -{ - for (uint32_t i = 0; i < max_workers; i++) { - sem_destroy(&tx_sem[i]); - } } void phy_common::set_nof_workers(uint32_t nof_workers_) @@ -107,8 +96,6 @@ bool phy_common::init(const phy_cell_cfg_list_t& cell_list_, q.resize(cell_list.size()); } - is_first_tx = true; - // Set UE PHY data-base stack ue_db.init(stack, cell_list); @@ -118,9 +105,7 @@ bool phy_common::init(const phy_cell_cfg_list_t& cell_list_, void phy_common::stop() { - for (uint32_t i = 0; i < max_workers; i++) { - sem_post(&tx_sem[i]); - } + semaphore.wait_all(); } /* The transmission of UL subframes must be in sequence. The correct sequence is guaranteed by a chain of N semaphores, @@ -130,35 +115,27 @@ void phy_common::stop() * Each worker uses this function to indicate that all processing is done and data is ready for transmission or * there is no transmission at all (tx_enable). In that case, the end of burst message will be sent to the radio */ -void phy_common::worker_end(uint32_t tti, +void phy_common::worker_end(void* tx_sem_id, cf_t* buffer[SRSLTE_MAX_PORTS], uint32_t nof_samples, srslte_timestamp_t tx_time) { - - // This variable is not protected but it is very unlikely that 2 threads arrive here simultaneously since at the - // beginning there is no workload and threads are separated by 1 ms - if (is_first_tx) { - is_first_tx = false; - // Allow my own transmission if I'm the first to transmit - sem_post(&tx_sem[tti % nof_workers]); - } - // Wait for the green light to transmit in the current TTI - sem_wait(&tx_sem[tti % nof_workers]); + semaphore.wait(tx_sem_id); + // Run DL channel emulator if created if (dl_channel) { dl_channel->run(buffer, buffer, nof_samples, tx_time); } - // always transmit on single radio + // Always transmit on single radio radio->tx(0, buffer, nof_samples, tx_time); - // Allow next TTI to transmit - sem_post(&tx_sem[(tti + 1) % nof_workers]); - // Trigger MAC clock stack->tti_clock(); + + // Allow next TTI to transmit + semaphore.release(); } void phy_common::set_mch_period_stop(uint32_t stop) diff --git a/srsenb/src/phy/sf_worker.cc b/srsenb/src/phy/sf_worker.cc index 023bb2e6c..31525b819 100644 --- a/srsenb/src/phy/sf_worker.cc +++ b/srsenb/src/phy/sf_worker.cc @@ -237,7 +237,7 @@ void sf_worker::work_imp() } Debug("Sending to radio\n"); - phy->worker_end(tx_worker_cnt, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->get_nof_prb(0)), tx_time); + phy->worker_end(this, signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->get_nof_prb(0)), tx_time); #ifdef DEBUG_WRITE_FILE fwrite(signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t), 1, f); diff --git a/srsenb/src/phy/txrx.cc b/srsenb/src/phy/txrx.cc index 314baee04..056044ef4 100644 --- a/srsenb/src/phy/txrx.cc +++ b/srsenb/src/phy/txrx.cc @@ -157,6 +157,7 @@ void txrx::run_thread() tx_worker_cnt = (tx_worker_cnt + 1) % nof_workers; // Trigger phy worker execution + worker_com->semaphore.push(worker); workers_pool->start_worker(worker); // Trigger prach worker execution