From 76fc205b352b1a813ddfac553d9e67ef7d2a9274 Mon Sep 17 00:00:00 2001
From: Cedric Roux <cedric.roux@eurecom.fr>
Date: Mon, 8 Jun 2015 08:24:51 +0000
Subject: [PATCH] carrier aggregation prepartion work: - handle an UE on the
 second carrier - quick fix (may change in the future) to deal with race
 conditions   in lte-softmodem. TX procedures (phy_procedures_eNB_TX) are now
 done   the one after the other, from carrier 0 to carrier N.

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@7541 818b1a75-f10b-46b9-bf7c-635c3b92a50f
---
 openair1/SCHED/phy_procedures_lte_eNb.c |  3 +-
 openair2/LAYER2/MAC/config.c            | 13 ++++---
 openair2/LAYER2/MAC/eNB_scheduler.c     | 11 +++---
 openair2/LAYER2/MAC/proto.h             |  2 +
 openair2/RRC/LITE/defs.h                |  8 ++--
 openair2/RRC/LITE/rrc_UE.c              | 17 +++++----
 openair2/RRC/LITE/rrc_eNB.c             | 11 +++++-
 targets/RT/USER/lte-softmodem.c         | 49 +++++++++++++++++++++----
 8 files changed, 81 insertions(+), 33 deletions(-)

diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index 3828a9be72..9e9e314ead 100755
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -3111,8 +3111,9 @@ void prach_procedures(PHY_VARS_eNB *phy_vars_eNB,uint8_t sched_subframe,uint8_t
       phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UE_timing_offset = preamble_delay_list[preamble_max]&0x1FFF; //limit to 13 (=11+2) bits
       //phy_vars_eNb->eNB_UE_stats[(uint32_t)UE_id].mode = PRACH;
       phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].sector = 0;
-      LOG_I(PHY,"[eNB %d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n",
+      LOG_I(PHY,"[eNB %d/%d][RAPROC] Frame %d, subframe %d Initiating RA procedure with preamble %d, energy %d.%d dB, delay %d\n",
             phy_vars_eNB->Mod_id,
+            phy_vars_eNB->CC_id,
             frame,
             subframe,
             preamble_max,
diff --git a/openair2/LAYER2/MAC/config.c b/openair2/LAYER2/MAC/config.c
index 5b3c8bd05e..61dea4889c 100644
--- a/openair2/LAYER2/MAC/config.c
+++ b/openair2/LAYER2/MAC/config.c
@@ -91,6 +91,7 @@ void ue_mac_reset(module_id_t module_idP,uint8_t eNB_index)
 int
 rrc_mac_config_req(
   module_id_t                      Mod_id,
+  int                              CC_id,
   eNB_flag_t                       eNB_flagP,
   rnti_t                           rntiP,
   uint8_t                          eNB_index,
@@ -125,7 +126,7 @@ rrc_mac_config_req(
                       )
 {
 
-  int i,CC_id=0;
+  int i;
 
   int UE_id = -1;
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_IN);
@@ -139,15 +140,15 @@ rrc_mac_config_req(
   } else {
     UE_id = find_UE_id(Mod_id, rntiP);
     if (physicalConfigDedicated == NULL) {
-      LOG_I(MAC,"[CONFIG][eNB %d] Configuring MAC/PHY\n",Mod_id);
+      LOG_I(MAC,"[CONFIG][eNB %d/%d] Configuring MAC/PHY\n", Mod_id, CC_id);
     } else {
-      LOG_I(MAC,"[CONFIG][eNB %d] Configuring MAC/PHY for UE %d (%x)\n",Mod_id,UE_id,UE_RNTI(Mod_id,UE_id));
+      LOG_I(MAC,"[CONFIG][eNB %d/%d] Configuring MAC/PHY for UE %d (%x)\n", Mod_id, CC_id, UE_id, UE_RNTI(Mod_id, UE_id));
     }
   }
 
   if (tdd_Config && SIwindowsize && SIperiod) {
     if (eNB_flagP == ENB_FLAG_YES) {
-      mac_xface->phy_config_sib1_eNB(Mod_id,0,tdd_Config,*SIwindowsize,*SIperiod);
+      mac_xface->phy_config_sib1_eNB(Mod_id, CC_id, tdd_Config, *SIwindowsize, *SIperiod);
     } else {
       mac_xface->phy_config_sib1_ue(Mod_id,0,eNB_index,tdd_Config,*SIwindowsize,*SIperiod);
     }
@@ -164,7 +165,7 @@ rrc_mac_config_req(
       LOG_I(MAC,"[CONFIG]pusch_config_common.groupAssignmentPUSCH = %ld\n",radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH);
       LOG_I(MAC,"[CONFIG]pusch_config_common.sequenceHoppingEnabled = %d\n",radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled);
       LOG_I(MAC,"[CONFIG]pusch_config_common.cyclicShift  = %ld\n",radioResourceConfigCommon->pusch_ConfigCommon.ul_ReferenceSignalsPUSCH.cyclicShift);
-      mac_xface->phy_config_sib2_eNB(Mod_id,0,radioResourceConfigCommon,ul_CarrierFreq,ul_Bandwidth,additionalSpectrumEmission,mbsfn_SubframeConfigList);
+      mac_xface->phy_config_sib2_eNB(Mod_id, CC_id, radioResourceConfigCommon, ul_CarrierFreq, ul_Bandwidth, additionalSpectrumEmission, mbsfn_SubframeConfigList);
     } else {
       UE_mac_inst[Mod_id].radioResourceConfigCommon = radioResourceConfigCommon;
       mac_xface->phy_config_sib2_ue(Mod_id,0,eNB_index,radioResourceConfigCommon,ul_CarrierFreq,ul_Bandwidth,additionalSpectrumEmission,mbsfn_SubframeConfigList);
@@ -260,7 +261,7 @@ rrc_mac_config_req(
 
   if (physicalConfigDedicated != NULL) {
     if (eNB_flagP==1) {
-      mac_xface->phy_config_dedicated_eNB(Mod_id,0,UE_RNTI(Mod_id,UE_id),physicalConfigDedicated);
+      mac_xface->phy_config_dedicated_eNB(Mod_id, CC_id, UE_RNTI(Mod_id, UE_id), physicalConfigDedicated);
     } else {
       mac_xface->phy_config_dedicated_ue(Mod_id,0,eNB_index,physicalConfigDedicated);
       UE_mac_inst[Mod_id].physicalConfigDedicated=physicalConfigDedicated; // for SR proc
diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c
index a1997db99e..d7cd57e2dc 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler.c
@@ -116,13 +116,14 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag,
   i = UE_list->head;
 
   while (i>=0) {
-
-    rnti = UE_RNTI(module_idP,i);
-    LOG_D(MAC,"UE %d: rnti %x (%p)\n",i,rnti,mac_xface->get_eNB_UE_stats(module_idP,0,rnti));
+    rnti = UE_RNTI(module_idP, i);
+    CC_id = UE_PCCID(module_idP, i);
+    LOG_D(MAC,"UE %d: rnti %x (%p)\n", i, rnti,
+          mac_xface->get_eNB_UE_stats(module_idP, CC_id, rnti));
     next_i= UE_list->next[i];
 
-    if (mac_xface->get_eNB_UE_stats(module_idP,0,rnti)==NULL) {
-      mac_remove_ue(module_idP,i,frameP, subframeP);
+    if (mac_xface->get_eNB_UE_stats(module_idP, CC_id, rnti)==NULL) {
+      mac_remove_ue(module_idP, i, frameP, subframeP);
     }
     i = next_i;
   }
diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h
index c9a00e09fe..671b81a683 100644
--- a/openair2/LAYER2/MAC/proto.h
+++ b/openair2/LAYER2/MAC/proto.h
@@ -700,6 +700,7 @@ unsigned char generate_dlsch_header(unsigned char *mac_header,
 
 /** \brief RRC Configuration primitive for PHY/MAC.  Allows configuration of PHY/MAC resources based on System Information (SI), RRCConnectionSetup and RRCConnectionReconfiguration messages.
 @param Mod_id Instance ID of eNB
+@param CC_id Component Carrier of the eNB
 @param eNB_flag Indicates if this is a eNB or UE configuration
 @param rntiP id of UE if this is an eNB configuration
 @param eNB_id Index of eNB if this is a UE configuration
@@ -720,6 +721,7 @@ unsigned char generate_dlsch_header(unsigned char *mac_header,
 @param pmch_InfoList pointer to PMCH_InfoList from MBSFNAreaConfiguration Message (MCCH Message)
 */
 int rrc_mac_config_req(module_id_t     module_idP,
+                       int             CC_id,
                        eNB_flag_t eNB_flag,
                        rnti_t          rntiP,
                        uint8_t         eNB_index,
diff --git a/openair2/RRC/LITE/defs.h b/openair2/RRC/LITE/defs.h
index 1bcf08a259..a0507c31a8 100644
--- a/openair2/RRC/LITE/defs.h
+++ b/openair2/RRC/LITE/defs.h
@@ -295,7 +295,9 @@ typedef struct HANDOVER_INFO_UE_s {
   PhysCellId_t targetCellId;
   uint8_t measFlag;
 } HANDOVER_INFO_UE;
+
 typedef struct eNB_RRC_UE_s {
+  uint8_t                            primaryCC_id;
 #ifdef Rel10
   SCellToAddMod_r10_t                sCell_config[2];
 #endif
@@ -317,7 +319,6 @@ typedef struct eNB_RRC_UE_s {
   MeasConfig_t*                      measConfig;
   HANDOVER_INFO*                     handover_info;
 
-
 #if defined(ENABLE_SECURITY)
   /* KeNB as derived from KASME received from EPC */
   uint8_t kenb[32];
@@ -326,8 +327,6 @@ typedef struct eNB_RRC_UE_s {
   e_SecurityAlgorithmConfig__cipheringAlgorithm     ciphering_algorithm;
   e_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm;
 
-
-
   uint8_t                            Status;
   rnti_t                             rnti;
   uint64_t                           random_ue_identity;
@@ -361,6 +360,7 @@ typedef struct eNB_RRC_UE_s {
 } eNB_RRC_UE_t;
 
 typedef uid_t ue_uid_t;
+
 typedef struct rrc_eNB_ue_context_s {
   /* Tree related data */
   RB_ENTRY(rrc_eNB_ue_context_s) entries;
@@ -370,7 +370,7 @@ typedef struct rrc_eNB_ue_context_s {
    */
   rnti_t         ue_id_rnti;
 
-  // an other key for protocol layers but should not be used as a key for RB tree
+  // another key for protocol layers but should not be used as a key for RB tree
   ue_uid_t       local_uid;
 
   /* UE id for initial connection to S1AP */
diff --git a/openair2/RRC/LITE/rrc_UE.c b/openair2/RRC/LITE/rrc_UE.c
index fbb76f63ea..42537701a3 100644
--- a/openair2/RRC/LITE/rrc_UE.c
+++ b/openair2/RRC/LITE/rrc_UE.c
@@ -802,7 +802,7 @@ rrc_ue_process_measConfig(
       }
     }
 
-    rrc_mac_config_req(ctxt_pP->module_id,ENB_FLAG_NO,0,eNB_index,
+    rrc_mac_config_req(ctxt_pP->module_id,0,ENB_FLAG_NO,0,eNB_index,
                        (RadioResourceConfigCommonSIB_t *)NULL,
                        (struct PhysicalConfigDedicated *)NULL,
 #ifdef Rel10
@@ -1092,7 +1092,7 @@ rrc_ue_process_radioResourceConfigDedicated(
 
           LOG_D(RRC, "[FRAME %05d][RRC_UE][MOD %02d][][--- MAC_CONFIG_REQ  (SRB1 eNB %d) --->][MAC_UE][MOD %02d][]\n",
                 ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);
-          rrc_mac_config_req(ctxt_pP->module_id,ENB_FLAG_NO,0,eNB_index,
+          rrc_mac_config_req(ctxt_pP->module_id,0,ENB_FLAG_NO,0,eNB_index,
                              (RadioResourceConfigCommonSIB_t *)NULL,
                              UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index],
 #ifdef Rel10
@@ -1150,7 +1150,7 @@ rrc_ue_process_radioResourceConfigDedicated(
                 ctxt_pP->module_id,
                 eNB_index,
                 ctxt_pP->module_id);
-          rrc_mac_config_req(ctxt_pP->module_id,ENB_FLAG_NO,0,eNB_index,
+          rrc_mac_config_req(ctxt_pP->module_id,0,ENB_FLAG_NO,0,eNB_index,
                              (RadioResourceConfigCommonSIB_t *)NULL,
                              UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index],
 #ifdef Rel10
@@ -1248,7 +1248,7 @@ rrc_ue_process_radioResourceConfigDedicated(
               radioResourceConfigDedicated->drb_ToAddModList->list.array[i]->drb_Identity,
               eNB_index,
               ctxt_pP->module_id);
-        rrc_mac_config_req(ctxt_pP->module_id,ENB_FLAG_NO,0,eNB_index,
+        rrc_mac_config_req(ctxt_pP->module_id,0,ENB_FLAG_NO,0,eNB_index,
                            (RadioResourceConfigCommonSIB_t *)NULL,
                            UE_rrc_inst[ctxt_pP->module_id].physicalConfigDedicated[eNB_index],
 #ifdef Rel10
@@ -1749,6 +1749,7 @@ rrc_ue_process_mobilityControlInfo(
 
   // Reset MAC and configure PHY
   rrc_mac_config_req(ctxt_pP->module_id,
+                     0,
                      ENB_FLAG_NO,
                      0,
                      eNB_index,
@@ -2564,7 +2565,7 @@ static int decode_SIB1( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_
   LOG_D( RRC, "[FRAME unknown][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB1 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
          ctxt_pP->module_id, eNB_index, ctxt_pP->module_id );
 
-  rrc_mac_config_req( ctxt_pP->module_id,ENB_FLAG_NO, 0, eNB_index,
+  rrc_mac_config_req(ctxt_pP->module_id, 0, ENB_FLAG_NO, 0, eNB_index,
                       (RadioResourceConfigCommonSIB_t *)NULL,
                       (struct PhysicalConfigDedicated *)NULL,
 #ifdef Rel10
@@ -3021,7 +3022,7 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in
       dump_sib2( UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index] );
       LOG_D( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB2 params  eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
              ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id );
-      rrc_mac_config_req( ctxt_pP->module_id, ENB_FLAG_NO, 0, eNB_index,
+      rrc_mac_config_req(ctxt_pP->module_id, 0, ENB_FLAG_NO, 0, eNB_index,
                           &UE_rrc_inst[ctxt_pP->module_id].sib2[eNB_index]->radioResourceConfigCommon,
                           (struct PhysicalConfigDedicated *)NULL,
 #ifdef Rel10
@@ -3157,7 +3158,7 @@ static int decode_SI( const protocol_ctxt_t* const ctxt_pP, const uint8_t eNB_in
       // adding here function to store necessary parameters for using in decode_MCCH_Message + maybe transfer to PHY layer
       LOG_D( RRC, "[FRAME %05"PRIu32"][RRC_UE][MOD %02"PRIu8"][][--- MAC_CONFIG_REQ (SIB13 params eNB %"PRIu8") --->][MAC_UE][MOD %02"PRIu8"][]\n",
              ctxt_pP->frame, ctxt_pP->module_id, eNB_index, ctxt_pP->module_id);
-      rrc_mac_config_req(ctxt_pP->module_id,ENB_FLAG_NO,0,eNB_index,
+      rrc_mac_config_req(ctxt_pP->module_id,0,ENB_FLAG_NO,0,eNB_index,
                          (RadioResourceConfigCommonSIB_t *)NULL,
                          (struct PhysicalConfigDedicated *)NULL,
                          (SCellToAddMod_r10_t *)NULL,
@@ -3605,7 +3606,7 @@ static void decode_MBSFNAreaConfiguration( module_id_t ue_mod_idP, uint8_t eNB_i
   LOG_D(RRC,"[UE %d] Frame %d : Number of MCH(s) in the MBSFN Sync Area %d  is %d\n",
         ue_mod_idP, frameP, mbsfn_sync_area, UE_rrc_inst[ue_mod_idP].mcch_message[eNB_index]->pmch_InfoList_r9.list.count);
   //  store to MAC/PHY necessary parameters for receiving MTCHs
-  rrc_mac_config_req(ue_mod_idP,ENB_FLAG_NO,0,eNB_index,
+  rrc_mac_config_req(ue_mod_idP,0,ENB_FLAG_NO,0,eNB_index,
                      (RadioResourceConfigCommonSIB_t *)NULL,
                      (struct PhysicalConfigDedicated *)NULL,
 #ifdef Rel10
diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c
index 37f2e0600f..b00ae05e1b 100644
--- a/openair2/RRC/LITE/rrc_eNB.c
+++ b/openair2/RRC/LITE/rrc_eNB.c
@@ -328,7 +328,7 @@ init_SI(
     LOG_D(RRC,
           PROTOCOL_RRC_CTXT_FMT" RRC_UE --- MAC_CONFIG_REQ (SIB1.tdd & SIB2 params) ---> MAC_UE\n",
           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP));
-    rrc_mac_config_req(ctxt_pP->module_id, ENB_FLAG_YES, 0, 0,
+    rrc_mac_config_req(ctxt_pP->module_id, CC_id, ENB_FLAG_YES, 0, 0,
                        (RadioResourceConfigCommonSIB_t *) &
                        eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].sib2->radioResourceConfigCommon,
                        (struct PhysicalConfigDedicated *)NULL,
@@ -425,7 +425,7 @@ init_MCCH(
 
   //  LOG_I(RRC, "DUY: serviceID is %d\n",eNB_rrc_inst[enb_mod_idP].mcch_message->pmch_InfoList_r9.list.array[0]->mbms_SessionInfoList_r9.list.array[0]->tmgi_r9.serviceId_r9.buf[2]);
   //  LOG_I(RRC, "DUY: session ID is %d\n",eNB_rrc_inst[enb_mod_idP].mcch_message->pmch_InfoList_r9.list.array[0]->mbms_SessionInfoList_r9.list.array[0]->sessionId_r9->buf[0]);
-  rrc_mac_config_req(enb_mod_idP, ENB_FLAG_YES, 0, 0,
+  rrc_mac_config_req(enb_mod_idP, CC_id, ENB_FLAG_YES, 0, 0,
                      (RadioResourceConfigCommonSIB_t *) NULL,
                      (struct PhysicalConfigDedicated *)NULL,
 #ifdef Rel10
@@ -2215,6 +2215,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
         ctxt_pP->frame, ctxt_pP->module_id, ue_context_pP->ue_context.rnti, ctxt_pP->module_id);
   rrc_mac_config_req(
     ctxt_pP->module_id,
+    ue_context_pP->ue_context.primaryCC_id,
     ENB_FLAG_YES,
     ue_context_pP->ue_context.rnti,
     0,
@@ -2785,6 +2786,7 @@ rrc_eNB_generate_RRCConnectionReconfiguration_handover(
   //pdcp_data_req (ctxt_pP->module_id, frameP, 1, (ue_mod_idP * NB_RB_MAX) + DCCH,rrc_eNB_mui++, 0, size, (char *) buffer, 1);
   rrc_mac_config_req(
     ctxt_pP->module_id,
+    ue_context_pP->ue_context.primaryCC_id,
     ENB_FLAG_YES,
     ue_context_pP->ue_context.rnti,
     0,
@@ -3050,6 +3052,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
 
           rrc_mac_config_req(
             ctxt_pP->module_id,
+            ue_context_pP->ue_context.primaryCC_id,
             ENB_FLAG_YES,
             ue_context_pP->ue_context.rnti,
             0,
@@ -3097,6 +3100,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
                 PROTOCOL_RRC_CTXT_UE_FMT" RRC_eNB --- MAC_CONFIG_REQ  (DRB) ---> MAC_eNB\n",
                 PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
           rrc_mac_config_req(ctxt_pP->module_id,
+                             ue_context_pP->ue_context.primaryCC_id,
                              ENB_FLAG_YES,
                              ue_context_pP->ue_context.rnti,
                              0,
@@ -3186,6 +3190,7 @@ rrc_eNB_generate_RRCConnectionSetup(
               PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
         rrc_mac_config_req(
           ctxt_pP->module_id,
+          ue_context_pP->ue_context.primaryCC_id,
           ENB_FLAG_YES,
           ue_context_pP->ue_context.rnti,
           0,
@@ -3630,6 +3635,8 @@ rrc_eNB_decode_ccch(
       send_msg(&S_rrc, msg_rrc_MR_attach_ind(ctxt_pP->module_id, Mac_id));
 #else
 
+      ue_context_p->ue_context.primaryCC_id = CC_id;
+
       //LG COMMENT Idx = (ue_mod_idP * NB_RB_MAX) + DCCH;
       Idx = DCCH;
       // SRB1
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 1e04764671..c021861713 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -992,6 +992,15 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB)
   }
 }
 
+/* mutex, cond and variable to serialize phy proc TX calls
+ * (this mechanism may be relaxed in the future for better
+ * performances)
+ */
+static struct {
+  pthread_mutex_t  mutex_phy_proc_tx;
+  pthread_cond_t   cond_phy_proc_tx;
+  volatile uint8_t phy_proc_CC_id;
+} sync_phy_proc[NUM_ENB_THREADS];
 
 /*!
  * \brief The transmit thread of eNB.
@@ -1092,16 +1101,35 @@ static void* eNB_thread_tx( void* param )
 
     if (oai_exit) break;
 
-    if ((((PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == TDD)&&
-          (subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx)==SF_DL))||
-         (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD))) {
+    if (((PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == TDD) &&
+         ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx) == SF_DL) ||
+          (subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx) == SF_S))) ||
+        (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD)) {
+      /* run PHY TX procedures the one after the other for all CCs to avoid race conditions
+       * (may be relaxed in the future for performance reasons)
+       */
+      if (pthread_mutex_lock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) {
+        LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
+        exit_fun("nothing to add");
+        break;
+      }
+      /* wait for our turn */
+      while (sync_phy_proc[proc->subframe].phy_proc_CC_id != proc->CC_id) {
+        pthread_cond_wait(&sync_phy_proc[proc->subframe].cond_phy_proc_tx,
+                          &sync_phy_proc[proc->subframe].mutex_phy_proc_tx);
+      }
 
       phy_procedures_eNB_TX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay, NULL );
 
-    }
-
-    if ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx) == SF_S)) {
-      phy_procedures_eNB_TX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay, NULL );
+      /* we're done, let the next one proceed */
+      sync_phy_proc[proc->subframe].phy_proc_CC_id++;
+      sync_phy_proc[proc->subframe].phy_proc_CC_id %= MAX_NUM_CCs;
+      pthread_cond_broadcast(&sync_phy_proc[proc->subframe].cond_phy_proc_tx);
+      if (pthread_mutex_unlock(&sync_phy_proc[proc->subframe].mutex_phy_proc_tx) != 0) {
+        LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc %d\n", proc->subframe);
+        exit_fun("nothing to add");
+        break;
+      }
     }
 
     do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] );
@@ -1376,6 +1404,13 @@ void init_eNB_proc(void)
     //    PHY_vars_eNB_g[0][CC_id]->proc[0].frame_tx = 1;
 #endif
   }
+
+  /* setup PHY proc TX sync mechanism */
+  for (i=0; i<NUM_ENB_THREADS; i++) {
+    pthread_mutex_init(&sync_phy_proc[i].mutex_phy_proc_tx, NULL);
+    pthread_cond_init(&sync_phy_proc[i].cond_phy_proc_tx, NULL);
+    sync_phy_proc[i].phy_proc_CC_id = 0;
+  }
 }
 
 /*!
-- 
GitLab