From 2ebc75b9a24adf084664700f7b3698fda76c322b Mon Sep 17 00:00:00 2001
From: Raymond Knopp <raymond.knopp@eurecom.fr>
Date: Wed, 22 Jan 2020 15:09:32 +0100
Subject: [PATCH] fixes for the thread blocking problem

---
 common/utils/LOG/vcd_signal_dumper.c       |  3 ++-
 common/utils/LOG/vcd_signal_dumper.h       |  1 +
 common/utils/T/T_defs.h                    |  2 +-
 common/utils/T/T_messages.txt              |  5 ++++
 executables/nr-gnb.c                       | 13 ++++++++---
 executables/nr-ru.c                        | 27 +++++++++++++++-------
 openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c |  7 +++---
 7 files changed, 41 insertions(+), 17 deletions(-)

diff --git a/common/utils/LOG/vcd_signal_dumper.c b/common/utils/LOG/vcd_signal_dumper.c
index 63c5336bd88..3597add1b5f 100644
--- a/common/utils/LOG/vcd_signal_dumper.c
+++ b/common/utils/LOG/vcd_signal_dumper.c
@@ -512,7 +512,8 @@ const char* eurecomFunctionsNames[] = {
   /*NR softmodem signal*/
   "wakeup_txfh",
   "gNB_thread_rxtx0",
-  "gNB_thread_rxtx1"
+  "gNB_thread_rxtx1",
+  "ru_thread_tx_wait"
 };
 
 struct vcd_module_s vcd_modules[] = {
diff --git a/common/utils/LOG/vcd_signal_dumper.h b/common/utils/LOG/vcd_signal_dumper.h
index 3a6fb6d6abb..b9cc0e47422 100644
--- a/common/utils/LOG/vcd_signal_dumper.h
+++ b/common/utils/LOG/vcd_signal_dumper.h
@@ -505,6 +505,7 @@ typedef enum {
   VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH,
   VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0,
   VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT,
 
   VCD_SIGNAL_DUMPER_FUNCTIONS_END
 } vcd_signal_dump_functions;
diff --git a/common/utils/T/T_defs.h b/common/utils/T/T_defs.h
index ab275d4d62d..344344710a1 100644
--- a/common/utils/T/T_defs.h
+++ b/common/utils/T/T_defs.h
@@ -73,7 +73,7 @@ typedef struct {
 } T_cache_t;
 
 /* number of VCD functions (to be kept up to date! see in T_messages.txt) */
-#define VCD_NUM_FUNCTIONS (245)
+#define VCD_NUM_FUNCTIONS (246)
 
 /* number of VCD variables (to be kept up to date! see in T_messages.txt) */
 #define VCD_NUM_VARIABLES (186)
diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt
index 407bb66be17..f9d92cc418f 100644
--- a/common/utils/T/T_messages.txt
+++ b/common/utils/T/T_messages.txt
@@ -3285,3 +3285,8 @@ ID = VCD_FUNCTION_gNB_PROC_RXTX1
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
     FORMAT = int,value
     VCD_NAME = gNB_thread_rxtx1
+ID = VCD_FUNCTION_RU_TX_WAIT
+    DESC = VCD function RU_TX_WAIT
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = ru_thread_tx_wait
diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c
index 4196b8451d1..bea2bb47952 100644
--- a/executables/nr-gnb.c
+++ b/executables/nr-gnb.c
@@ -423,11 +423,16 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot
 
 // note this  should depend on the numerology used by the TX L1 thread, set here for 500us slot time
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,1);
-  waitret=wait_on_condition(&proc->mutex_RUs_tx,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh"); 
-  AssertFatal(release_thread(&proc->mutex_RUs_tx,&proc->instance_cnt_RUs,"wakeup_txfh")==0, "error releaseing gNB lock on RUs\n"); 
+  AssertFatal((ret = pthread_mutex_lock(&proc->mutex_RUs_tx))==0,"mutex_lock returns %d\n",ret);
+  while (proc->instance_cnt_RUs < 0) {
+    pthread_cond_wait(&proc->cond_RUs,&proc->mutex_RUs_tx); // this unlocks mutex_rxtx while waiting and then locks it again
+  }
+  proc->instance_cnt_RUs = -1;
+  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
+  AssertFatal((ret = pthread_mutex_unlock(&proc->mutex_RUs_tx))==0,"mutex_unlock returns %d\n",ret);
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,0);
 
-  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 (%d.%d) because FH is blocked more than 1 slot times (500us)\n",frame_tx,slot_tx);
@@ -465,6 +470,8 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot
       return(-1);
     }
 
+    AssertFatal((ret=pthread_mutex_lock(&ru_proc->mutex_gNBs))==0,"mutex_lock returned %d\n",ret);
+
     ru_proc->instance_cnt_gNBs = 0;
     ru_proc->timestamp_tx = timestamp_tx;
     ru_proc->tti_tx       = slot_tx;
diff --git a/executables/nr-ru.c b/executables/nr-ru.c
index 168274bfa5d..ea3408f2f69 100644
--- a/executables/nr-ru.c
+++ b/executables/nr-ru.c
@@ -721,8 +721,9 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
   T(T_ENB_PHY_OUTPUT_SIGNAL, T_INT(0), T_INT(0), T_INT(frame), T_INT(slot),
     T_INT(0), T_BUFFER(&ru->common.txdata[0][slot * fp->samples_per_slot], fp->samples_per_slot * 4));
 
-  int slot_type         = nr_slot_select(cfg,frame,slot%((1<<cfg->ssb_config.scs_common.value)*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME));
-  int prevslot_type     = nr_slot_select(cfg,frame,(slot+(((1<<cfg->ssb_config.scs_common.value)*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)-1))%((1<<cfg->ssb_config.scs_common.value)*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME));
+  int slot_type         = nr_slot_select(cfg,frame,slot%fp->slots_per_frame);
+  int prevslot_type     = nr_slot_select(cfg,frame,(slot+(fp->slots_per_frame-1))%fp->slots_per_frame);
+  int nextslot_type     = nr_slot_select(cfg,frame,(slot+1)%fp->slots_per_frame);
   int sf_extension  = 0;                 //sf_extension = ru->sf_extension;
   int siglen=fp->samples_per_slot;
   int flags=1;
@@ -747,7 +748,14 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
         prevslot_type == NR_UPLINK_SLOT) {
       flags = 2; // start of burst
     }
-    
+
+    if (cfg->cell_config.frame_duplex_type.value == TDD &&
+        slot_type == NR_DOWNLINK_SLOT &&
+        nextslot_type == NR_UPLINK_SLOT) {
+      flags = 3; // end of burst
+    }
+   
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS, flags ); 
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame );
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot );
     for (i=0; i<ru->nb_tx; i++)
@@ -1262,7 +1270,10 @@ void *ru_thread_tx( void *param ) {
 
     LOG_D(PHY,"ru_thread_tx: Waiting for TX processing\n");
     // wait until eNBs are finished subframe RX n and TX n+4
+
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 1 );
     wait_on_condition(&proc->mutex_gNBs,&proc->cond_gNBs,&proc->instance_cnt_gNBs,"ru_thread_tx");
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RU_TX_WAIT, 0 );
 
     ret = pthread_mutex_lock(&proc->mutex_gNBs);
     AssertFatal(ret == 0,"mutex_lock return %d\n",ret);
@@ -1355,14 +1366,14 @@ void *ru_thread_tx( void *param ) {
         ret = pthread_mutex_lock(&L1_proc->mutex_RUs_tx);
         AssertFatal(ret == 0,"mutex_lock returns %d\n",ret);
         // the thread can now be woken up
-        //if (L1_proc->instance_cnt_RUs == -1) {
+        if (L1_proc->instance_cnt_RUs == -1) {
           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);
           AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0,
                        "ERROR pthread_cond_signal for gNB_L1_thread\n");
-        //} //else AssertFatal(1==0,"gNB TX thread is not ready\n");
+        } //else AssertFatal(1==0,"gNB TX thread is not ready\n");
         ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx);
         AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret);
-        VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs);
       }
     }
   }
@@ -1502,11 +1513,11 @@ void *ru_thread( void *param ) {
 
     // do RX front-end processing (frequency-shift, dft) if needed
 
-    if (proc->tti_rx == NR_UPLINK_SLOT || fp->frame_type == FDD) {
+    /*if (proc->tti_rx == NR_UPLINK_SLOT || fp->frame_type == FDD) {
 
       if (ru->feprx) ru->feprx(ru,proc->tti_rx);
 
-    }
+    }*/
 
     LOG_D(PHY,"RU proc: frame_rx = %d, tti_rx = %d\n", proc->frame_rx, proc->tti_rx);
     LOG_D(PHY,"Copying rxdataF from RU to gNB\n");
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
index 73f51ed39a4..096e4674686 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
@@ -323,13 +323,12 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
   NR_COMMON_channels_t *cc      = RC.nrmac[module_idP]->common_channels;
   //nfapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config = NULL;
 
-  start_meas(&RC.nrmac[module_idP]->eNB_scheduler);
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN);
-
-
   // Check if there are downlink symbols in the slot, if not return, no scheduling opportunities
   if (is_nr_DL_slot(cc->ServingCellConfigCommon,slot_txP)==0) return;
 
+  start_meas(&RC.nrmac[module_idP]->eNB_scheduler);
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN);
+
   RC.nrmac[module_idP]->frame    = frame_rxP;
   RC.nrmac[module_idP]->slot     = slot_rxP;
 
-- 
GitLab