diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 46679c7f7c635ed1a61aa5b4416a16144d89e351..8a6c827ff80b5b9c3cda69dc0f977e331d603a39 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -256,6 +256,8 @@ typedef struct eNB_proc_t_s { int instance_cnt_asynch_rxtx; /// pthread structure for FH processing thread pthread_t pthread_FH; + /// pthread structure for eNB single processing thread + pthread_t pthread_single; /// pthread structure for asychronous RX/TX processing thread pthread_t pthread_asynch_rxtx; /// flag to indicate first RX acquisition @@ -264,12 +266,16 @@ typedef struct eNB_proc_t_s { int first_tx; /// pthread attributes for FH processing thread pthread_attr_t attr_FH; + /// pthread attributes for single eNB processing thread + pthread_attr_t attr_single; /// pthread attributes for prach processing thread pthread_attr_t attr_prach; /// pthread attributes for asynchronous RX thread pthread_attr_t attr_asynch_rxtx; /// scheduling parameters for FH thread struct sched_param sched_param_FH; + /// scheduling parameters for single eNB thread + struct sched_param sched_param_single; /// scheduling parameters for prach thread struct sched_param sched_param_prach; /// scheduling parameters for asynch_rxtx thread @@ -363,6 +369,7 @@ typedef struct PHY_VARS_eNB_s { eNB_proc_t proc; eNB_func_t node_function; eNB_timing_t node_timing; + int single_thread_flag; openair0_rf_map rf_map; int abstraction_flag; void (*do_prach)(struct PHY_VARS_eNB_s *eNB); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 164c21ce21b271bd9218ed73445fc1c88343b7aa..0623ae02d5db2dd1ed602dd2438717ddb0019494 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -2583,30 +2583,27 @@ void do_prach(PHY_VARS_eNB *eNB) { void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB){ - eNB_proc_t *proc = &eNB->proc; - LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - - const int subframe = proc->subframe_rx; - const int frame = proc->frame_rx; - + eNB_proc_t *proc = &eNB->proc; + LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + const int subframe = proc->subframe_rx; + const int frame = proc->frame_rx; + int offset = (proc == &eNB->proc.proc_rxtx[0]) ? 0 : 1; if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+(subframe&1), 1 ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_ENB+offset, proc->frame_rx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB+offset, proc->subframe_rx ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+offset, 1 ); start_meas(&eNB->phy_proc_rx); - - LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_common_RX(%d)\n",eNB->Mod_id,frame,subframe); if (eNB->fep) eNB->fep(eNB); if (eNB->do_prach) eNB->do_prach(eNB); - - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+(subframe&1), 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+offset, 0 ); } @@ -2623,11 +2620,12 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; const int subframe = proc->subframe_rx; - const int frame = proc->frame_rx; + const int frame = proc->frame_rx; + int offset = (proc == &eNB->proc.proc_rxtx[0]) ? 0 : 1; if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+(subframe&1), 1 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 1 ); start_meas(&eNB->phy_proc_rx); #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n",eNB->Mod_id,frame, subframe); @@ -3189,7 +3187,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const phy_procedures_emos_eNB_RX(subframe,eNB); #endif - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+(subframe&1), 0 ); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 0 ); stop_meas(&eNB->phy_proc_rx); diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index d55c2d058655d047be11ddef324104b5914aedf4..3d6bb61c0ea5573fdd12387b23e0fa49d5d18820 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -159,14 +159,14 @@ static struct { void exit_fun(const char* s); -void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *); +void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *,int); void stop_eNB(int nb_inst); -inline void thread_top_init(char *thread_name, - uint64_t runtime, - uint64_t deadline, - uint64_t period) { +static inline void thread_top_init(char *thread_name, + uint64_t runtime, + uint64_t deadline, + uint64_t period) { MSC_START_USE(); @@ -261,7 +261,7 @@ inline void thread_top_init(char *thread_name, } -inline void wait_sync(char *thread_name) { +static inline void wait_sync(char *thread_name) { printf( "waiting for sync (%s)\n",thread_name); pthread_mutex_lock( &sync_mutex ); @@ -275,7 +275,7 @@ inline void wait_sync(char *thread_name) { } -inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { +static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { struct timespec wait; @@ -302,7 +302,7 @@ inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *in return(0); } -inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) { +static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) { if (pthread_mutex_lock(mutex) != 0) { LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name); @@ -461,6 +461,11 @@ void proc_tx_high0(PHY_VARS_eNB *eNB, relaying_type_t r_type, PHY_VARS_RN *rn) { + int offset = proc == &eNB->proc.proc_rxtx[0] ? 0 : 1; + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+offset, proc->frame_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_rx ); + phy_procedures_eNB_TX(eNB,proc,r_type,rn); /* we're done, let the next one proceed */ @@ -483,6 +488,7 @@ void proc_tx_high(PHY_VARS_eNB *eNB, relaying_type_t r_type, PHY_VARS_RN *rn) { + // do PHY high proc_tx_high0(eNB,proc,r_type,rn); @@ -517,6 +523,11 @@ void proc_tx_rru_if4p5(PHY_VARS_eNB *eNB, uint32_t symbol_mask, symbol_mask_full; uint16_t packet_type; + int offset = proc == &eNB->proc.proc_rxtx[0] ? 0 : 1; + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+offset, proc->frame_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_rx ); + /// **** recv_IF4 of txdataF from RCC **** /// symbol_number = 0; symbol_mask = 0; @@ -532,6 +543,10 @@ void proc_tx_rru_if4p5(PHY_VARS_eNB *eNB, } void proc_tx_rru_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) { + int offset = proc == &eNB->proc.proc_rxtx[0] ? 0 : 1; + + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+offset, proc->frame_tx ); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+offset, proc->subframe_rx ); /// **** recv_IF5 of txdata from BBU **** /// recv_IF5(eNB, &proc->timestamp_tx, proc->subframe_tx, IF5_RRH_GW_DL); } @@ -563,6 +578,34 @@ int wait_CCs(eNB_rxtx_proc_t *proc) { return(0); } +static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_name) { + + start_meas(&softmodem_stats_rxtx_sf); + // **************************************** + // Common RX procedures subframe n + phy_procedures_eNB_common_RX(eNB); + + // UE-specific RX processing for subframe n + if (eNB->proc_uespec_rx) eNB->proc_uespec_rx(eNB, proc, no_relay ); + + // ***************************************** + // TX processing for subframe n+4 + // 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 (wait_CCs(proc)<0) return(-1); + + if (oai_exit) return(-1); + + if (eNB->proc_tx) eNB->proc_tx(eNB, proc, no_relay, NULL ); + + if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) return(-1); + + stop_meas( &softmodem_stats_rxtx_sf ); + + return(0); +} + /*! * \brief The RX UE-specific and TX thread of eNB. * \param param is a \ref eNB_proc_t structure which contains the info what to process. @@ -574,7 +617,6 @@ static void* eNB_thread_rxtx( void* param ) { eNB_rxtx_proc_t *proc = (eNB_rxtx_proc_t*)param; PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; - LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; char thread_name[100]; @@ -592,41 +634,12 @@ static void* eNB_thread_rxtx( void* param ) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 ); - start_meas( &softmodem_stats_rxtx_sf ); + if (oai_exit) break; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_ENB+(proc->subframe_rx&1), proc->frame_rx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB+(proc->subframe_rx&1), proc->subframe_rx ); - - // Common procedures - phy_procedures_eNB_common_RX(eNB); - // Do UE-specific RX processing for subframe n if any - if (eNB->proc_uespec_rx) eNB->proc_uespec_rx(eNB, proc, no_relay ); - - // TX processing for subframe n+4 - if (((fp->frame_type == TDD) && - ((subframe_select(fp,proc->subframe_tx) == SF_DL) || - (subframe_select(fp,proc->subframe_tx) == SF_S))) || - (fp->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 (wait_CCs(proc)<0) break; + if (rxtx(eNB,proc,thread_name) < 0) break; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+(proc->subframe_tx&1), proc->frame_tx ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+(proc->subframe_tx&1), proc->subframe_tx ); - - if (oai_exit) break; - - if (eNB->proc_tx) eNB->proc_tx(eNB, proc, no_relay, NULL ); - - } - - if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break; - - stop_meas( &softmodem_stats_rxtx_sf ); } // while !oai_exit VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); @@ -1239,6 +1252,84 @@ static void* eNB_thread_prach( void* param ) { return &eNB_thread_prach_status; } +static void* eNB_thread_single( void* param ) { + + static int eNB_thread_single_status; + + eNB_proc_t *proc = (eNB_proc_t*)param; + eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[0]; + PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; + + int subframe=0, frame=0; + + // set default return value + eNB_thread_single_status = 0; + + thread_top_init("eNB_thread_single",870000,1000000,1000000); + + wait_sync("eNB_thread_single"); + +#if defined(ENABLE_ITTI) + if (eNB->node_function < NGFI_RRU_IF5) + wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); +#endif + + // Start IF device if any + if (eNB->start_if) + if (eNB->start_if(eNB) != 0) + LOG_E(HW,"Could not start the IF device\n"); + + // Start RF device if any + if (eNB->start_rf) + if (eNB->start_rf(eNB) != 0) + LOG_E(HW,"Could not start the RF device\n"); + + // wakeup asnych_rxtx thread because the devices are ready at this point + pthread_mutex_lock(&proc->mutex_asynch_rxtx); + proc->instance_cnt_asynch_rxtx=0; + pthread_mutex_unlock(&proc->mutex_asynch_rxtx); + pthread_cond_signal(&proc->cond_asynch_rxtx); + + // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices + while (!oai_exit) { + + // these are local subframe/frame counters to check that we are in synch with the fronthaul timing. + // They are set on the first rx/tx in the underly FH routines. + if (subframe==9) { + subframe=0; + frame++; + frame&=1023; + } else { + subframe++; + } + + + // synchronization on FH interface, acquire signals/data and block + if (eNB->rx_fh) eNB->rx_fh(eNB,&frame,&subframe); + else AssertFatal(1==0, "No fronthaul interface : eNB->node_function %d",eNB->node_function); + + T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx)); + + // At this point, all information for subframe has been received on FH interface + // If this proc is to provide synchronization, do so + wakeup_slaves(proc); + + proc_rxtx->subframe_rx = proc->subframe_rx; + proc_rxtx->frame_rx = proc->frame_rx; + proc_rxtx->subframe_tx = (proc->subframe_rx+4)%10; + proc_rxtx->frame_tx = (proc->frame_rx < 6) ? proc->frame_rx : (proc->frame_rx+1); + + if (rxtx(eNB,proc_rxtx,"eNB_thread_single") < 0) break; + } + + + printf( "Exiting eNB_single thread \n"); + + eNB_thread_single_status = 0; + return &eNB_thread_single_status; + +} + void init_eNB_proc(int inst) { @@ -1247,40 +1338,14 @@ void init_eNB_proc(int inst) { PHY_VARS_eNB *eNB; eNB_proc_t *proc; eNB_rxtx_proc_t *proc_rxtx; - + pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL; + for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { eNB = PHY_vars_eNB_g[inst][CC_id]; LOG_I(PHY,"Initializing eNB %d CC_id %d (%s,%s),\n",inst,CC_id,eNB_functions[eNB->node_function],eNB_timing[eNB->node_timing]); proc = &eNB->proc; + proc_rxtx = proc->proc_rxtx; -#ifndef DEADLINE_SCHEDULER - /* - pthread_attr_init( &attr_eNB_proc_tx[CC_id][i] ); - if (pthread_attr_setstacksize( &attr_eNB_proc_tx[CC_id][i], 64 *PTHREAD_STACK_MIN ) != 0) - perror("[ENB_PROC_TX] setting thread stack size failed\n"); - - pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] ); - if (pthread_attr_setstacksize( &attr_eNB_proc_rx[CC_id][i], 64 * PTHREAD_STACK_MIN ) != 0) - perror("[ENB_PROC_RX] setting thread stack size failed\n"); - */ - // set the kernel scheduling policy and priority - proc_rxtx[0].sched_param_rxtx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc_rxtx[0].attr_rxtx, &proc_rxtx[0].sched_param_rxtx); - pthread_attr_setschedpolicy (&proc_rxtx[0].attr_rxtx, SCHED_FIFO); - proc_rxtx[1].sched_param_rxtx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc_rxtx[1].attr_rxtx, &proc_rxtx[1].sched_param_rxtx); - pthread_attr_setschedpolicy (&proc_rxtx[1].attr_rxtx, SCHED_FIFO); - - proc->sched_param_FH.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc->attr_FH, &proc->sched_param_FH); - pthread_attr_setschedpolicy (&proc->attr_FH, SCHED_FIFO); - - proc->sched_param_prach.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; - pthread_attr_setschedparam (&proc->attr_prach, &proc->sched_param_prach); - pthread_attr_setschedpolicy (&proc->attr_prach, SCHED_FIFO); - - printf("Setting OS scheduler to SCHED_FIFO for eNB [cc%d][thread%d] \n",CC_id, i); -#endif proc_rxtx[0].instance_cnt_rxtx = -1; proc_rxtx[1].instance_cnt_rxtx = -1; proc->instance_cnt_prach = -1; @@ -1293,31 +1358,38 @@ void init_eNB_proc(int inst) { pthread_mutex_init( &proc_rxtx[0].mutex_rxtx, NULL); pthread_mutex_init( &proc_rxtx[1].mutex_rxtx, NULL); - pthread_mutex_init( &proc->mutex_prach, NULL); - pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); pthread_cond_init( &proc_rxtx[0].cond_rxtx, NULL); pthread_cond_init( &proc_rxtx[1].cond_rxtx, NULL); + + pthread_mutex_init( &proc->mutex_prach, NULL); + pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL); + pthread_cond_init( &proc->cond_prach, NULL); pthread_cond_init( &proc->cond_FH, NULL); pthread_cond_init( &proc->cond_asynch_rxtx, NULL); #ifndef DEADLINE_SCHEDULER - pthread_create( &proc_rxtx[0].pthread_rxtx, &proc_rxtx[0].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[0] ); - pthread_create( &proc_rxtx[1].pthread_rxtx, &proc_rxtx[1].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[1] ); - pthread_create( &proc->pthread_FH, &proc->attr_FH, eNB_thread_FH, &eNB->proc ); - pthread_create( &proc->pthread_prach, &proc->attr_prach, eNB_thread_prach, &eNB->proc ); + attr0 = &proc_rxtx[0].attr_rxtx; + attr1 = &proc_rxtx[1].attr_rxtx; + attr_FH = &proc->attr_FH; + attr_prach = &proc->attr_prach; + attr_asynch = &proc->attr_asynch_rxtx; + attr_single = &proc->attr_single; +#endif + + if (eNB->single_thread_flag==0) { + pthread_create( &proc_rxtx[0].pthread_rxtx, attr0, eNB_thread_rxtx, &proc_rxtx[0] ); + pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, eNB_thread_rxtx, &proc_rxtx[1] ); + pthread_create( &proc->pthread_FH, attr_FH, eNB_thread_FH, &eNB->proc ); + } + else + pthread_create(&proc->pthread_single, attr_single, eNB_thread_single, &eNB->proc); + + pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, &eNB->proc ); if ((eNB->node_timing == synch_to_other) || (eNB->node_function == NGFI_RRU_IF5) || (eNB->node_function == NGFI_RRU_IF4p5)) - pthread_create( &proc->pthread_asynch_rxtx, &proc->attr_asynch_rxtx, eNB_thread_asynch_rxtx, &eNB->proc ); -#else - pthread_create( &proc_rxtx[0].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[0] ); - pthread_create( &proc_rxtx[1].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[1] ); - pthread_create( &proc->pthread_FH, NULL, eNB_thread_FH, &eNB->proc ); - pthread_create( &proc->pthread_prach, NULL, eNB_thread_prach, &eNB->proc ); - if (eNB->node_timing == synch_to_other) - pthread_create( &proc->pthread_asynch_rxtx, NULL, eNB_thread_asynch_rxtx, &eNB->proc ); - -#endif + pthread_create( &proc->pthread_asynch_rxtx, attr_asynch, eNB_thread_asynch_rxtx, &eNB->proc ); + char name[16]; snprintf( name, sizeof(name), "RXTX0 %d", i ); pthread_setname_np( proc_rxtx[0].pthread_rxtx, name ); @@ -1511,7 +1583,7 @@ extern void eNB_fep_rru_if5(PHY_VARS_eNB *eNB); extern void eNB_fep_full(PHY_VARS_eNB *eNB); extern void do_prach(PHY_VARS_eNB *eNB); -void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *eth_params) { +void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *eth_params,int single_thread_flag) { int CC_id; int inst; @@ -1524,6 +1596,7 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst eNB->node_function = node_function[CC_id]; eNB->node_timing = node_timing[CC_id]; eNB->abstraction_flag = 0; + eNB->single_thread_flag = single_thread_flag; LOG_I(PHY,"Initializing eNB %d CC_id %d : (%s,%s)\n",inst,CC_id,eNB_functions[node_function[CC_id]],eNB_timing[node_timing[CC_id]]); switch (node_function[CC_id]) { diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 4849e6380762982c3dfdbabe0e8c09428768b617..852147f46220f69e811eb4b71818334bf6568f8d 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -119,7 +119,7 @@ unsigned short config_frames[4] = {2,9,11,13}; // In lte-enb.c extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg); -extern void init_eNB(eNB_func_t *, eNB_timing_t *,int,eth_params_t *); +extern void init_eNB(eNB_func_t *, eNB_timing_t *,int,eth_params_t *,int); extern void stop_eNB(int); extern void kill_eNB_proc(void); @@ -163,14 +163,14 @@ uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, volatile int start_eNB = 0; volatile int start_UE = 0; #endif -volatile int oai_exit = 0; +volatile int oai_exit = 0; -static char UE_flag=0; +static char UE_flag=0; unsigned int mmapped_dma=0; -//static uint8_t eNB_id=0,UE_id=0; +int single_thread_flag=0; static char threequarter_fs=0; @@ -682,6 +682,7 @@ static void get_options (int argc, char **argv) LONG_OPTION_LOOPMEMORY, LONG_OPTION_PHYTEST, LONG_OPTION_MMAPPED_DMA, + LONG_OPTION_SINGLE_THREAD, #if T_TRACER LONG_OPTION_T_PORT, LONG_OPTION_T_NOWAIT, @@ -706,6 +707,7 @@ static void get_options (int argc, char **argv) {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY}, {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST}, {"mmapped-dma", no_argument, NULL, LONG_OPTION_MMAPPED_DMA}, + {"single-thread", no_argument, NULL, LONG_OPTION_SINGLE_THREAD}, #if T_TRACER {"T_port", required_argument, 0, LONG_OPTION_T_PORT}, {"T_nowait", no_argument, 0, LONG_OPTION_T_NOWAIT}, @@ -802,6 +804,10 @@ static void get_options (int argc, char **argv) case LONG_OPTION_MMAPPED_DMA: mmapped_dma = 1; break; + + case LONG_OPTION_SINGLE_THREAD: + single_thread_flag = 1; + break; #if T_TRACER case LONG_OPTION_T_PORT: { @@ -1773,7 +1779,7 @@ int main( int argc, char **argv ) // start the main thread if (UE_flag == 1) init_UE(1); - else init_eNB(node_function,node_timing,1,eth_params); + else init_eNB(node_function,node_timing,1,eth_params,single_thread_flag); // Sleep to allow all threads to setup number_of_cards = 1;