diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 2892fe9333d7b81c102f2d803d1d5f0215ae38a3..5556a2624d9569a2b898c1ffa5c9d90287be3256 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -37,6 +37,7 @@ * \note * \warning */ +#define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -118,6 +119,8 @@ unsigned short config_frames[4] = {2,9,11,13}; #define FRAME_PERIOD 100000000ULL #define DAQ_PERIOD 66667ULL +#define DEBUG_THREADS 1 + #define MY_RF_MODE (RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + DMAMODE_RX + DMAMODE_TX) #define RF_MODE_BASE (TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM) @@ -166,6 +169,11 @@ pthread_attr_t attr_dlsch_threads; struct sched_param sched_param_dlsch; #endif +pthread_attr_t attr_eNB_proc_tx[10]; +pthread_attr_t attr_eNB_proc_rx[10]; +struct sched_param sched_param_eNB_proc_tx[10]; +struct sched_param sched_param_eNB_proc_rx[10]; + #ifdef XFORMS static pthread_t thread2; //xforms #endif @@ -625,13 +633,65 @@ void *l2l1_task(void *arg) } #endif -static void * eNB_proc_thread(void *param) { + +void do_OFDM_mod(int subframe,PHY_VARS_eNB *phy_vars_eNB) { + + unsigned int aa,slot_offset, slot_offset_F; + int dummy_tx_b[7680*4] __attribute__((aligned(16))); + int i, tx_offset; + + slot_offset_F = (subframe<<1)* + (phy_vars_eNB->lte_frame_parms.ofdm_symbol_size)* + ((phy_vars_eNB->lte_frame_parms.Ncp==1) ? 6 : 7); + slot_offset = (subframe<<1)* + (phy_vars_eNB->lte_frame_parms.samples_per_tti>>1); + if ((subframe_select(&phy_vars_eNB->lte_frame_parms,subframe)==SF_DL)|| + ((subframe_select(&phy_vars_eNB->lte_frame_parms,subframe)==SF_S))) { + // LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot); + + for (aa=0; aa<phy_vars_eNB->lte_frame_parms.nb_antennas_tx; aa++) { + if (phy_vars_eNB->lte_frame_parms.Ncp == EXTENDED){ + PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F], + dummy_tx_b, + phy_vars_eNB->lte_frame_parms.log2_symbol_size, + 6, + phy_vars_eNB->lte_frame_parms.nb_prefix_samples, + phy_vars_eNB->lte_frame_parms.twiddle_ifft, + phy_vars_eNB->lte_frame_parms.rev, + CYCLIC_PREFIX); + } + else { + normal_prefix_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F], + dummy_tx_b, + 7, + &(phy_vars_eNB->lte_frame_parms)); + } +#ifdef EXMIMO + for (i=0; i<phy_vars_eNB->lte_frame_parms.samples_per_tti/2; i++) { + tx_offset = (int)slot_offset+time_offset[aa]+i; + if (tx_offset<0) + tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; + if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti)) + tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; + ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0]= + ((short*)dummy_tx_b)[2*i]<<4; + ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1]= + ((short*)dummy_tx_b)[2*i+1]<<4; + } +#endif //EXMIMO + } + } +} + + +int eNB_thread_tx_status[10]; +static void * eNB_thread_tx(void *param) { //unsigned long cpuid; eNB_proc_t *proc = (eNB_proc_t*)param; - int i,tx_offset; - int next_slot,last_slot; - RTIME time_in,time_out; + int i; + int subframe_tx; + // RTIME time_in,time_out; #ifdef RTAI RT_TASK *task; char task_name[8]; @@ -639,19 +699,27 @@ static void * eNB_proc_thread(void *param) { int dummy_tx_b[7680*4] __attribute__((aligned(16))); unsigned int aa,slot_offset,slot_offset_F,slot_offset_F2; +#if defined(ENABLE_ITTI) + /* Wait for eNB application initialization to be complete (eNB registration to MME) */ + wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); +#endif + #ifdef RTAI - sprintf(task_name,"eNB_proc %d",proc->subframe); + sprintf(task_name,"eNB_proc_TX %d",proc->subframe); task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF); if (task==NULL) { - LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc thread_index %d (%s)!!!!\n",proc->subframe,task_name); + LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_TX thread_index %d (%s)!!!!\n",proc->subframe,task_name); return 0; } else { - LOG_I(PHY,"[SCHED][eNB] dlsch_thread for process %d started with id %p\n", + LOG_I(PHY,"[SCHED][eNB] eNB TX thread %d started with id %p on CPU %d\n", proc->subframe, - task); + task,rtai_cpuid()); } +#else + LOG_I(PHY,"[SCHED][eNB] eNB TX thread %d started on CPU %d\n", + proc->subframe,sched_getcpu()); #endif mlockall(MCL_CURRENT | MCL_FUTURE); @@ -664,113 +732,196 @@ static void * eNB_proc_thread(void *param) { #endif - last_slot = ((proc->subframe<<1)-1)%20; - next_slot = ((proc->subframe<<1)+1)%20; + subframe_tx = (proc->subframe+1)%10; while (!oai_exit){ - vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC0+proc->subframe,0); - if (pthread_mutex_lock(&proc->mutex) != 0) { - LOG_E(PHY,"[SCHED][eNB] error locking mutex for eNB proc %d\n",proc->subframe); + vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe),0); + + + // LOG_I(PHY,"Locking mutex for eNB proc %d (IC %d,mutex %p)\n",proc->subframe,proc->instance_cnt,&proc->mutex); + if (pthread_mutex_lock(&proc->mutex_tx) != 0) { + LOG_E(PHY,"[SCHED][eNB] error locking mutex for eNB TX proc %d\n",proc->subframe); } else { - while (proc->instance_cnt < 0) { - pthread_cond_wait(&proc->cond,&proc->mutex); + while (proc->instance_cnt_tx < 0) { + // LOG_I(PHY,"Waiting and unlocking mutex for eNB proc %d (IC %d,lock %d)\n",proc->subframe,proc->instance_cnt,pthread_mutex_trylock(&proc->mutex)); + + pthread_cond_wait(&proc->cond_tx,&proc->mutex_tx); } - - if (pthread_mutex_unlock(&proc->mutex) != 0) { - LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB proc %d\n",proc->subframe); + // LOG_I(PHY,"Waking up and unlocking mutex for eNB proc %d\n",proc->subframe); + if (pthread_mutex_unlock(&proc->mutex_tx) != 0) { + LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n",proc->subframe); } } - vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC0+proc->subframe,1); + vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe),1); + vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_ENB, proc->frame_tx); + vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_ENB, proc->subframe*2); + if (oai_exit) break; - if ((((PHY_vars_eNB_g[0]->lte_frame_parms.frame_type == TDD)&&(subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_DL))|| + if ((((PHY_vars_eNB_g[0]->lte_frame_parms.frame_type == TDD)&&(subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,subframe_tx)==SF_DL))|| (PHY_vars_eNB_g[0]->lte_frame_parms.frame_type == FDD))) { -#ifdef Rel10 - if (phy_procedures_RN_eNB_TX(last_slot, next_slot, no_relay) != 0 ) -#endif - phy_procedures_eNB_TX(next_slot,PHY_vars_eNB_g[0],0,no_relay,NULL); + phy_procedures_eNB_TX(subframe_tx,PHY_vars_eNB_g[0],0,no_relay,NULL); } - if ((((PHY_vars_eNB_g[0]->lte_frame_parms.frame_type == TDD )&&(subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,last_slot>>1)==SF_UL)) || - (PHY_vars_eNB_g[0]->lte_frame_parms.frame_type == FDD))){ - phy_procedures_eNB_RX(last_slot,PHY_vars_eNB_g[0],0,no_relay); + if ((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,subframe_tx)==SF_S)) { + phy_procedures_eNB_TX(subframe_tx,PHY_vars_eNB_g[0],0,no_relay,NULL); } - if ((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_S)) { -#ifdef Rel10 - if (phy_procedures_RN_eNB_TX(last_slot, next_slot, no_relay) != 0 ) -#endif - phy_procedures_eNB_TX(next_slot,PHY_vars_eNB_g[0],0,no_relay,NULL); - } - if ((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,last_slot>>1)==SF_S)){ - phy_procedures_eNB_S_RX(last_slot,PHY_vars_eNB_g[0],0,no_relay); + do_OFDM_mod(subframe_tx,PHY_vars_eNB_g[0]); + + if (pthread_mutex_lock(&proc->mutex_tx) != 0) { + printf("[openair][SCHED][eNB] error locking mutex for eNB TX proc %d\n",proc->subframe); } + else { + proc->instance_cnt_tx--; + if (pthread_mutex_unlock(&proc->mutex_tx) != 0) { + printf("[openair][SCHED][eNB] error unlocking mutex for eNB TX proc %d\n",proc->subframe); + } + } + + proc->frame_tx++; + if (proc->frame_tx==1024) + proc->frame_tx=0; } + vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe),0); +#ifdef HARD_RT + rt_make_soft_real_time(); +#endif - slot_offset_F = (next_slot)* - (PHY_vars_eNB_g[0]->lte_frame_parms.ofdm_symbol_size)* - ((PHY_vars_eNB_g[0]->lte_frame_parms.Ncp==1) ? 6 : 7); - slot_offset = (next_slot)* - (PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti>>1); - slot_offset_F2 = (next_slot+1)* - (PHY_vars_eNB_g[0]->lte_frame_parms.ofdm_symbol_size)* - ((PHY_vars_eNB_g[0]->lte_frame_parms.Ncp==1) ? 6 : 7); - - if ((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_DL)|| - ((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_S))) { - // LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot); - - for (aa=0; aa<PHY_vars_eNB_g[0]->lte_frame_parms.nb_antennas_tx; aa++) { - if (PHY_vars_eNB_g[0]->lte_frame_parms.Ncp == 1) { - PHY_ofdm_mod(&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F], - dummy_tx_b, - PHY_vars_eNB_g[0]->lte_frame_parms.log2_symbol_size, - 6, - PHY_vars_eNB_g[0]->lte_frame_parms.nb_prefix_samples, - PHY_vars_eNB_g[0]->lte_frame_parms.twiddle_ifft, - PHY_vars_eNB_g[0]->lte_frame_parms.rev, - CYCLIC_PREFIX); - PHY_ofdm_mod(&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F2], - dummy_tx_b+(PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti>>1), - PHY_vars_eNB_g[0]->lte_frame_parms.log2_symbol_size, - 6, - PHY_vars_eNB_g[0]->lte_frame_parms.nb_prefix_samples, - PHY_vars_eNB_g[0]->lte_frame_parms.twiddle_ifft, - PHY_vars_eNB_g[0]->lte_frame_parms.rev, - CYCLIC_PREFIX); +#ifdef DEBUG_THREADS + printf("Exiting eNB thread TX %d\n",proc->subframe); +#endif + // clean task +#ifdef RTAI + rt_task_delete(task); +#else + eNB_thread_tx_status[proc->subframe]=0; + pthread_exit(&eNB_thread_tx_status[proc->subframe]); +#endif + +#ifdef DEBUG_THREADS + printf("Exiting eNB TX thread %d\n",proc->subframe); +#endif +} + +int eNB_thread_rx_status[10]; +static void * eNB_thread_rx(void *param) { + + //unsigned long cpuid; + eNB_proc_t *proc = (eNB_proc_t*)param; + int i; + int subframe_rx; + // RTIME time_in,time_out; +#ifdef RTAI + RT_TASK *task; + char task_name[8]; +#endif + +#if defined(ENABLE_ITTI) + /* Wait for eNB application initialization to be complete (eNB registration to MME) */ + wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); +#endif + +#ifdef RTAI + sprintf(task_name,"eNB_proc_RX %d",proc->subframe); + task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF); + + if (task==NULL) { + LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_RX thread_index %d (%s)!!!!\n",proc->subframe,task_name); + return 0; + } + else { + LOG_I(PHY,"[SCHED][eNB] eNB RX thread %d started with id %p on CPU %d\n", + proc->subframe, + task,rtai_cpuid()); + } +#else + LOG_I(PHY,"[SCHED][eNB] eNB RX thread %d started on CPU %d\n", + proc->subframe,sched_getcpu()); +#endif + + mlockall(MCL_CURRENT | MCL_FUTURE); + + //rt_set_runnable_on_cpuid(task,1); + //cpuid = rtai_cpuid(); + +#ifdef HARD_RT + rt_make_hard_real_time(); +#endif + + + subframe_rx = (proc->subframe+9)%10; + + while (!oai_exit){ + + vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe),0); + + + // LOG_I(PHY,"Locking mutex for eNB proc %d (IC %d,mutex %p)\n",proc->subframe,proc->instance_cnt,&proc->mutex); + if (pthread_mutex_lock(&proc->mutex_rx) != 0) { + LOG_E(PHY,"[SCHED][eNB] error locking mutex for eNB RX proc %d\n",proc->subframe); + } + else { + + while (proc->instance_cnt_rx < 0) { + // LOG_I(PHY,"Waiting and unlocking mutex for eNB proc %d (IC %d,lock %d)\n",proc->subframe,proc->instance_cnt,pthread_mutex_trylock(&proc->mutex)); + + pthread_cond_wait(&proc->cond_rx,&proc->mutex_rx); } -#ifdef EXMIMO - for (i=0; i<PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti; i++) { - tx_offset = (int)slot_offset+time_offset[aa]+i; - if (tx_offset<0) - tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti; - if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti)) - tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti; - ((short*)&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0]= - ((short*)dummy_tx_b)[2*i]<<4; - ((short*)&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1]= - ((short*)dummy_tx_b)[2*i+1]<<4; + // LOG_I(PHY,"Waking up and unlocking mutex for eNB proc %d\n",proc->subframe); + if (pthread_mutex_unlock(&proc->mutex_rx) != 0) { + LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n",proc->subframe); } -#endif //EXMIMO } - } - if (pthread_mutex_lock(&proc->mutex) != 0) { - msg("[openair][SCHED][eNB] error locking mutex for eNB proc %d\n",proc->subframe); + vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe),1); + + if (oai_exit) break; + + if ((((PHY_vars_eNB_g[0]->lte_frame_parms.frame_type == TDD )&&(subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,subframe_rx)==SF_UL)) || + (PHY_vars_eNB_g[0]->lte_frame_parms.frame_type == FDD))){ + phy_procedures_eNB_RX(subframe_rx,PHY_vars_eNB_g[0],0,no_relay); + } + if ((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,subframe_rx)==SF_S)){ + phy_procedures_eNB_S_RX(subframe_rx,PHY_vars_eNB_g[0],0,no_relay); + } + + if (pthread_mutex_lock(&proc->mutex_rx) != 0) { + printf("[openair][SCHED][eNB] error locking mutex for eNB RX proc %d\n",proc->subframe); } else { - proc->instance_cnt--; + proc->instance_cnt_rx--; - if (pthread_mutex_unlock(&proc->mutex) != 0) { - msg("[openair][SCHED][eNB] error unlocking mutex for eNB proc %d\n",proc->subframe); + if (pthread_mutex_unlock(&proc->mutex_rx) != 0) { + printf("[openair][SCHED][eNB] error unlocking mutex for eNB RX proc %d\n",proc->subframe); } } + + proc->frame_rx++; + if (proc->frame_rx==1024) + proc->frame_rx=0; + } + vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe),0); #ifdef HARD_RT - rt_make_soft_real_time(); + rt_make_soft_real_time(); +#endif + +#ifdef DEBUG_THREADS + printf("Exiting eNB thread RX %d\n",proc->subframe); +#endif + // clean task +#ifdef RTAI + rt_task_delete(task); +#else + eNB_thread_rx_status[proc->subframe]=0; + pthread_exit(&eNB_thread_rx_status[proc->subframe]); #endif +#ifdef DEBUG_THREADS + printf("Exiting eNB RX thread %d\n",proc->subframe); +#endif } @@ -779,29 +930,80 @@ void init_eNB_proc() { int i; + + for (i=0;i<10;i++) { - PHY_vars_eNB_g[0]->proc[i].instance_cnt=0; + pthread_attr_init (&attr_eNB_proc_tx[i]); + pthread_attr_setstacksize(&attr_eNB_proc_tx[i],OPENAIR_THREAD_STACK_SIZE); + //attr_dlsch_threads.priority = 1; + sched_param_eNB_proc_tx[i].sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&attr_eNB_proc_tx[i], &sched_param_eNB_proc_tx); + pthread_attr_setschedpolicy (&attr_eNB_proc_tx[i], SCHED_FIFO); + + pthread_attr_init (&attr_eNB_proc_rx[i]); + pthread_attr_setstacksize(&attr_eNB_proc_rx[i],OPENAIR_THREAD_STACK_SIZE); + //attr_dlsch_threads.priority = 1; + sched_param_eNB_proc_rx[i].sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; + pthread_attr_setschedparam (&attr_eNB_proc_rx[i], &sched_param_eNB_proc_rx); + pthread_attr_setschedpolicy (&attr_eNB_proc_rx[i], SCHED_FIFO); + + PHY_vars_eNB_g[0]->proc[i].instance_cnt_tx=-1; + PHY_vars_eNB_g[0]->proc[i].instance_cnt_rx=-1; PHY_vars_eNB_g[0]->proc[i].subframe=i; - pthread_mutex_init(&PHY_vars_eNB_g[0]->proc[i].mutex,NULL); - pthread_cond_init(&PHY_vars_eNB_g[0]->proc[i].cond,NULL); - pthread_create(&PHY_vars_eNB_g[0]->proc[i].pthread,NULL,eNB_proc_thread,(void*)&PHY_vars_eNB_g[0]->proc[i]); + pthread_mutex_init(&PHY_vars_eNB_g[0]->proc[i].mutex_tx,NULL); + pthread_mutex_init(&PHY_vars_eNB_g[0]->proc[i].mutex_rx,NULL); + pthread_cond_init(&PHY_vars_eNB_g[0]->proc[i].cond_tx,NULL); + pthread_cond_init(&PHY_vars_eNB_g[0]->proc[i].cond_rx,NULL); + pthread_create(&PHY_vars_eNB_g[0]->proc[i].pthread_tx,NULL,eNB_thread_tx,(void*)&PHY_vars_eNB_g[0]->proc[i]); + pthread_create(&PHY_vars_eNB_g[0]->proc[i].pthread_rx,NULL,eNB_thread_rx,(void*)&PHY_vars_eNB_g[0]->proc[i]); } } void kill_eNB_proc() { int i; + int *status_tx,*status_rx; for (i=0;i<10;i++) { - pthread_join(PHY_vars_eNB_g[0]->proc[i].pthread,NULL); - pthread_mutex_destroy(&PHY_vars_eNB_g[0]->proc[i].mutex); - pthread_cond_destroy(&PHY_vars_eNB_g[0]->proc[i].cond); + +#ifdef DEBUG_THREADS + printf("Killing TX thread %d\n",i); +#endif + PHY_vars_eNB_g[0]->proc[i].instance_cnt_tx=0; + pthread_cond_signal(&PHY_vars_eNB_g[0]->proc[i].cond_tx); +#ifdef DEBUG_THREADS + printf("Joining eNB TX thread %d...",i); +#endif + pthread_join(PHY_vars_eNB_g[0]->proc[i].pthread_tx,(void**)status_tx); +#ifdef DEBUG_THREADS + if (status_tx) printf("status %d...",*status_tx); +#endif +#ifdef DEBUG_THREADS + printf("Killing RX thread %d\n",i); +#endif + PHY_vars_eNB_g[0]->proc[i].instance_cnt_rx=0; + pthread_cond_signal(&PHY_vars_eNB_g[0]->proc[i].cond_rx); +#ifdef DEBUG_THREADS + printf("Joining eNB RX thread %d...",i); +#endif + pthread_join(PHY_vars_eNB_g[0]->proc[i].pthread_rx,(void**)status_rx); +#ifdef DEBUG_THREADS + if (status_rx) printf("status %d...",*status_rx); +#endif + pthread_mutex_destroy(&PHY_vars_eNB_g[0]->proc[i].mutex_tx); + pthread_mutex_destroy(&PHY_vars_eNB_g[0]->proc[i].mutex_rx); + pthread_cond_destroy(&PHY_vars_eNB_g[0]->proc[i].cond_tx); + pthread_cond_destroy(&PHY_vars_eNB_g[0]->proc[i].cond_rx); } } + + /* This is the main eNB thread. */ +int eNB_thread_status; + static void *eNB_thread(void *arg) { #ifdef RTAI @@ -809,7 +1011,6 @@ static void *eNB_thread(void *arg) #endif unsigned char slot=0,last_slot, next_slot; int hw_slot,frame=0; - unsigned int aa,slot_offset, slot_offset_F; int diff; int delay_cnt; RTIME time_in, time_diff; @@ -829,7 +1030,10 @@ static void *eNB_thread(void *arg) if (!oai_exit) { #ifdef RTAI - LOG_D(HW,"Started eNB thread (id %p)\n",task); + LOG_D(HW,"[SCHED][eNB] Started eNB thread (id %p) on CPU %d\n",task,rtai_cpuid()); +#else + LOG_I(HW,"[SCHED][eNB] Started eNB thread on CPU %d\n", + sched_getcpu()); #endif #ifdef HARD_RT @@ -843,211 +1047,191 @@ static void *eNB_thread(void *arg) timing_info.time_avg = 0; timing_info.n_samples = 0; - while (!oai_exit) - { - hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; - //LOG_D(HW,"eNB frame %d, time %llu: slot %d, hw_slot %d (mbox %d)\n",frame,rt_get_time_ns(),slot,hw_slot,((unsigned int *)DAQ_MBOX)[0]); - //this is the mbox counter where we should be - //mbox_target = ((((slot+1)%20)*15+1)>>1)%150; - mbox_target = mbox_bounds[slot]; - //this is the mbox counter where we are - mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0]; - //this is the time we need to sleep in order to synchronize with the hw (in multiples of DAQ_PERIOD) - if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround + while (!oai_exit) { + hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; + // LOG_D(HW,"eNB frame %d, time %llu: slot %d, hw_slot %d (mbox %d)\n",frame,rt_get_time_ns(),slot,hw_slot,((unsigned int *)DAQ_MBOX)[0]); + //this is the mbox counter where we should be + //mbox_target = ((((slot+1)%20)*15+1)>>1)%150; + mbox_target = mbox_bounds[slot]; + //this is the mbox counter where we are + mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0]; + //this is the time we need to sleep in order to synchronize with the hw (in multiples of DAQ_PERIOD) + if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround + diff = 150-mbox_current+mbox_target; + else if ((mbox_current<15) && (mbox_target>=135)) + diff = -150+mbox_target-mbox_current; + else + diff = mbox_target - mbox_current; + + if (((slot%2==0) && (diff < (-14))) || ((slot%2==1) && (diff < (-7)))) { + // at the eNB, even slots have double as much time since most of the processing is done here and almost nothing in odd slots + LOG_D(HW,"eNB Frame %d, time %llu: missed slot, proceeding with next one (slot %d, hw_slot %d, diff %d)\n",frame, rt_get_time_ns(), slot, hw_slot, diff); + slot++; + if (frame > 0) { + exit_fun("[HW][eNB] missed slot"); + } + if (slot==20){ + slot=0; + frame++; + } + continue; + } + if (diff>8) + LOG_D(HW,"eNB Frame %d, time %llu: skipped slot, waiting for hw to catch up (slot %d, hw_slot %d, mbox_current %d, mbox_target %d, diff %d)\n",frame, rt_get_time_ns(), slot, hw_slot, mbox_current, mbox_target, diff); + + vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *((volatile unsigned int *) openair0_exmimo_pci[card].rxcnt_ptr[0])); + vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DIFF, diff); + + delay_cnt = 0; + while ((diff>0) && (!oai_exit)) { + time_in = rt_get_time_ns(); + //LOG_D(HW,"eNB Frame %d delaycnt %d : hw_slot %d (%d), slot %d, (slot+1)*15=%d, diff %d, time %llu\n",frame,delay_cnt,hw_slot,((unsigned int *)DAQ_MBOX)[0],slot,(((slot+1)*15)>>1),diff,time_in); + //LOG_D(HW,"eNB Frame %d, time %llu: sleeping for %llu (slot %d, hw_slot %d, diff %d, mbox %d, delay_cnt %d)\n", frame, time_in, diff*DAQ_PERIOD,slot,hw_slot,diff,((volatile unsigned int *)DAQ_MBOX)[0],delay_cnt); + vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1); + ret = rt_sleep_ns(diff*DAQ_PERIOD); + vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,0); + vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *((volatile unsigned int *) openair0_exmimo_pci[card].rxcnt_ptr[0])); + if (ret) + LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in); + hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; + //LOG_D(HW,"eNB Frame %d : hw_slot %d, time %llu\n",frame,hw_slot,rt_get_time_ns()); + delay_cnt++; + if (delay_cnt == 10) { + LOG_D(HW,"eNB Frame %d: HW stopped ... \n",frame); + exit_fun("[HW][eNB] HW stopped"); + } + mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0]; + if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround diff = 150-mbox_current+mbox_target; - else if ((mbox_current<15) && (mbox_target>=135)) + else if ((mbox_current<15) && (mbox_target>=135)) diff = -150+mbox_target-mbox_current; - else + else diff = mbox_target - mbox_current; + } + + if (oai_exit) break; - if (((slot%2==0) && (diff < (-14))) || ((slot%2==1) && (diff < (-7)))) { - // at the eNB, even slots have double as much time since most of the processing is done here and almost nothing in odd slots - LOG_D(HW,"eNB Frame %d, time %llu: missed slot, proceeding with next one (slot %d, hw_slot %d, diff %d)\n",frame, rt_get_time_ns(), slot, hw_slot, diff); - slot++; - if (frame > 0) { - exit_fun("[HW][eNB] missed slot"); - } - if (slot==20){ - slot=0; - frame++; - } - continue; - } - if (diff>8) - LOG_D(HW,"eNB Frame %d, time %llu: skipped slot, waiting for hw to catch up (slot %d, hw_slot %d, mbox_current %d, mbox_target %d, diff %d)\n",frame, rt_get_time_ns(), slot, hw_slot, mbox_current, mbox_target, diff); - - delay_cnt = 0; - while ((diff>0) && (!oai_exit)) - { - time_in = rt_get_time_ns(); - //LOG_D(HW,"eNB Frame %d delaycnt %d : hw_slot %d (%d), slot %d, (slot+1)*15=%d, diff %d, time %llu\n",frame,delay_cnt,hw_slot,((unsigned int *)DAQ_MBOX)[0],slot,(((slot+1)*15)>>1),diff,time_in); - //LOG_D(HW,"eNB Frame %d, time %llu: sleeping for %llu (slot %d, hw_slot %d, diff %d, mbox %d, delay_cnt %d)\n", frame, time_in, diff*DAQ_PERIOD,slot,hw_slot,diff,((volatile unsigned int *)DAQ_MBOX)[0],delay_cnt); - ret = rt_sleep_ns(diff*DAQ_PERIOD); - if (ret) - LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in); - hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; - //LOG_D(HW,"eNB Frame %d : hw_slot %d, time %llu\n",frame,hw_slot,rt_get_time_ns()); - delay_cnt++; - if (delay_cnt == 10) - { - LOG_D(HW,"eNB Frame %d: HW stopped ... \n",frame); - exit_fun("[HW][eNB] HW stopped"); - } - mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0]; - if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround - diff = 150-mbox_current+mbox_target; - else if ((mbox_current<15) && (mbox_target>=135)) - diff = -150+mbox_target-mbox_current; - else - diff = mbox_target - mbox_current; - } - - last_slot = (slot)%LTE_SLOTS_PER_FRAME; - if (last_slot <0) - last_slot+=20; - next_slot = (slot+2)%LTE_SLOTS_PER_FRAME; - - //PHY_vars_eNB_g[0]->frame = frame; - if (frame>5) - { - /* - if (frame%100==0) - LOG_D(HW,"frame %d (%d), slot %d, hw_slot %d, next_slot %d (before): DAQ_MBOX %d\n",frame, PHY_vars_eNB_g[0]->frame, slot, hw_slot,next_slot,DAQ_MBOX[0]); - */ - - //if (PHY_vars_eNB_g[0]->frame>5) { - timing_info.time_last = timing_info.time_now; - timing_info.time_now = rt_get_time_ns(); - - if (timing_info.n_samples>0) { - time_diff = timing_info.time_now - timing_info.time_last; - if (time_diff < timing_info.time_min) - timing_info.time_min = time_diff; - if (time_diff > timing_info.time_max) - timing_info.time_max = time_diff; - timing_info.time_avg += time_diff; + last_slot = (slot)%LTE_SLOTS_PER_FRAME; + if (last_slot <0) + last_slot+=20; + next_slot = (slot+2)%LTE_SLOTS_PER_FRAME; + + //PHY_vars_eNB_g[0]->frame = frame; + if (frame>5) { + /* + if (frame%100==0) + LOG_D(HW,"frame %d (%d), slot %d, hw_slot %d, next_slot %d (before): DAQ_MBOX %d\n",frame, PHY_vars_eNB_g[0]->frame, slot, hw_slot,next_slot,DAQ_MBOX[0]); + */ + + //if (PHY_vars_eNB_g[0]->frame>5) { + timing_info.time_last = timing_info.time_now; + timing_info.time_now = rt_get_time_ns(); + + if (timing_info.n_samples>0) { + time_diff = timing_info.time_now - timing_info.time_last; + if (time_diff < timing_info.time_min) + timing_info.time_min = time_diff; + if (time_diff > timing_info.time_max) + timing_info.time_max = time_diff; + timing_info.time_avg += time_diff; + } + + timing_info.n_samples++; + /* + if ((timing_info.n_samples%2000)==0) { + LOG_D(HW,"frame %d (%d), slot %d, hw_slot %d: diff=%llu, min=%llu, max=%llu, avg=%llu (n_samples %d)\n", + frame, PHY_vars_eNB_g[0]->frame, slot, hw_slot,time_diff, + timing_info.time_min,timing_info.time_max,timing_info.time_avg/timing_info.n_samples,timing_info.n_samples); + timing_info.n_samples = 0; + timing_info.time_avg = 0; + } + */ + //} + + if (multi_thread == 0) { + phy_procedures_eNB_lte (((slot+1)%20)>>1, PHY_vars_eNB_g[0], 0, no_relay,NULL); + do_OFDM_mod(((slot+1)%20)>>1,PHY_vars_eNB_g[0]); + } + else { // multi-thread > 0 + if ((slot&1) == 0) { + sf = ((slot>>1)+1)%10; + // LOG_I(PHY,"[eNB] Multithread slot %d (IC %d)\n",slot,PHY_vars_eNB_g[0]->proc[sf].instance_cnt); + + if (pthread_mutex_lock(&PHY_vars_eNB_g[0]->proc[sf].mutex_tx) != 0) { + LOG_E(PHY,"[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n",sf,PHY_vars_eNB_g[0]->proc[sf].instance_cnt_tx); } - - timing_info.n_samples++; - /* - if ((timing_info.n_samples%2000)==0) { - LOG_D(HW,"frame %d (%d), slot %d, hw_slot %d: diff=%llu, min=%llu, max=%llu, avg=%llu (n_samples %d)\n", - frame, PHY_vars_eNB_g[0]->frame, slot, hw_slot,time_diff, - timing_info.time_min,timing_info.time_max,timing_info.time_avg/timing_info.n_samples,timing_info.n_samples); - timing_info.n_samples = 0; - timing_info.time_avg = 0; - } - */ - //} - - if (fs4_test==0) - { - if (multi_thread == 0) { - phy_procedures_eNB_lte ((slot+1)>>1, PHY_vars_eNB_g[0], 0, no_relay,NULL); - slot_offset_F = (next_slot)* - (PHY_vars_eNB_g[0]->lte_frame_parms.ofdm_symbol_size)* - ((PHY_vars_eNB_g[0]->lte_frame_parms.Ncp==1) ? 6 : 7); - slot_offset = (next_slot)* - (PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti>>1); - if ((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_DL)|| - ((subframe_select(&PHY_vars_eNB_g[0]->lte_frame_parms,next_slot>>1)==SF_S))) - { - // LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot); - - for (aa=0; aa<PHY_vars_eNB_g[0]->lte_frame_parms.nb_antennas_tx; aa++) - { - if (PHY_vars_eNB_g[0]->lte_frame_parms.Ncp == 1) - { - PHY_ofdm_mod(&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F], -#ifdef BIT8_TX - &PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][slot_offset>>1], -#else - dummy_tx_buffer,//&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][slot_offset], -#endif - PHY_vars_eNB_g[0]->lte_frame_parms.log2_symbol_size, - 6, - PHY_vars_eNB_g[0]->lte_frame_parms.nb_prefix_samples, - PHY_vars_eNB_g[0]->lte_frame_parms.twiddle_ifft, - PHY_vars_eNB_g[0]->lte_frame_parms.rev, - CYCLIC_PREFIX); - } - else - { - normal_prefix_mod(&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F], -#ifdef BIT8_TX - &PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][slot_offset>>1], -#else - dummy_tx_buffer,//&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][slot_offset], -#endif - 7, - &(PHY_vars_eNB_g[0]->lte_frame_parms)); - } -#ifdef EXMIMO - for (i=0; i<PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti/2; i++) - { - tx_offset = (int)slot_offset+time_offset[aa]+i; - if (tx_offset<0) - tx_offset += LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti; - if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti)) - tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*PHY_vars_eNB_g[0]->lte_frame_parms.samples_per_tti; - ((short*)&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0]= - ((short*)dummy_tx_buffer)[2*i]<<4; - ((short*)&PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1]= - ((short*)dummy_tx_buffer)[2*i+1]<<4; - } -#endif //EXMIMO - } - } + else { + // LOG_I(PHY,"[eNB] Waking up eNB process %d (IC %d)\n",sf,PHY_vars_eNB_g[0]->proc[sf].instance_cnt); + PHY_vars_eNB_g[0]->proc[sf].instance_cnt_tx++; + pthread_mutex_unlock(&PHY_vars_eNB_g[0]->proc[sf].mutex_tx); + if (PHY_vars_eNB_g[0]->proc[sf].instance_cnt_tx == 0) { + if (pthread_cond_signal(&PHY_vars_eNB_g[0]->proc[sf].cond_tx) != 0) { + LOG_E(PHY,"[eNB] ERROR pthread_cond_signal for eNB TX thread %d\n",sf); } - else { // multi-thread > 0 - - if ((slot&1) == 0) { - sf = (slot<<1)+1; - if (PHY_vars_eNB_g[0]->proc[sf].instance_cnt == 0) { - if (pthread_cond_signal(&PHY_vars_eNB_g[0]->proc[sf].cond) != 0) { - LOG_E(PHY,"[eNB] ERROR pthread_cond_signal for eNB proc %d\n",sf); - } - } - else { - LOG_W(PHY,"[eNB] Frame %d, eNB proc %d busy!!\n",PHY_vars_eNB_g[0]->proc[sf].frame_tx,sf); - } - } + } + else { + LOG_W(PHY,"[eNB] Frame %d, eNB TX thread %d busy!!\n",PHY_vars_eNB_g[0]->proc[sf].frame_tx,sf); + } + } + + if (pthread_mutex_lock(&PHY_vars_eNB_g[0]->proc[sf].mutex_rx) != 0) { + LOG_E(PHY,"[eNB] ERROR pthread_mutex_lock for eNB RX thread %d (IC %d)\n",sf,PHY_vars_eNB_g[0]->proc[sf].instance_cnt_rx); + } + else { + // LOG_I(PHY,"[eNB] Waking up eNB process %d (IC %d)\n",sf,PHY_vars_eNB_g[0]->proc[sf].instance_cnt); + PHY_vars_eNB_g[0]->proc[sf].instance_cnt_rx++; + pthread_mutex_unlock(&PHY_vars_eNB_g[0]->proc[sf].mutex_rx); + if (PHY_vars_eNB_g[0]->proc[sf].instance_cnt_rx == 0) { + if (pthread_cond_signal(&PHY_vars_eNB_g[0]->proc[sf].cond_rx) != 0) { + LOG_E(PHY,"[eNB] ERROR pthread_cond_signal for eNB RX thread %d\n",sf); } } - } - /* - if ((slot%2000)<10) - LOG_D(HW,"fun0: doing very hard work\n"); - */ - - slot++; - if (slot==20) { - slot=0; - frame++; + else { + LOG_W(PHY,"[eNB] Frame %d, eNB RX thread %d busy!!\n",PHY_vars_eNB_g[0]->proc[sf].frame_rx,sf); + } } + + } + } + } + + slot++; + if (slot==20) { + slot=0; + frame++; + } #if defined(ENABLE_ITTI) - itti_update_lte_time(frame, slot); + itti_update_lte_time(frame, slot); #endif - } - - LOG_D(HW,"eNB_thread: finished, ran %d times.\n",frame); - + } + } +#ifdef DEBUG_THREADS + printf("eNB_thread: finished, ran %d times.\n",frame); +#endif + #ifdef HARD_RT - rt_make_soft_real_time(); + rt_make_soft_real_time(); #endif - } - // clean task + +#ifdef DEBUG_THREADS + printf("Exiting eNB_thread ..."); +#endif + // clean task #ifdef RTAI - rt_task_delete(task); + rt_task_delete(task); +#else + eNB_thread_status = 0; + pthread_exit(&eNB_thread_status); #endif - LOG_D(HW,"Task deleted. returning\n"); - return 0; - } +#ifdef DEBUG_THREADS + printf("eNB_thread deleted. returning\n"); +#endif + return 0; +} - /* This is the main UE thread. Initially it is doing a periodic get_frame. One synchronized it gets woken up by the kernel driver using the RTAI message mechanism (rt_send and rt_receive). */ - static void *UE_thread(void *arg) - { +/* This is the main UE thread. Initially it is doing a periodic get_frame. One synchronized it gets woken up by the kernel driver using the RTAI message mechanism (rt_send and rt_receive). */ +static void *UE_thread(void *arg) { #ifdef RTAI RT_TASK *task; #endif @@ -1124,9 +1308,10 @@ static void *eNB_thread(void *arg) LOG_D(HW,"UE Frame %d: skipped slot, waiting for hw to catch up (slot %d, hw_slot %d, mbox_current %d, mbox_target %d, diff %d)\n",frame, slot, hw_slot, mbox_current, mbox_target, diff2); /* - if (frame%100==0) + if (frame%100==0) LOG_D(HW,"frame %d (%d), slot %d, hw_slot %d, rx_offset_mbox %d, mbox_target %d, mbox_current %d, diff %d\n",frame, PHY_vars_UE_g[0]->frame, slot,hw_slot,rx_offset_mbox,mbox_target,mbox_current,diff2); */ + vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *((volatile unsigned int *) openair0_exmimo_pci[card].rxcnt_ptr[0])); vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DIFF, diff2); @@ -1135,9 +1320,11 @@ static void *eNB_thread(void *arg) { time_in = rt_get_time_ns(); //LOG_D(HW,"eNB Frame %d delaycnt %d : hw_slot %d (%d), slot %d (%d), diff %d, time %llu\n",frame,delay_cnt,hw_slot,((volatile unsigned int *)DAQ_MBOX)[0],slot,mbox_target,diff2,time_in); + vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *((volatile unsigned int *) openair0_exmimo_pci[card].rxcnt_ptr[0])); vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1); ret = rt_sleep_ns(diff2*DAQ_PERIOD); vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,0); + vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *((volatile unsigned int *) openair0_exmimo_pci[card].rxcnt_ptr[0])); if (ret) LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in); @@ -1490,12 +1677,16 @@ static void *eNB_thread(void *arg) int main(int argc, char **argv) { #ifdef RTAI // RT_TASK *task; +#else + int *eNB_thread_status_p; + int *eNB_thread_status_rx[10],*eNB_thread_status_tx[10]; #endif int i,j,aa; #if defined (XFORMS) || defined (EMOS) || (! defined (RTAI)) void *status; #endif + uint16_t Nid_cell = 0; uint8_t cooperation_flag=0, transmission_mode=1, abstraction_flag=0; #ifndef OPENAIR2 @@ -2130,7 +2321,7 @@ static void *eNB_thread(void *arg) pthread_attr_init (&attr_dlsch_threads); pthread_attr_setstacksize(&attr_dlsch_threads,OPENAIR_THREAD_STACK_SIZE); //attr_dlsch_threads.priority = 1; - sched_param_dlsch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY; + sched_param_dlsch.sched_priority = 90;//sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY; pthread_attr_setschedparam (&attr_dlsch_threads, &sched_param_dlsch); pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO); #endif @@ -2157,6 +2348,11 @@ static void *eNB_thread(void *arg) printf("UE threads created\n"); } else { + + if (multi_thread>0) { + init_eNB_proc(); + LOG_D(HW,"[lte-softmodem.c] eNB threads created\n"); + } #ifdef RTAI thread0 = rt_thread_create(eNB_thread, NULL, 100000000); #else @@ -2173,9 +2369,9 @@ static void *eNB_thread(void *arg) init_ulsch_threads(); #endif - init_eNB_proc(); - printf("eNB threads created\n"); + + } @@ -2228,11 +2424,23 @@ static void *eNB_thread(void *arg) #ifdef RTAI rt_thread_join(thread0); #else - pthread_join(thread0,&status); +#ifdef DEBUG_THREADS + printf("Joining eNB_thread ..."); +#endif + pthread_join(thread0,(void**)&eNB_thread_status_p); +#ifdef DEBUG_THREADS + printf("status %d\n",*eNB_thread_status_p); +#endif #endif #ifdef ULSCH_THREAD cleanup_ulsch_threads(); #endif + + if (multi_thread>0) { + printf("Killing eNB processing threads\n"); + kill_eNB_proc(); + + } } #ifdef OPENAIR2