From 8c1f9c9e75b8900f4dfa448a5c341172156726b9 Mon Sep 17 00:00:00 2001 From: Raymond Knopp <raymond.knopp@eurecom.fr> Date: Mon, 6 May 2019 16:04:04 +0200 Subject: [PATCH] modifications to synchronization between RU_TX and L1_TX (timed cond wait to drop slots) tested on both 40 and 80 MHz channels --- openair1/PHY/defs_common.h | 29 +++++++++++++++++++++++++++++ targets/RT/USER/gNB_usrp.gtkw | 25 +++++++++++++++---------- targets/RT/USER/nr-gnb.c | 34 ++++++++++++++++++++++------------ targets/RT/USER/nr-ru.c | 4 +++- 4 files changed, 69 insertions(+), 23 deletions(-) diff --git a/openair1/PHY/defs_common.h b/openair1/PHY/defs_common.h index f479c30b8c..c035b75fea 100644 --- a/openair1/PHY/defs_common.h +++ b/openair1/PHY/defs_common.h @@ -1011,6 +1011,35 @@ static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond, return(0); } +static inline int timedwait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name,uint32_t time_ns) { + int rc; + int waitret=0; + if ((rc = pthread_mutex_lock(mutex)) != 0) { + LOG_E(PHY, "[SCHED][eNB] wait_on_condition(): error locking mutex for %s (%d %s, %p)\n", + name, rc, strerror(rc), (void *)mutex); + exit_fun("nothing to add"); + return(-1); + } + + struct timespec now,abstime; + + while (*instance_cnt < 0) { + clock_gettime(CLOCK_REALTIME,&now); + // most of the time the thread is waiting here + // proc->instance_cnt_rxtx is -1 + abstime.tv_sec=now.tv_sec; + abstime.tv_nsec = now.tv_nsec + time_ns; + if ((waitret = pthread_cond_timedwait(cond,mutex,&abstime))==ETIMEDOUT) break; // this unlocks mutex_rxtx while waiting and then locks it again + + } + + if (pthread_mutex_unlock(mutex) != 0) { + LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name); + exit_fun("nothing to add"); + return(-1); + } + return(waitret); +} static inline int wait_on_busy_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { int rc; if ((rc = pthread_mutex_lock(mutex)) != 0) { diff --git a/targets/RT/USER/gNB_usrp.gtkw b/targets/RT/USER/gNB_usrp.gtkw index 74e04e6a73..818cff3548 100644 --- a/targets/RT/USER/gNB_usrp.gtkw +++ b/targets/RT/USER/gNB_usrp.gtkw @@ -1,19 +1,19 @@ [*] [*] GTKWave Analyzer v3.3.61 (w)1999-2014 BSI -[*] Wed May 1 00:14:54 2019 +[*] Mon May 6 11:32:36 2019 [*] -[dumpfile] "/tmp/openair_dump_eNB.vcd" -[dumpfile_mtime] "Wed May 1 00:10:57 2019" -[dumpfile_size] 22152850 +[dumpfile] "/tmp/openair_dump_gNB40.vcd" +[dumpfile_mtime] "Mon May 6 11:32:05 2019" +[dumpfile_size] 803075 [savefile] "/home/caracal/raymond/openairinterface5g/targets/RT/USER/gNB_usrp.gtkw" -[timestart] 11537525000 -[size] 1859 841 +[timestart] 10835824000 +[size] 1920 859 [pos] -1 -1 -*-19.848083 11540069031 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +*-19.848083 10838512202 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 [sst_width] 386 [signals_width] 344 [sst_expanded] 1 -[sst_vpaned_height] 421 +[sst_vpaned_height] 197 @28 functions.trx_read functions.trx_write @@ -30,8 +30,6 @@ variables.tti_number_TX0_RU[63:0] @28 functions.mac_schedule_dlsch functions.macxface_eNB_dlsch_ulsch_scheduler -functions.macxface_ue_scheduler -functions.phy_eNB_ofdm_mod_l @24 variables.frame_number_RX0_gNB[63:0] variables.slot_number_RX0_gNB[63:0] @@ -46,6 +44,13 @@ variables.frame_number_TX1_gNB[63:0] variables.slot_number_TX1_gNB[63:0] @28 functions.gNB_thread_rxtx1 +functions.phy_enb_pdcch_tx +functions.phy_eNB_dlsch_encoding +functions.phy_eNB_dlsch_encoding_w +functions.generate_dlsch +@421 +variables.frame_number_RX0_UE[63:0] +@28 functions.phy_procedures_ru_feprx0 functions.phy_procedures_ru_feprx1 functions.phy_procedures_ru_feptx_ofdm0 diff --git a/targets/RT/USER/nr-gnb.c b/targets/RT/USER/nr-gnb.c index 6c30375d61..ecd5d035f7 100644 --- a/targets/RT/USER/nr-gnb.c +++ b/targets/RT/USER/nr-gnb.c @@ -248,7 +248,8 @@ static void* gNB_L1_thread_tx(void* param) { while (!oai_exit) { - if (wait_on_condition(&L1_proc_tx->mutex,&L1_proc_tx->cond,&L1_proc_tx->instance_cnt,thread_name)<0) break; + while (L1_proc_tx->instance_cnt==-1) + if (wait_on_condition(&L1_proc_tx->mutex,&L1_proc_tx->cond,&L1_proc_tx->instance_cnt,thread_name)<0) break; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 1 ); if (oai_exit) break; // ***************************************** @@ -273,8 +274,8 @@ static void* gNB_L1_thread_tx(void* param) { exit_fun( "ERROR pthread_cond_signal" ); } pthread_mutex_unlock( &L1_proc_tx->mutex ); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 0 ); wakeup_txfh(gNB,L1_proc_tx,frame_tx,slot_tx,timestamp_tx); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 0 ); } return 0; @@ -398,22 +399,31 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot RU_t *ru; RU_proc_t *ru_proc; - + int waitret; struct timespec wait; wait.tv_sec=0; wait.tv_nsec=5000000L; + - if(wait_on_condition(&proc->mutex_RUs_tx,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh")<0) { - LOG_E(PHY,"Frame %d, subframe %d: TX FH not ready\n", proc->frame_tx, proc->slot_tx); - return(-1); - } + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); + +// note this should depend on the numerology used by the TX L1 thread, set here for 500us slot time + waitret=timedwait_on_condition(&proc->mutex_RUs_tx,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh",500000); - pthread_mutex_lock(&gNB->proc.mutex_RU_tx); - gNB->proc.RU_mask_tx = 0; - pthread_mutex_unlock(&gNB->proc.mutex_RU_tx); if (release_thread(&proc->mutex_RUs_tx,&proc->instance_cnt_RUs,"wakeup_txfh")<0) return(-1); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs); + + if (waitret == ETIMEDOUT) { + LOG_W(PHY,"Dropping TX slot because FH is blocked more than 2 slot times (1000us)\n"); + + pthread_mutex_lock(&gNB->proc.mutex_RU_tx); + gNB->proc.RU_mask_tx = 0; + pthread_mutex_unlock(&gNB->proc.mutex_RU_tx); + + return(-1); + } for(int i=0; i<gNB->num_RU; i++) { ru = gNB->RU_list[i]; @@ -523,7 +533,7 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { /* accept some delay in processing - up to 5ms */ for (i = 0; i < fp->slots_per_frame && L1_proc->instance_cnt == 0; i++) { - LOG_W( PHY,"[gNB] SFN.SL %d.%d, gNB RXn-TXnp4 thread busy!! (i %d, cnt %i)\n", L1_proc->frame_tx, L1_proc->slot_tx, i,L1_proc->instance_cnt); + LOG_W( PHY,"[gNB] SFN.SL %d.%d, gNB L1 thread busy!! (i %d, cnt %i)\n", L1_proc->frame_tx, L1_proc->slot_tx, i,L1_proc->instance_cnt); usleep(100); } if (L1_proc->instance_cnt == 0) { @@ -534,7 +544,7 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) { // wake up TX for subframe n+sl_ahead // lock the TX mutex and make sure the thread is ready if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) { - LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB RXTX thread %d (IC %d)\n", L1_proc->slot_rx&1,L1_proc->instance_cnt ); + LOG_E( PHY, "[gNB] ERROR pthread_mutex_lock for gNB L1 thread %d (IC %d)\n", L1_proc->slot_rx&1,L1_proc->instance_cnt ); exit_fun( "error locking mutex" ); return(-1); } diff --git a/targets/RT/USER/nr-ru.c b/targets/RT/USER/nr-ru.c index ad45218861..058ac8748c 100644 --- a/targets/RT/USER/nr-ru.c +++ b/targets/RT/USER/nr-ru.c @@ -791,7 +791,7 @@ void tx_rf(RU_t *ru) { txp, siglen+sf_extension, ru->nb_tx, - flags); + 4);//flags); LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx, (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->frame_tx_unwrap,proc->tti_tx); @@ -1370,6 +1370,8 @@ static void* ru_thread_tx( void* param ) { pthread_mutex_lock(&L1_proc->mutex_RUs_tx); L1_proc->instance_cnt_RUs = 0; + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs); + // the thread can now be woken up if (pthread_cond_signal(&L1_proc->cond_RUs) != 0) { LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB L1 TX thread\n"); -- 2.26.2