diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 9aeafd17d60d253a4cec7d3caebcbed438f33643..310bc1f6d27e8588d2dca22eaf0b254e45897629 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -21,7 +21,7 @@ # Author: laurent THOMAS, Lionel GAUTHIER -cmake_minimum_required (VERSION 3.0) +cmake_minimum_required (VERSION 2.8) ############################################# # Base directories, compatible with legacy OAI building diff --git a/openair1/PHY/defs_common.h b/openair1/PHY/defs_common.h index c7e5897fff1f433eb970112e6ffb146dbedb9f54..78c12683c1b7df3353d7dcdcf6ca30614edb33e6 100644 --- a/openair1/PHY/defs_common.h +++ b/openair1/PHY/defs_common.h @@ -51,6 +51,7 @@ #include <sys/sysinfo.h> + #include <stdio.h> #include <stdlib.h> #include <malloc.h> @@ -60,6 +61,8 @@ #include "msc.h" #include <common/utils/LOG/log.h> +#include "assertions.h" + //#include <complex.h> @@ -1035,14 +1038,15 @@ typedef uint8_t(encoder_if_t)(uint8_t *input, static inline void wait_sync(char *thread_name) { + int rc; printf( "waiting for sync (%s,%d/%p,%p,%p)\n",thread_name,sync_var,&sync_var,&sync_cond,&sync_mutex); - pthread_mutex_lock( &sync_mutex ); + AssertFatal((rc = pthread_mutex_lock( &sync_mutex ))==0,"sync mutex lock error"); while (sync_var<0) pthread_cond_wait( &sync_cond, &sync_mutex ); - pthread_mutex_unlock(&sync_mutex); + AssertFatal((rc = pthread_mutex_unlock( &sync_mutex ))==0,"sync mutex unlock error"); printf( "got sync (%s)\n", thread_name); /* @@ -1056,37 +1060,20 @@ static inline int wakeup_thread(pthread_mutex_t *mutex,pthread_cond_t *cond,int int rc; int sleep_cnt=0; - if ((rc = pthread_mutex_lock(mutex)) != 0) { - LOG_E(PHY, "wakeup_thread(): error locking mutex for %s (%d %s, %p)\n", - name, rc, strerror(rc), (void *)mutex); - exit_fun("nothing to add"); - return(-1); - } + AssertFatal((rc = pthread_mutex_lock(mutex))==0,"wakeup_thread(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex); + while (*instance_cnt == 0) { - if ((rc = pthread_mutex_unlock(mutex)) != 0) { - LOG_E(PHY, "wakeup_thread(): error unlocking mutex for %s (%d %s, %p)\n", - name, rc, strerror(rc), (void *)mutex); - exit_fun("nothing to add"); - return(-1); - } + + AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"wakeup_thread(): error unlocking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex); + sleep_cnt++; if (sleep_cnt>sleep_cnt_max) return(-1); usleep(sleeptime); - if ((rc = pthread_mutex_lock(mutex)) != 0) { - LOG_E(PHY, "wakeup_thread(): error locking mutex for %s (%d %s, %p)\n", - name, rc, strerror(rc), (void *)mutex); - exit_fun("nothing to add"); - return(-1); - } + AssertFatal((rc = pthread_mutex_lock(mutex))==0,"wakeup_thread(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex); } *instance_cnt = *instance_cnt + 1; - if ((rc = pthread_mutex_unlock(mutex)) != 0) { - LOG_E(PHY, "wakeup_thread(): error locking mutex for %s (%d %s, %p)\n", - name, rc, strerror(rc), (void *)mutex); - exit_fun("nothing to add"); - return(-1); - } + AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"wakeup_thread(): error unlocking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex); // the thread can now be woken up if (pthread_cond_signal(cond) != 0) { @@ -1095,41 +1082,50 @@ static inline int wakeup_thread(pthread_mutex_t *mutex,pthread_cond_t *cond,int return(-1); } - pthread_mutex_unlock(mutex); + AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"wakeup_thread(): error unlocking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex); return(0); } -static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { +static inline int timedwait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name,uint32_t time_ns) { int rc; - if ((rc = pthread_mutex_lock(mutex)) != 0) { - LOG_E(PHY, "[SCHED][eNB] wait_on_condition(): error locking mutex for %s (%d %s, %p)\n", - name, rc, strerror(rc), (void *)mutex); - exit_fun("nothing to add"); - return(-1); + int waitret=0; + struct timespec now,abstime; + + AssertFatal((rc = pthread_mutex_lock(mutex))==0,"[SCHED][eNB] timedwait_on_condition(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex); + + clock_gettime(CLOCK_REALTIME,&now); + while (*instance_cnt < 0) { + // most of the time the thread is waiting here + // proc->instance_cnt_rxtx is -1 + abstime.tv_sec=now.tv_sec; + abstime.tv_nsec = now.tv_nsec + time_ns; + if ((waitret = pthread_cond_timedwait(cond,mutex,&abstime))==ETIMEDOUT) break; // this unlocks mutex_rxtx while waiting and then locks it again } + AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"[SCHED][eNB] timedwait_on_condition(): error unlocking mutex return %d for %s\n", rc, name); + + return(0); +} + +static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { + int rc; + + AssertFatal((rc = pthread_mutex_lock(mutex))==0,"[SCHED][eNB] wait_on_condition(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex); + while (*instance_cnt < 0) { // most of the time the thread is waiting here // proc->instance_cnt_rxtx is -1 pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again } - if (pthread_mutex_unlock(mutex) != 0) { - LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name); - exit_fun("nothing to add"); - return(-1); - } + AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"[SCHED][eNB] wait_on_condition(): error unlocking mutex return %d for %s\n", rc, name); + return(0); } static inline int wait_on_busy_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { int rc; - if ((rc = pthread_mutex_lock(mutex)) != 0) { - LOG_E(PHY, "[SCHED][eNB] wait_on_busy_condition(): error locking mutex for %s (%d %s, %p)\n", - name, rc, strerror(rc), (void *)mutex); - exit_fun("nothing to add"); - return(-1); - } + AssertFatal((rc = pthread_mutex_lock(mutex))==0,"[SCHED][eNB] wait_on_busy_condition(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex); while (*instance_cnt == 0) { // most of the time the thread will skip this @@ -1137,30 +1133,20 @@ static inline int wait_on_busy_condition(pthread_mutex_t *mutex,pthread_cond_t * pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again } - if (pthread_mutex_unlock(mutex) != 0) { - LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name); - exit_fun("nothing to add"); - return(-1); - } + AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"[SCHED][eNB] wait_on_busy_condition(): error unlocking mutex return %d for %s\n", rc, name); + return(0); } static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) { int rc; - if ((rc = pthread_mutex_lock(mutex)) != 0) { - LOG_E(PHY, "[SCHED][eNB] release_thread(): error locking mutex for %s (%d %s, %p)\n", - name, rc, strerror(rc), (void *)mutex); - exit_fun("nothing to add"); - return(-1); - } + + AssertFatal((rc = pthread_mutex_lock(mutex))==0,"[SCHED][eNB] release_thread(): error locking mutex for %s (%d %s, %p)\n", name, rc, strerror(rc), (void *)mutex); *instance_cnt=*instance_cnt-1; - if (pthread_mutex_unlock(mutex) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for %s\n",name); - exit_fun("nothing to add"); - return(-1); - } + AssertFatal((rc = pthread_mutex_unlock(mutex))==0,"[SCHED][eNB] release_thread(): error unlocking mutex return %d for %s\n", rc, name); + return(0); } diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 9ade3f9ea8042205f1cc0b1e1f2dcecf9ed8621a..3dfa7e741ccdbfeb8345899be088f4252bb130d6 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -144,8 +144,8 @@ extern double cpuf; void init_eNB(int,int); void stop_eNB(int nb_inst); -int wakeup_tx(PHY_VARS_eNB *eNB); -int wakeup_txfh(L1_rxtx_proc_t *proc,int frame_tx,int subframe_tx,uint64_t timestamp_tx,PHY_VARS_eNB *eNB); +int wakeup_tx(PHY_VARS_eNB *eNB ,int frame_rx,int subframe_rx,int frame_tx,int subframe_tx,uint64_t timestamp_tx); +int wakeup_txfh(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc,int frame_tx,int subframe_tx,uint64_t timestamp_tx); void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe); #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe); @@ -160,6 +160,7 @@ extern void add_subframe(uint16_t *frameP, uint16_t *subframeP, int offset); static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name) { + int ret; start_meas(&softmodem_stats_rxtx_sf); //L1_rxtx_proc_t *L1_proc_tx = &eNB->proc.L1_proc_tx; @@ -237,10 +238,7 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name memcpy(&pre_scd_eNB_UE_stats,&RC.mac[0]->UE_list.eNB_UE_stats, sizeof(eNB_UE_STATS)*MAX_NUM_CCs*NUMBER_OF_UE_MAX); memcpy(&pre_scd_activeUE, &RC.mac[0]->UE_list.active, sizeof(boolean_t)*NUMBER_OF_UE_MAX); - if (pthread_mutex_lock(&ru->proc.mutex_pre_scd)!= 0) { - LOG_E( PHY, "[eNB] error locking proc mutex for eNB pre scd\n"); - exit_fun("error locking mutex_time"); - } + AssertFatal((ret= pthread_mutex_lock(&ru->proc.mutex_pre_scd))==0,"[eNB] error locking proc mutex for eNB pre scd, return %d\n",ret); ru->proc.instance_pre_scd++; @@ -254,20 +252,18 @@ static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name proc->frame_rx,proc->subframe_rx,ru->proc.instance_pre_scd ); } - if (pthread_mutex_unlock(&ru->proc.mutex_pre_scd)!= 0) { - LOG_E( PHY, "[eNB] error unlocking mutex_pre_scd mutex for eNB pre scd\n"); - exit_fun("error unlocking mutex_pre_scd"); - } + AssertFatal((ret= pthread_mutex_unlock(&ru->proc.mutex_pre_scd))==0,"[eNB] error unlocking proc mutex for eNB pre scd, return %d\n",ret); + } #endif - pthread_mutex_lock(&eNB->UL_INFO_mutex); + AssertFatal((ret= pthread_mutex_lock(&eNB->UL_INFO_mutex))==0,"error locking UL_INFO_mutex, return %d\n",ret); eNB->UL_INFO.frame = proc->frame_rx; eNB->UL_INFO.subframe = proc->subframe_rx; eNB->UL_INFO.module_id = eNB->Mod_id; eNB->UL_INFO.CC_id = eNB->CC_id; eNB->if_inst->UL_indication(&eNB->UL_INFO); - pthread_mutex_unlock(&eNB->UL_INFO_mutex); + AssertFatal((ret= pthread_mutex_unlock(&eNB->UL_INFO_mutex))==0,"error unlocking UL_INFO_mutex, return %d\n",ret); /* this conflict resolution may be totally wrong, to be tested */ /* CONFLICT RESOLUTION: BEGIN */ @@ -336,6 +332,7 @@ static void *L1_thread_tx(void *param) { char thread_name[100]; sprintf(thread_name,"TXnp4_%d\n",&eNB->proc.L1_proc == proc ? 0 : 1); thread_top_init(thread_name,1,470000,500000,500000); + int ret; //wait_sync("tx_thread"); @@ -357,7 +354,7 @@ static void *L1_thread_tx(void *param) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX1_ENB,proc->frame_rx); LOG_D(PHY,"L1 TX processing %d.%d\n",proc->frame_tx,proc->subframe_tx); phy_procedures_eNB_TX(eNB, proc, 1); - pthread_mutex_lock( &proc->mutex ); + AssertFatal((ret= pthread_mutex_lock( &proc->mutex ))==0,"error locking L1_proc_tx mutex, return %d\n",ret); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,proc->instance_cnt); int subframe_tx = proc->subframe_tx; @@ -374,8 +371,8 @@ static void *L1_thread_tx(void *param) { exit_fun( "ERROR pthread_cond_signal" ); } - pthread_mutex_unlock( &proc->mutex ); - wakeup_txfh(proc,frame_tx,subframe_tx,timestamp_tx,eNB); + AssertFatal((ret= pthread_mutex_unlock( &proc->mutex ))==0,"error unlocking L1_proc_tx mutex, return %d\n",ret); + wakeup_txfh(eNB,proc,frame_tx,subframe_tx,timestamp_tx); } return 0; @@ -436,8 +433,8 @@ static void *L1_thread( void *param ) { if (NFAPI_MODE!=NFAPI_MODE_VNF) { - if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(eNB); - else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) wakeup_txfh(proc,proc->frame_tx,proc->subframe_tx,proc->timestamp_tx,eNB); + if(get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) wakeup_tx(eNB,proc->frame_rx,proc->subframe_rx,proc->frame_tx,proc->subframe_tx,proc->timestamp_tx); + else if(get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT) wakeup_txfh(eNB,proc,proc->frame_tx,proc->subframe_tx,proc->timestamp_tx); } if (release_thread(&proc->mutex,&proc->instance_cnt,thread_name)<0) break; @@ -475,48 +472,58 @@ void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string,RU_t } } -int wakeup_txfh(L1_rxtx_proc_t *proc,int frame_tx,int subframe_tx,uint64_t timestamp_tx,PHY_VARS_eNB *eNB) { +int wakeup_txfh(PHY_VARS_eNB *eNB, L1_rxtx_proc_t *proc,int frame_tx,int subframe_tx,uint64_t timestamp_tx) { + + RU_t *ru; RU_proc_t *ru_proc; LTE_DL_FRAME_PARMS *fp; - - - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; + int waitret,ret; LOG_D(PHY,"L1 TX Waking up TX FH %d.%d (IC RU TX %d)\n",frame_tx,subframe_tx,proc->instance_cnt_RUs); // grab the information for the RU due to the following wait - if(wait_on_condition(&proc->mutex_RUs,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh")<0) { - LOG_E(PHY,"Frame %d, subframe %d: TX FH not ready\n", frame_tx, subframe_tx); - return(-1); - } + waitret=timedwait_on_condition(&proc->mutex_RUs,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh",1000000); - if (release_thread(&proc->mutex_RUs,&proc->instance_cnt_RUs,"wakeup_txfh")<0) return(-1); + AssertFatal(release_thread(&proc->mutex_RUs,&proc->instance_cnt_RUs,"wakeup_txfh")==0, "error releaseing eNB lock on RUs\n"); + + if (waitret == ETIMEDOUT) { + LOG_W(PHY,"Dropping TX slot (%d.%d) because FH is blocked more than 1 subframe times (1ms)\n",frame_tx,subframe_tx); + + AssertFatal((ret=pthread_mutex_lock(&eNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); + eNB->proc.RU_mask_tx = 0; + AssertFatal((ret=pthread_mutex_unlock(&eNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); + AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RUs))==0,"mutex_lock returns %d\n",ret); + proc->instance_cnt_RUs = 0; + 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))==0,"mutex_unlock returns %d\n",ret); + return(-1); + } for(int ru_id=0; ru_id<eNB->num_RU; ru_id++){ - ru_proc = &eNB->RU_list[ru_id]->proc; - fp = &eNB->RU_list[ru_id]->frame_parms; + ru = eNB->RU_list[ru_id]; + ru_proc = &ru->proc; + fp = &ru->frame_parms; if (((fp->frame_type == TDD) && (subframe_select(fp,proc->subframe_tx)==SF_UL))|| (eNB->RU_list[ru_id]->state == RU_SYNC)|| (eNB->RU_list[ru_id]->wait_cnt>0)){ - pthread_mutex_lock(&proc->mutex_RUs); + AssertFatal((pthread_mutex_lock(&proc->mutex_RUs))==0, "mutex_lock returns %d\n",ret); proc->instance_cnt_RUs = 0; - pthread_mutex_unlock(&proc->mutex_RUs); + AssertFatal((pthread_mutex_unlock(&proc->mutex_RUs))==0, "mutex_unlock returns %d\n",ret); continue;//hacking only works when all RU_tx works on the same subframe #TODO: adding mask stuff } + AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_eNBs))==0,"ERROR pthread_mutex_lock failed on mutex_eNBs L1_thread_tx with ret=%d\n",ret); + if (ru_proc->instance_cnt_eNBs == 0) { - LOG_E(PHY,"Frame %d, subframe %d: TX FH thread busy, dropping Frame %d, subframe %d\n", ru_proc->frame_tx, ru_proc->subframe_tx, proc->frame_rx, proc->subframe_rx); - return(-1); + LOG_E(PHY,"Frame %d, subframe %d: TX FH thread busy, dropping Frame %d, subframe %d\n", ru_proc->frame_tx, ru_proc->subframe_tx, proc->frame_rx, proc->subframe_rx); + AssertFatal((ret=pthread_mutex_lock(&eNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret); + eNB->proc.RU_mask_tx = 0; + AssertFatal((ret=pthread_mutex_unlock(&eNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret); + AssertFatal((ret=pthread_mutex_unlock( &ru_proc->mutex_eNBs ))==0,"mutex_unlock return %d\n",ret); + return(-1); } - if (pthread_mutex_timedlock(&ru_proc->mutex_eNBs,&wait) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX1 thread %d (IC %d)\n", ru_proc->subframe_rx&1,ru_proc->instance_cnt_eNBs ); - exit_fun( "error locking mutex_eNB" ); - return(-1); - } ru_proc->instance_cnt_eNBs = 0; ru_proc->timestamp_tx = timestamp_tx; ru_proc->subframe_tx = subframe_tx; @@ -524,31 +531,23 @@ int wakeup_txfh(L1_rxtx_proc_t *proc,int frame_tx,int subframe_tx,uint64_t times LOG_D(PHY,"L1 TX Waking up TX FH (2) %d.%d\n",frame_tx,subframe_tx); // the thread can now be woken up - if (pthread_cond_signal(&ru_proc->cond_eNBs) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(-1); - } - pthread_mutex_unlock( &ru_proc->mutex_eNBs ); + AssertFatal(pthread_cond_signal(&ru_proc->cond_eNBs) == 0, + "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n"); + AssertFatal((ret=pthread_mutex_unlock(&ru_proc->mutex_eNBs))==0,"mutex_unlock returned %d\n",ret); } return(0); } -int wakeup_tx(PHY_VARS_eNB *eNB) { - L1_proc_t *proc=&eNB->proc; - L1_rxtx_proc_t *L1_proc_tx = &proc->L1_proc_tx; - L1_rxtx_proc_t *L1_proc = &proc->L1_proc; - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; +int wakeup_tx(PHY_VARS_eNB *eNB, int frame_rx,int subframe_rx,int frame_tx,int subframe_tx,uint64_t timestamp_tx) { + + L1_rxtx_proc_t *L1_proc = &eNB->proc.L1_proc; + L1_rxtx_proc_t *L1_proc_tx = &eNB->proc.L1_proc_tx; + + int ret; LOG_D(PHY,"ENTERED wakeup_tx (IC %d)\n",L1_proc_tx->instance_cnt); - if (pthread_mutex_timedlock(&L1_proc_tx->mutex,&wait) != 0) { - LOG_E(PHY, "[SCHED][eNB] ERROR locking mutex for eNB L1_thread_tx\n"); - exit_fun("ERROR pthread_lock"); - return(-1); - } + AssertFatal((ret = pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock returns %d\n",ret); LOG_D(PHY,"L1 RX %d.%d Waiting to wake up L1 TX %d.%d (IC L1TX %d)\n",L1_proc->frame_rx,L1_proc->subframe_rx,L1_proc->frame_tx,L1_proc->subframe_tx,L1_proc_tx->instance_cnt); @@ -560,21 +559,17 @@ int wakeup_tx(PHY_VARS_eNB *eNB) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,L1_proc_tx->instance_cnt); L1_proc_tx->instance_cnt = 0; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_TX_IC,L1_proc_tx->instance_cnt); - L1_proc_tx->subframe_rx = L1_proc->subframe_rx; - L1_proc_tx->frame_rx = L1_proc->frame_rx; - L1_proc_tx->subframe_tx = L1_proc->subframe_tx; - L1_proc_tx->frame_tx = L1_proc->frame_tx; - L1_proc_tx->timestamp_tx = L1_proc->timestamp_tx; + L1_proc_tx->subframe_rx = subframe_rx; + L1_proc_tx->frame_rx = frame_rx; + L1_proc_tx->subframe_tx = subframe_tx; + L1_proc_tx->frame_tx = frame_tx; + L1_proc_tx->timestamp_tx = timestamp_tx; // the thread can now be woken up LOG_D(PHY,"L1 RX Waking up L1 TX %d.%d\n",L1_proc->frame_tx,L1_proc->subframe_tx); - if (pthread_cond_signal(&L1_proc_tx->cond) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB TXnp4 thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(-1); - } + AssertFatal(pthread_cond_signal(&L1_proc_tx->cond) == 0, "ERROR pthread_cond_signal for eNB L1 thread tx\n"); - pthread_mutex_unlock( &L1_proc_tx->mutex); + AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"mutex_unlock returns %d\n",ret); return(0); } @@ -583,57 +578,43 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) { RU_proc_t *ru_proc=&ru->proc; L1_rxtx_proc_t *L1_proc=&proc->L1_proc; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; + + int i,ret; LOG_D(PHY,"ENTERED wakeup_rxtx, %d.%d\n",ru_proc->frame_rx,ru_proc->subframe_rx); - - struct timespec wait; - int sleep_cnt=0; - - wait.tv_sec=0; - wait.tv_nsec=5000000L; - // wake up TX for subframe n+sf_ahead - // lock the TX mutex and make sure the thread is ready - if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", L1_proc->subframe_rx&1,L1_proc->instance_cnt ); - exit_fun( "error locking mutex_rxtx" ); - return(-1); - } - if (L1_proc->instance_cnt == 0) { - pthread_mutex_unlock(&L1_proc->mutex); - usleep(200); - if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", L1_proc->subframe_rx&1,L1_proc->instance_cnt ); - exit_fun( "error locking mutex_rxtx" ); - return(-1); + + + AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret); + for (i=0;i<eNB->num_RU;i++) { + if (ru == eNB->RU_list[i]) { + if ((proc->RU_mask[ru_proc->subframe_rx]&(1<<i)) > 0) + LOG_E(PHY,"eNB %d frame %d, subframe %d : previous information from RU %d (num_RU %d,mask %x) has not been served yet!\n", + eNB->Mod_id,proc->frame_rx,proc->subframe_rx,ru->idx,eNB->num_RU,proc->RU_mask[ru_proc->subframe_rx]); + proc->RU_mask[ru_proc->subframe_rx] |= (1<<i); } - if (L1_proc->instance_cnt == 0) LOG_E(PHY,"Frame %d, subframe %d: RXTX0 thread busy, dropping\n",ru_proc->frame_rx,ru_proc->subframe_rx); } - if (L1_proc->instance_cnt == -1) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_IC,L1_proc->instance_cnt); - ++L1_proc->instance_cnt; - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_L1_PROC_IC,L1_proc->instance_cnt); - - // We have just received and processed the common part of a subframe, say n. - // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired - + if (proc->RU_mask[ru_proc->subframe_rx] != (1<<eNB->num_RU)-1) { // not all RUs have provided their information so return + LOG_E(PHY,"Not all RUs have provided their info\n"); + AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"mutex_unlock returns %d\n",ret); + return(0); + } + else { // all RUs have provided their information so continue on and wakeup eNB processing + proc->RU_mask[ru_proc->subframe_rx] = 0; + AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"mutex_unlock returns %d\n",ret); + } - LOG_D(PHY,"RU RX Waking up rxtx %d.%d (IC L1RX %d)\n",ru_proc->frame_rx,ru_proc->subframe_rx,L1_proc->instance_cnt); - while (L1_proc->instance_cnt == 0) { - pthread_mutex_unlock( &L1_proc->mutex); - if (++sleep_cnt == ru->wakeup_L1_sleep_cnt_max) { - LOG_E(PHY,"Frame %d, subframe %d: RXTX0 thread busy, dropping\n",L1_proc->frame_rx,L1_proc->subframe_rx); - return(-1); - } - usleep(ru->wakeup_L1_sleeptime); + // wake up TX for subframe n+sl_ahead + // lock the TX mutex and make sure the thread is ready + AssertFatal((ret=pthread_mutex_lock(&L1_proc->mutex)) == 0,"mutex_lock returns %d\n", ret); - if (pthread_mutex_timedlock(&L1_proc->mutex,&wait) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", L1_proc->subframe_rx&1,L1_proc->instance_cnt ); - exit_fun( "error locking mutex_rxtx" ); - return(-1); - } + if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe + AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"mutex_unlock return %d\n",ret); + LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->subframe_rx); + return(0); } + ++L1_proc->instance_cnt; // We have just received and processed the common part of a subframe, say n. @@ -642,38 +623,39 @@ int wakeup_rxtx(PHY_VARS_eNB *eNB,RU_t *ru) { // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, // we want to generate subframe (n+sf_ahead), so TS_tx = TX_rx+sf_ahead*samples_per_tti, // and proc->subframe_tx = proc->subframe_rx+sf_ahead - L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_tti); - L1_proc->frame_rx = ru_proc->frame_rx; - L1_proc->subframe_rx = ru_proc->subframe_rx; - L1_proc->frame_tx = (L1_proc->subframe_rx > (9-sf_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; - L1_proc->subframe_tx = (L1_proc->subframe_rx + sf_ahead)%10; + L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_tti); + L1_proc->frame_rx = ru_proc->frame_rx; + L1_proc->subframe_rx = ru_proc->subframe_rx; + L1_proc->frame_tx = (L1_proc->subframe_rx > (9-sf_ahead)) ? (L1_proc->frame_rx+1)&1023 : L1_proc->frame_rx; + L1_proc->subframe_tx = (L1_proc->subframe_rx + sf_ahead)%10; - LOG_D(PHY,"wakeup_rxtx: L1_proc->subframe_rx %d, L1_proc->subframe_tx %d, RU %d\n",L1_proc->subframe_rx,L1_proc->subframe_tx,ru->idx); + LOG_D(PHY,"wakeup_rxtx: L1_proc->subframe_rx %d, L1_proc->subframe_tx %d, RU %d\n",L1_proc->subframe_rx,L1_proc->subframe_tx,ru->idx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_RXTX_RX_RU+ru->idx, L1_proc->frame_rx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_RXTX_RX_RU+ru->idx, L1_proc->subframe_rx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->frame_tx); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->subframe_tx); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_RXTX_RX_RU+ru->idx, L1_proc->frame_rx); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_RXTX_RX_RU+ru->idx, L1_proc->subframe_rx); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->frame_tx); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_WAKEUP_RXTX_TX_RU+ru->idx, L1_proc->subframe_tx); // the thread can now be woken up - if (pthread_cond_signal(&L1_proc->cond) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n"); - exit_fun( "ERROR pthread_cond_signal" ); - return(-1); - } + if (pthread_cond_signal(&L1_proc->cond) != 0) { + LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n"); + exit_fun( "ERROR pthread_cond_signal" ); + return(-1); } - pthread_mutex_unlock( &L1_proc->mutex); + + AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"mutex_unlock return %d\n",ret); + return(0); } void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { L1_proc_t *proc = &eNB->proc; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - int i; + int i,ret; if (ru!=NULL) { - pthread_mutex_lock(&proc->mutex_RU_PRACH); + AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU_PRACH))==0,"mutex_lock return %d\n",ret); for (i=0; i<eNB->num_RU; i++) { if (ru == eNB->RU_list[i]) { LOG_D(PHY,"frame %d, subframe %d: RU %d for eNB %d signals PRACH (mask %x, num_RU %d)\n",frame,subframe,i,eNB->Mod_id,proc->RU_mask_prach,eNB->num_RU); @@ -687,11 +669,11 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { } if (proc->RU_mask_prach != (1<<eNB->num_RU)-1) { // not all RUs have provided their information so return - pthread_mutex_unlock(&proc->mutex_RU_PRACH); + AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU_PRACH))==0,"mutex_unlock return %d\n",ret); return; } else { // all RUs have provided their information so continue on and wakeup eNB processing proc->RU_mask_prach = 0; - pthread_mutex_unlock(&proc->mutex_RU_PRACH); + AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU_PRACH))==0,"mutex_unlock return %d\n",ret); } } @@ -705,11 +687,7 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { } // wake up thread for PRACH RX - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach); - exit_fun( "error locking mutex_prach" ); - return; - } + AssertFatal((ret=pthread_mutex_lock(&proc->mutex_prach))==0,"[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach); ++proc->instance_cnt_prach; // set timing for prach thread @@ -723,7 +701,7 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { return; } - pthread_mutex_unlock( &proc->mutex_prach ); + AssertFatal((ret=pthread_mutex_unlock( &proc->mutex_prach))==0,"mutex_unlock return %d\n",ret); } } @@ -731,10 +709,10 @@ void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { L1_proc_t *proc = &eNB->proc; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - int i; + int i,ret; if (ru!=NULL) { - pthread_mutex_lock(&proc->mutex_RU_PRACH_br); + AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU_PRACH_br))==0,"mutex_lock return %d\n",ret); for (i=0; i<eNB->num_RU; i++) { if (ru == eNB->RU_list[i]) { @@ -749,11 +727,11 @@ void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { } if (proc->RU_mask_prach_br != (1<<eNB->num_RU)-1) { // not all RUs have provided their information so return - pthread_mutex_unlock(&proc->mutex_RU_PRACH_br); + AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU_PRACH_br))==0,"mutex_unlock return %d\n",ret); return; } else { // all RUs have provided their information so continue on and wakeup eNB processing proc->RU_mask_prach_br = 0; - pthread_mutex_unlock(&proc->mutex_RU_PRACH_br); + AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU_PRACH_br))==0,"mutex_unlock return %d\n",ret); } } @@ -767,11 +745,7 @@ void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { } // wake up thread for PRACH RX - if (pthread_mutex_lock(&proc->mutex_prach_br) != 0) { - LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach_br); - exit_fun( "error locking mutex_prach" ); - return; - } + AssertFatal((ret=pthread_mutex_lock(&proc->mutex_prach_br))==0,"[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->thread_index, proc->instance_cnt_prach_br); ++proc->instance_cnt_prach_br; // set timing for prach thread @@ -785,7 +759,7 @@ void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) { return; } - pthread_mutex_unlock( &proc->mutex_prach_br ); + AssertFatal((ret=pthread_mutex_unlock( &proc->mutex_prach_br))==0,"mutex_unlock return %d\n",ret); } } #endif @@ -1029,6 +1003,7 @@ void kill_eNB_proc(int inst) { PHY_VARS_eNB *eNB; L1_proc_t *proc; L1_rxtx_proc_t *L1_proc, *L1_proc_tx; + int ret; for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) { eNB=RC.eNB[inst][CC_id]; @@ -1044,32 +1019,32 @@ void kill_eNB_proc(int inst) { LOG_I(PHY, "Killing TX CC_id %d inst %d\n", CC_id, inst ); if ((get_thread_parallel_conf() == PARALLEL_RU_L1_SPLIT || get_thread_parallel_conf() == PARALLEL_RU_L1_TRX_SPLIT) && NFAPI_MODE!=NFAPI_MODE_VNF) { - pthread_mutex_lock(&L1_proc->mutex); + AssertFatal((ret=pthread_mutex_lock(&L1_proc->mutex))==0,"mutex_lock return %d\n",ret); L1_proc->instance_cnt = 0; pthread_cond_signal(&L1_proc->cond); - pthread_mutex_unlock(&L1_proc->mutex); - pthread_mutex_lock(&L1_proc_tx->mutex); + AssertFatal((ret=pthread_mutex_unlock(&L1_proc->mutex))==0,"mutex_unlock return %d\n",ret); + AssertFatal((ret=pthread_mutex_lock(&L1_proc_tx->mutex))==0,"mutex_lock return %d\n",ret); L1_proc_tx->instance_cnt = 0; pthread_cond_signal(&L1_proc_tx->cond); - pthread_mutex_unlock(&L1_proc_tx->mutex); + AssertFatal((ret=pthread_mutex_unlock(&L1_proc_tx->mutex))==0,"muex_unlock return %d\n",ret); } - pthread_mutex_lock(&proc->mutex_prach); + AssertFatal((ret=pthread_mutex_lock(&proc->mutex_prach))==0,"mutex_lock return %d\n",ret); proc->instance_cnt_prach = 0; pthread_cond_signal( &proc->cond_prach ); - pthread_mutex_unlock(&proc->mutex_prach); + AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_prach))==0,"mutex_unlock return %d\n",ret); pthread_cond_signal( &proc->cond_asynch_rxtx ); pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx); LOG_D(PHY, "joining pthread_prach\n"); pthread_join( proc->pthread_prach, (void **)&status ); LOG_I(PHY, "Destroying prach mutex/cond\n"); - pthread_mutex_destroy( &proc->mutex_prach ); + pthread_mutex_destroy( &proc->mutex_prach); pthread_cond_destroy( &proc->cond_prach ); #if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0)) proc->instance_cnt_prach_br = 0; pthread_cond_signal( &proc->cond_prach_br ); pthread_join( proc->pthread_prach_br, (void **)&status ); - pthread_mutex_destroy( &proc->mutex_prach_br ); + pthread_mutex_destroy( &proc->mutex_prach_br); pthread_cond_destroy( &proc->cond_prach_br ); #endif LOG_I(PHY, "Destroying UL_INFO mutex\n");