From 4f1c51f38ca4812fd8423ce70f57cda7b97e9d17 Mon Sep 17 00:00:00 2001
From: Robert Schmidt <robert.schmidt@eurecom.fr>
Date: Thu, 25 Jan 2018 14:07:45 +0100
Subject: [PATCH] add phy_free_RU() and phy_free_lte_eNB()

this methods free the memory that is allocated by the functions
phy_init_RU() and phy_init_lte_eNB()
---
 openair1/PHY/INIT/defs.h        |   7 ++
 openair1/PHY/INIT/lte_init.c    | 127 +++++++++++++++++++++++++++++++-
 openair1/PHY/defs.h             |   6 ++
 targets/RT/USER/lte-enb.c       |   2 +
 targets/RT/USER/lte-ru.c        |   3 +
 targets/RT/USER/lte-softmodem.c |   4 +
 6 files changed, 147 insertions(+), 2 deletions(-)

diff --git a/openair1/PHY/INIT/defs.h b/openair1/PHY/INIT/defs.h
index 744fb3d3ce..e7972335ab 100644
--- a/openair1/PHY/INIT/defs.h
+++ b/openair1/PHY/INIT/defs.h
@@ -90,6 +90,13 @@ int phy_init_lte_eNB(PHY_VARS_eNB *phy_vars_eNb,
                      unsigned char is_secondary_eNb,
                      unsigned char abstraction_flag);
 
+/*!
+\brief Free the PHY variables relevant to the LTE implementation (eNB).
+\details Only a subset of phy_vars_eNb is freed (those who have been allocated with phy_init_lte_eNB()).
+@param[in] phy_vars_eNb Pointer to eNB Variables
+ */
+void phy_free_lte_eNB(PHY_VARS_eNB *phy_vars_eNb);
+
 /** \brief Configure LTE_DL_FRAME_PARMS with components derived after initial synchronization (MIB decoding + primary/secondary synch).
 \details The basically allows configuration of \f$N_{\mathrm{RB}}^{\mathrm{DL}}\f$, the cell id  \f$N_{\mathrm{ID}}^{\mathrm{cell}}\f$, the normal/extended prefix mode, the frame type (FDD/TDD), \f$N_{\mathrm{cp}}\f$, the number of TX antennas at eNB (\f$p\f$) and the number of PHICH groups, \f$N_{\mathrm{group}}^{\mathrm{PHICH}}\f$
 @param lte_frame_parms pointer to LTE parameter structure
diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c
index 283667134d..f5db781309 100644
--- a/openair1/PHY/INIT/lte_init.c
+++ b/openair1/PHY/INIT/lte_init.c
@@ -1777,7 +1777,55 @@ int phy_init_RU(RU_t *ru) {
 
   return(0);
 }
-  
+
+void phy_free_RU(RU_t *ru)
+{
+  int i,j;
+  int p;
+
+  LOG_I(PHY, "Feeing RU signal buffers (if_south %s) nb_tx %d\n", ru_if_types[ru->if_south], ru->nb_tx);
+
+  if (ru->if_south <= REMOTE_IF5) { // this means REMOTE_IF5 or LOCAL_RF, so free memory for time-domain signals
+    for (i = 0; i < ru->nb_tx; i++) free_and_zero(ru->common.txdata[i]);
+    for (i = 0; i < ru->nb_rx; i++) free_and_zero(ru->common.rxdata[i]);
+    free_and_zero(ru->common.txdata);
+    free_and_zero(ru->common.rxdata);
+  } // else: IF5 or local RF -> nothing to free()
+
+  if (ru->function != NGFI_RRU_IF5) { // we need to do RX/TX RU processing
+    for (i = 0; i < ru->nb_rx; i++) free_and_zero(ru->common.rxdata_7_5kHz[i]);
+    free_and_zero(ru->common.rxdata_7_5kHz);
+
+    // free IFFT input buffers (TX)
+    for (i = 0; i < ru->nb_tx; i++) free_and_zero(ru->common.txdataF_BF[i]);
+    free_and_zero(ru->common.txdataF_BF);
+
+    // free FFT output buffers (RX)
+    for (i = 0; i < ru->nb_rx; i++) free_and_zero(ru->common.rxdataF[i]);
+    free_and_zero(ru->common.rxdataF);
+
+    for (i = 0; i < ru->nb_rx; i++) {
+      free_and_zero(ru->prach_rxsigF[i]);
+#ifdef Rel14
+      for (j = 0; j < 4; j++) free_and_zero(ru->prach_rxsigF_br[j][i]);
+#endif
+    }
+    for (j = 0; j < 4; j++) free_and_zero(ru->prach_rxsigF_br[j]);
+    free_and_zero(ru->prach_rxsigF);
+    /* ru->prach_rxsigF_br is not allocated -> don't free */
+
+    for (i = 0; i < RC.nb_L1_inst; i++) {
+      for (p = 0; p < 15; p++) {
+	if (p < ru->eNB_list[i]->frame_parms.nb_antenna_ports_eNB || p == 5) {
+	  for (j=0; j<ru->nb_tx; j++) free_and_zero(ru->beam_weights[i][p][j]);
+	  free_and_zero(ru->beam_weights[i][p]);
+	}
+      }
+    }
+  }
+  free_and_zero(ru->common.sync_corr);
+}
+
 int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
                      unsigned char is_secondary_eNB,
                      unsigned char abstraction_flag)
@@ -1911,7 +1959,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
     AssertFatal(fp->N_RB_UL > 5, "fp->N_RB_UL %d < 6\n",fp->N_RB_UL);
     for (i=0; i<2; i++) {
       // RK 2 times because of output format of FFT!
-      // FIXME We should get rid of this
+      // FIXME We should get rid of this, consider also phy_free_lte_eNB()
       pusch_vars[UE_id]->rxdataF_ext[i]      = (int32_t*)malloc16_clear( 2*sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti );
       pusch_vars[UE_id]->rxdataF_ext2[i]     = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti );
       pusch_vars[UE_id]->drs_ch_estimates[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*fp->N_RB_UL*12*fp->symbols_per_tti );
@@ -1934,3 +1982,78 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
   return (0);
 
 }
+
+
+void phy_free_lte_eNB(PHY_VARS_eNB *eNB)
+{
+  LTE_DL_FRAME_PARMS* const fp       = &eNB->frame_parms;
+  LTE_eNB_COMMON* const common_vars  = &eNB->common_vars;
+  LTE_eNB_PUSCH** const pusch_vars   = eNB->pusch_vars;
+  LTE_eNB_SRS* const srs_vars        = eNB->srs_vars;
+  LTE_eNB_PRACH* const prach_vars    = &eNB->prach_vars;
+#ifdef Rel14
+  LTE_eNB_PRACH* const prach_vars_br = &eNB->prach_vars_br;
+#endif
+  int i, UE_id;
+
+  for (i = 0; i < NB_ANTENNA_PORTS_ENB; i++) {
+    if (i < fp->nb_antenna_ports_eNB || i == 5) {
+      free_and_zero(common_vars->txdataF[i]);
+      /* rxdataF[i] is not allocated -> don't free */
+    }
+  }
+  free_and_zero(common_vars->txdataF);
+  free_and_zero(common_vars->rxdataF);
+
+  // Channel estimates for SRS
+  for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
+    for (i=0; i<64; i++) {
+      free_and_zero(srs_vars[UE_id].srs_ch_estimates[i]);
+      free_and_zero(srs_vars[UE_id].srs_ch_estimates_time[i]);
+    }
+    free_and_zero(srs_vars[UE_id].srs_ch_estimates);
+    free_and_zero(srs_vars[UE_id].srs_ch_estimates_time);
+  } //UE_id
+
+  free_ul_ref_sigs();
+
+  for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) free_and_zero(srs_vars[UE_id].srs);
+
+  free_and_zero(prach_vars->prachF);
+
+  for (i = 0; i < 64; i++) free_and_zero(prach_vars->prach_ifft[0][i]);
+  free_and_zero(prach_vars->prach_ifft[0]);
+
+#ifdef Rel14
+  for (int ce_level = 0; ce_level < 4; ce_level++) {
+    for (i = 0; i < 64; i++) free_and_zero(prach_vars_br->prach_ifft[ce_level][i]);
+    free_and_zero(prach_vars_br->prach_ifft[ce_level]);
+    free_and_zero(prach_vars->rxsigF[ce_level]);
+  }
+  free_and_zero(prach_vars_br->prachF);
+#endif
+  free_and_zero(prach_vars->rxsigF[0]);
+
+  for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
+    for (i = 0; i < 2; i++) {
+      free_and_zero(pusch_vars[UE_id]->rxdataF_ext[i]);
+      free_and_zero(pusch_vars[UE_id]->rxdataF_ext2[i]);
+      free_and_zero(pusch_vars[UE_id]->drs_ch_estimates[i]);
+      free_and_zero(pusch_vars[UE_id]->drs_ch_estimates_time[i]);
+      free_and_zero(pusch_vars[UE_id]->rxdataF_comp[i]);
+      free_and_zero(pusch_vars[UE_id]->ul_ch_mag[i]);
+      free_and_zero(pusch_vars[UE_id]->ul_ch_magb[i]);
+    }
+    free_and_zero(pusch_vars[UE_id]->rxdataF_ext);
+    free_and_zero(pusch_vars[UE_id]->rxdataF_ext2);
+    free_and_zero(pusch_vars[UE_id]->drs_ch_estimates);
+    free_and_zero(pusch_vars[UE_id]->drs_ch_estimates_time);
+    free_and_zero(pusch_vars[UE_id]->rxdataF_comp);
+    free_and_zero(pusch_vars[UE_id]->ul_ch_mag);
+    free_and_zero(pusch_vars[UE_id]->ul_ch_magb);
+    free_and_zero(pusch_vars[UE_id]->llr);
+    free_and_zero(pusch_vars[UE_id]);
+  } //UE_id
+
+  for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) eNB->UE_stats_ptr[UE_id] = NULL;
+}
diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index 0e44a7f8bd..b5c2e54fa5 100644
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -79,6 +79,12 @@
 #define bigmalloc16 malloc16
 #define openair_free(y,x) free((y))
 #define PAGE_SIZE 4096
+#define free_and_zero(PtR) do { \
+      if (PtR) {           \
+        free(PtR);         \
+        PtR = NULL;        \
+      }                    \
+    } while (0)
 
 #define RX_NB_TH_MAX 2
 #define RX_NB_TH 2
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index 6b418bb8ff..ece2b75c77 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -974,5 +974,7 @@ void stop_eNB(int nb_inst) {
   for (int inst=0;inst<nb_inst;inst++) {
     LOG_I(PHY,"Killing eNB %d processing threads\n",inst);
     kill_eNB_proc(inst);
+    /* release memory used by these threads (incomplete) */
+    for (int cc_id = 0; cc_id < RC.nb_CC[inst]; cc_id++) phy_free_lte_eNB(RC.eNB[inst][cc_id]);
   }
 }
diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c
index e2918091e9..6459b6a58d 100644
--- a/targets/RT/USER/lte-ru.c
+++ b/targets/RT/USER/lte-ru.c
@@ -114,6 +114,7 @@ extern volatile int                    oai_exit;
 
 
 extern void  phy_init_RU(RU_t*);
+extern void  phy_free_RU(RU_t*);
 
 void init_RU(char*);
 void stop_RU(int nb_ru);
@@ -2177,5 +2178,7 @@ void stop_RU(int nb_ru)
   for (int inst = 0; inst < nb_ru; inst++) {
     LOG_I(PHY, "Stopping RU %d processing threads\n", inst);
     kill_RU_proc(inst);
+    /* release memory used by these threads (incomplete) */
+    phy_free_RU(RC.ru[inst]);
   }
 }
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 91d626c9d3..6ae35a9bf0 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -884,6 +884,8 @@ void terminate_task(task_id_t task_id, module_id_t mod_id)
   itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
 }
 
+extern void  phy_free_RU(RU_t*);
+
 int stop_L1L2(module_id_t enb_id)
 {
   LOG_W(ENB_APP, "stopping lte-softmodem\n");
@@ -921,6 +923,8 @@ int stop_L1L2(module_id_t enb_id)
   LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id);
   kill_RU_proc(enb_id);
   oai_exit = 0;
+  for (int cc_id = 0; cc_id < RC.nb_CC[enb_id]; cc_id++) phy_free_lte_eNB(RC.eNB[enb_id][cc_id]);
+  phy_free_RU(RC.ru[enb_id]);
   return 0;
 }
 
-- 
GitLab