diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c index 36eba0efe3f6dab43eca7b5eabb117e62bcdcf65..d55c2d058655d047be11ddef324104b5914aedf4 100644 --- a/targets/RT/USER/lte-enb.c +++ b/targets/RT/USER/lte-enb.c @@ -163,6 +163,163 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst void stop_eNB(int nb_inst); +inline void thread_top_init(char *thread_name, + uint64_t runtime, + uint64_t deadline, + uint64_t period) { + + MSC_START_USE(); + +#ifdef DEADLINE_SCHEDULER + struct sched_attr attr; + + unsigned int flags = 0; + + attr.size = sizeof(attr); + attr.sched_flags = 0; + attr.sched_nice = 0; + attr.sched_priority = 0; + + attr.sched_policy = SCHED_DEADLINE; + attr.sched_runtime = runtime; + attr.sched_deadline = deadline; + attr.sched_period = period; + + if (sched_setattr(0, &attr, flags) < 0 ) { + perror("[SCHED] eNB tx thread: sched_setattr failed\n"); + return &eNB_thread_rxtx_status; + } + + LOG_I( HW, "[SCHED] eNB RXn-TXnp4 deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); + +#else //LOW_LATENCY + int policy, s, j; + struct sched_param sparam; + char cpu_affinity[1024]; + cpu_set_t cpuset; + + /* Set affinity mask to include CPUs 1 to MAX_CPUS */ + /* CPU 0 is reserved for UHD threads */ + /* CPU 1 is reserved for all RX_TX threads */ + /* Enable CPU Affinity only if number of CPUs >2 */ + CPU_ZERO(&cpuset); + +#ifdef CPU_AFFINITY + if (get_nprocs() > 2) + { + for (j = 1; j < get_nprocs(); j++) + CPU_SET(j, &cpuset); + s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) + { + perror( "pthread_setaffinity_np"); + exit_fun("Error setting processor affinity"); + } + } +#endif //CPU_AFFINITY + + /* Check the actual affinity mask assigned to the thread */ + s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); + if (s != 0) { + perror( "pthread_getaffinity_np"); + exit_fun("Error getting processor affinity "); + } + memset(cpu_affinity,0,sizeof(cpu_affinity)); + for (j = 0; j < CPU_SETSIZE; j++) + if (CPU_ISSET(j, &cpuset)) { + char temp[1024]; + sprintf (temp, " CPU_%d", j); + strcat(cpu_affinity, temp); + } + + memset(&sparam, 0, sizeof(sparam)); + sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; + policy = SCHED_FIFO ; + + s = pthread_setschedparam(pthread_self(), policy, &sparam); + if (s != 0) { + perror("pthread_setschedparam : "); + exit_fun("Error setting thread priority"); + } + + s = pthread_getschedparam(pthread_self(), &policy, &sparam); + if (s != 0) { + perror("pthread_getschedparam : "); + exit_fun("Error getting thread priority"); + } + + LOG_I(HW, "[SCHED][eNB] %s started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",thread_name,sched_getcpu(),gettid(), + (policy == SCHED_FIFO) ? "SCHED_FIFO" : + (policy == SCHED_RR) ? "SCHED_RR" : + (policy == SCHED_OTHER) ? "SCHED_OTHER" : + "???", + sparam.sched_priority, cpu_affinity ); + +#endif //LOW_LATENCY + + mlockall(MCL_CURRENT | MCL_FUTURE); + +} + +inline void wait_sync(char *thread_name) { + + printf( "waiting for sync (%s)\n",thread_name); + pthread_mutex_lock( &sync_mutex ); + + while (sync_var<0) + pthread_cond_wait( &sync_cond, &sync_mutex ); + + pthread_mutex_unlock(&sync_mutex); + + printf( "got sync (%s)\n", thread_name); + +} + +inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) { + + struct timespec wait; + + wait.tv_sec=0; + wait.tv_nsec=5000000L; + + if (pthread_mutex_timedlock(mutex,&wait) != 0) { + LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name); + exit_fun("nothing to add"); + return(-1); + } + + 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); + } + return(0); +} + +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); + exit_fun("nothing to add"); + return(-1); + } + + *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); + } + return(0); +} + void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) { unsigned int aa,slot_offset, slot_offset_F; @@ -419,135 +576,19 @@ static void* eNB_thread_rxtx( void* param ) { PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms; - FILE *tx_time_file = NULL; - char tx_time_name[101]; + char thread_name[100]; + - - if (opp_enabled == 1) { - snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf", "eNB"); - tx_time_file = fopen(tx_time_name,"w"); - } // set default return value eNB_thread_rxtx_status = 0; - MSC_START_USE(); - -#ifdef DEADLINE_SCHEDULER - struct sched_attr attr; - - unsigned int flags = 0; - uint64_t runtime = 850000 ; - uint64_t deadline = 1 * 1000000 ; // each tx thread will finish within 1ms - uint64_t period = 1 * 10000000; // each tx thread has a period of 10ms from the starting point - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0; - - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = runtime; - attr.sched_deadline = deadline; - attr.sched_period = period; - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] eNB tx thread: sched_setattr failed\n"); - return &eNB_thread_rxtx_status; - } - - LOG_I( HW, "[SCHED] eNB RXn-TXnp4 deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); - -#else //LOW_LATENCY - int policy, s, j; - struct sched_param sparam; - char cpu_affinity[1024]; - cpu_set_t cpuset; - struct timespec wait; - - wait.tv_sec=0; - wait.tv_nsec=5000000L; - - /* Set affinity mask to include CPUs 1 to MAX_CPUS */ - /* CPU 0 is reserved for UHD threads */ - /* CPU 1 is reserved for all RX_TX threads */ - /* Enable CPU Affinity only if number of CPUs >2 */ - CPU_ZERO(&cpuset); - -#ifdef CPU_AFFINITY - if (get_nprocs() > 2) - { - for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) - { - perror( "pthread_setaffinity_np"); - exit_fun("Error setting processor affinity"); - } - } -#endif //CPU_AFFINITY - - /* Check the actual affinity mask assigned to the thread */ - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) { - perror( "pthread_getaffinity_np"); - exit_fun("Error getting processor affinity "); - } - memset(cpu_affinity,0,sizeof(cpu_affinity)); - for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) { - char temp[1024]; - sprintf (temp, " CPU_%d", j); - strcat(cpu_affinity, temp); - } - - memset(&sparam, 0, sizeof(sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; - policy = SCHED_FIFO ; - - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) { - perror("pthread_getschedparam : "); - exit_fun("Error getting thread priority"); - } - - LOG_I(HW, "[SCHED][eNB] RXn_TXnp4 thread started on CPU %d TID %ld, sched_policy = %s , priority = %d, CPU Affinity=%s \n",sched_getcpu(),gettid(), - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - sparam.sched_priority, cpu_affinity ); - -#endif //LOW_LATENCY - - mlockall(MCL_CURRENT | MCL_FUTURE); + sprintf(thread_name,"RXn_TXnp4_%d\n",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1); + thread_top_init(thread_name,850000L,1000000L,2000000L); while (!oai_exit) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); - if (pthread_mutex_timedlock(&proc->mutex_rxtx,&wait) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RXn-TXnp4\n"); - exit_fun("nothing to add"); - break; - } - - while (proc->instance_cnt_rxtx < 0) { - // most of the time the thread is waiting here - // proc->instance_cnt_rxtx is -1 - pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx ); // this unlocks mutex_rxtx while waiting and then locks it again - } - - if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { - LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX\n"); - exit_fun("nothing to add"); - break; - } + if (wait_on_condition(&proc->mutex_rxtx,&proc->cond_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 ); @@ -583,33 +624,10 @@ static void* eNB_thread_rxtx( void* param ) { } - - if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc\n"); - exit_fun("nothing to add"); - break; - } - - proc->instance_cnt_rxtx--; - - if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB TX proc\n"); - exit_fun("nothing to add"); - break; - } + if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) break; stop_meas( &softmodem_stats_rxtx_sf ); - - if (opp_enabled){ - -#ifdef DEADLINE_SCHEDULER - if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime){ - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); - } -#endif - } - print_meas_now(&softmodem_stats_rxtx_sf,"eNB_TX_SF",tx_time_file); - } + } // while !oai_exit VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); @@ -795,125 +813,20 @@ static void* eNB_thread_asynch_rxtx( void* param ) { eNB_proc_t *proc = (eNB_proc_t*)param; PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; - LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - - int subframe=0, frame=0; - - -#ifdef DEADLINE_SCHEDULER - struct sched_attr attr; - unsigned int flags = 0; - uint64_t runtime = 870000 ; - uint64_t deadline = 1 * 1000000; - uint64_t period = 1 * 10000000; // each rx thread has a period of 10ms from the starting point - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0; - - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = runtime; - attr.sched_deadline = deadline; - attr.sched_period = period; - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] eNB FH sched_setattr failed\n"); - return &eNB_thread_asynch_rx_status; - } - - LOG_I( HW, "[SCHED] eNB asynch RX deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); -#else // LOW_LATENCY - int policy, s, j; - struct sched_param sparam; - char cpu_affinity[1024]; - cpu_set_t cpuset; - - /* Set affinity mask to include CPUs 1 to MAX_CPUS */ - /* CPU 0 is reserved for UHD */ - /* CPU 1 is reserved for all TX threads */ - /* CPU 2..MAX_CPUS is reserved for all RX threads */ - /* Set CPU Affinity only if number of CPUs >2 */ - CPU_ZERO(&cpuset); -#ifdef CPU_AFFINITY - if (get_nprocs() >2) { - for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); - - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) { - perror( "pthread_setaffinity_np"); - exit_fun (" Error setting processor affinity :"); - } - } -#endif //CPU_AFFINITY - /* Check the actual affinity mask assigned to the thread */ - - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) { - perror ("pthread_getaffinity_np"); - exit_fun (" Error getting processor affinity :"); - } - memset(cpu_affinity,0, sizeof(cpu_affinity)); - for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) { - char temp[1024]; - sprintf (temp, " CPU_%d", j); - strcat(cpu_affinity, temp); - } - - memset(&sparam, 0 , sizeof (sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO); - - policy = SCHED_FIFO ; - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - - memset(&sparam, 0 , sizeof (sparam)); - - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) { - perror("pthread_getschedparam"); - exit_fun("Error getting thread priority"); - } - - LOG_I(HW, "[SCHED][eNB] eNB asynch RX thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - sparam.sched_priority, cpu_affinity); - - -#endif // DEADLINE_SCHEDULER + int subframe=0, frame=0; - mlockall(MCL_CURRENT | MCL_FUTURE); + thread_top_init("thread_asynch",870000L,1000000L,1000000L); // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe - printf( "waiting for sync (eNB_thread_asynch_rx)\n"); - pthread_mutex_lock( &sync_mutex ); - - while (sync_var<0) - pthread_cond_wait( &sync_cond, &sync_mutex ); - - pthread_mutex_unlock(&sync_mutex); - - printf( "got sync (eNB_thread_asynch_rx)\n" ); + wait_sync("thread_asynch"); // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe printf( "waiting for devices (eNB_thread_asynch_rx)\n"); - pthread_mutex_lock( &proc->mutex_asynch_rxtx); - while (proc->instance_cnt_asynch_rxtx<0) - pthread_cond_wait( &proc->cond_asynch_rxtx, &proc->mutex_asynch_rxtx ); - - pthread_mutex_unlock(&proc->mutex_asynch_rxtx); + wait_on_condition(&proc->mutex_asynch_rxtx,&proc->cond_asynch_rxtx,&proc->instance_cnt_asynch_rxtx,"thread_asynch"); printf( "devices ok (eNB_thread_asynch_rx)\n"); @@ -1105,17 +1018,11 @@ void rx_fh_slave(PHY_VARS_eNB *eNB,int *frame,int *subframe) { // it just waits for an external event. The actual rx_rh is handle by the asynchronous RX thread eNB_proc_t *proc=&eNB->proc; - if (pthread_mutex_lock(&proc->mutex_FH) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for FH Slave\n"); - exit_fun( "error locking mutex" ); - } - - while (proc->instance_cnt_FH < 0) { - pthread_cond_wait( &proc->cond_FH,&proc->mutex_FH ); - } - proc->instance_cnt_FH++; - - pthread_mutex_unlock( &proc->mutex_FH ); + if (wait_on_condition(&proc->mutex_FH,&proc->cond_FH,&proc->instance_cnt_FH,"rx_fh_slave") < 0) + return; + + release_thread(&proc->mutex_FH,&proc->instance_cnt_FH,"rx_fh_slave"); + } @@ -1219,6 +1126,7 @@ void wakeup_slaves(eNB_proc_t *proc) { * \param param is a \ref eNB_proc_t structure which contains the info what to process. * \returns a pointer to an int. The storage is not on the heap and must not be freed. */ + static void* eNB_thread_FH( void* param ) { static int eNB_thread_FH_status; @@ -1227,131 +1135,20 @@ static void* eNB_thread_FH( void* param ) { PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id]; LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms; - FILE *rx_time_file = NULL; - char rx_time_name[101]; - int subframe=0, frame=0; - if (opp_enabled == 1) { - snprintf(rx_time_name, 100,"/tmp/%s_rx_time_thread_sf", "eNB"); - rx_time_file = fopen(rx_time_name,"w"); - } // set default return value eNB_thread_FH_status = 0; - MSC_START_USE(); - -#ifdef DEADLINE_SCHEDULER - struct sched_attr attr; - unsigned int flags = 0; - uint64_t runtime = 870000 ; - uint64_t deadline = 1 * 1000000; - uint64_t period = 1 * 10000000; // each rx thread has a period of 10ms from the starting point - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0; - - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = runtime; - attr.sched_deadline = deadline; - attr.sched_period = period; - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] eNB FH sched_setattr failed\n"); - return &eNB_thread_FH_status; - } - - LOG_I( HW, "[SCHED] eNB FH deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() ); -#else // LOW_LATENCY - int policy, s, j; - struct sched_param sparam; - char cpu_affinity[1024]; - cpu_set_t cpuset; - - /* Set affinity mask to include CPUs 1 to MAX_CPUS */ - /* CPU 0 is reserved for UHD */ - /* CPU 1 is reserved for all TX threads */ - /* CPU 2..MAX_CPUS is reserved for all RX threads */ - /* Set CPU Affinity only if number of CPUs >2 */ - CPU_ZERO(&cpuset); -#ifdef CPU_AFFINITY - if (get_nprocs() >2) { - for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); - - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) { - perror( "pthread_setaffinity_np"); - exit_fun (" Error setting processor affinity :"); - } - } -#endif //CPU_AFFINITY - /* Check the actual affinity mask assigned to the thread */ - - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) { - perror ("pthread_getaffinity_np"); - exit_fun (" Error getting processor affinity :"); - } - memset(cpu_affinity,0, sizeof(cpu_affinity)); - - for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) { - char temp[1024]; - sprintf (temp, " CPU_%d", j); - strcat(cpu_affinity, temp); - } - - memset(&sparam, 0 , sizeof (sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO); - - policy = SCHED_FIFO ; - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - - memset(&sparam, 0 , sizeof (sparam)); + thread_top_init("eNB_thread_FH",870000,1000000,1000000); - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) { - perror("pthread_getschedparam"); - exit_fun("Error getting thread priority"); - } + wait_sync("eNB_thread_FH"); - LOG_I(HW, "[SCHED][eNB] FH thread started on CPU %d TID %ld, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(), - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - sparam.sched_priority, cpu_affinity); - - -#endif // DEADLINE_SCHEDULER - - - mlockall(MCL_CURRENT | MCL_FUTURE); - - // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe - printf( "waiting for sync (eNB_thread_FH)\n"); - pthread_mutex_lock( &sync_mutex ); - - while (sync_var<0) - pthread_cond_wait( &sync_cond, &sync_mutex ); - - pthread_mutex_unlock(&sync_mutex); - - printf( "got sync (eNB_thread_FH)\n" ); - #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) @@ -1362,7 +1159,7 @@ static void* eNB_thread_FH( void* param ) { if (eNB->start_rf(eNB) != 0) LOG_E(HW,"Could not start the RF device\n"); - // wakeup asnych_rxtx thread + // 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); @@ -1371,10 +1168,8 @@ static void* eNB_thread_FH( void* param ) { // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices while (!oai_exit) { - if (oai_exit) break; - - - // this is to check that we are in synch with the fronthaul timing + // 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++; @@ -1399,30 +1194,7 @@ static void* eNB_thread_FH( void* param ) { if (wakeup_rxtx(proc,&proc->proc_rxtx[proc->subframe_rx&1],fp) < 0) break; - stop_meas( &softmodem_stats_rxtx_sf ); -#ifdef DEADLINE_SCHEDULER - if (opp_enabled){ - if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_RXTX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0); - } - } -#endif // DEADLINE_SCHEDULER - print_meas_now(&softmodem_stats_rx_sf,"eNB_RX_SF", rx_time_file); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); - - print_meas_now(&softmodem_stats_rx_sf,"eNB_RX_SF", rx_time_file); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 ); - - - if (eNB->node_timing == synch_to_ext_device) { - proc->instance_cnt_FH--; - - if (pthread_mutex_unlock(&proc->mutex_FH) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for FH\n"); - exit_fun( "error unlocking mutex" ); - } - } - + // artifical sleep for very slow fronthaul if (eNB->frame_parms.N_RB_DL==6) rt_sleep_ns(800000LL); } @@ -1444,147 +1216,21 @@ static void* eNB_thread_prach( void* param ) { eNB_proc_t *proc = (eNB_proc_t*)param; PHY_VARS_eNB *eNB= PHY_vars_eNB_g[0][proc->CC_id]; - /* - struct timespec wait; - wait.tv_sec=0; - wait.tv_nsec=5000000L; - */ // set default return value eNB_thread_prach_status = 0; - MSC_START_USE(); - -#ifdef DEADLINE_SCHEDULER - struct sched_attr attr; - unsigned int flags = 0; - uint64_t runtime = 870000 ; - uint64_t deadline = 1 * 1000000; - uint64_t period = 1 * 10000000; // each prach thread has a period of 10ms from the starting point - - attr.size = sizeof(attr); - attr.sched_flags = 0; - attr.sched_nice = 0; - attr.sched_priority = 0; - - attr.sched_policy = SCHED_DEADLINE; - attr.sched_runtime = runtime; - attr.sched_deadline = deadline; - attr.sched_period = period; - - if (sched_setattr(0, &attr, flags) < 0 ) { - perror("[SCHED] eNB PRACH sched_setattr failed\n"); - return &eNB_thread_prach_status; - } - - LOG_I( HW, "[SCHED] eNB PRACH deadline thread (TID %ld) started on CPU %d\n", 0, gettid(), sched_getcpu() ); -#else // LOW_LATENCY - int policy, s, j; - struct sched_param sparam; - char cpu_affinity[1024]; - cpu_set_t cpuset; - - /* Set affinity mask to include CPUs 1 to MAX_CPUS */ - /* CPU 0 is reserved for UHD */ - /* CPU 1 is reserved for all TX threads */ - /* CPU 2..MAX_CPUS is reserved for all RX threads */ - /* Set CPU Affinity only if number of CPUs >2 */ - CPU_ZERO(&cpuset); -#ifdef CPU_AFFINITY - if (get_nprocs() >2) { - for (j = 1; j < get_nprocs(); j++) - CPU_SET(j, &cpuset); - - s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) { - perror( "pthread_setaffinity_np"); - exit_fun (" Error setting processor affinity :"); - } - } -#endif //CPU_AFFINITY - - /* Check the actual affinity mask assigned to the thread */ - s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset); - if (s != 0) { - perror ("pthread_getaffinity_np"); - exit_fun (" Error getting processor affinity :"); - } - memset(cpu_affinity,0, sizeof(cpu_affinity)); - - for (j = 0; j < CPU_SETSIZE; j++) - if (CPU_ISSET(j, &cpuset)) { - char temp[1024]; - sprintf (temp, " CPU_%d", j); - strcat(cpu_affinity, temp); - } - - memset(&sparam, 0 , sizeof (sparam)); - sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-2; - - policy = SCHED_FIFO ; - s = pthread_setschedparam(pthread_self(), policy, &sparam); - if (s != 0) { - perror("pthread_setschedparam : "); - exit_fun("Error setting thread priority"); - } - - memset(&sparam, 0 , sizeof (sparam)); - - s = pthread_getschedparam(pthread_self(), &policy, &sparam); - if (s != 0) { - perror("pthread_getschedparam"); - exit_fun("Error getting thread priority"); - } - - LOG_I(HW, "[SCHED][eNB] PRACH thread started on CPU %d TID %ld, IC %d, sched_policy = %s, priority = %d, CPU Affinity = %s\n", sched_getcpu(),gettid(),proc->instance_cnt_prach, - (policy == SCHED_FIFO) ? "SCHED_FIFO" : - (policy == SCHED_RR) ? "SCHED_RR" : - (policy == SCHED_OTHER) ? "SCHED_OTHER" : - "???", - sparam.sched_priority, cpu_affinity); - -#endif // DEADLINE_SCHEDULER - - mlockall(MCL_CURRENT | MCL_FUTURE); + thread_top_init("eNB_thread_prach",500000L,1000000L,20000000L); while (!oai_exit) { if (oai_exit) break; - - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH\n"); - exit_fun( "error locking mutex" ); - break; - } - - while (proc->instance_cnt_prach < 0) { - // most of the time the thread is waiting here - // proc->instance_cnt_prach is -1 - pthread_cond_wait( &proc->cond_prach, &proc->mutex_prach ); // this unlocks mutex_rxtx while waiting and then locks it again - } - if (pthread_mutex_unlock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB PRACH\n"); - exit_fun( "error unlocking mutex" ); - break; - } - + if (wait_on_condition(&proc->mutex_prach,&proc->cond_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break; prach_procedures(eNB); - if (pthread_mutex_lock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH proc %d\n"); - exit_fun( "error locking mutex" ); - break; - } - - proc->instance_cnt_prach--; - - if (pthread_mutex_unlock(&proc->mutex_prach) != 0) { - LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n"); - exit_fun( "error unlocking mutex" ); - break; - } + if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"eNB_prach_thread") < 0) break; } printf( "Exiting eNB thread PRACH\n"); diff --git a/targets/RT/USER/rt_wrapper.c b/targets/RT/USER/rt_wrapper.c index ed9eb4e79833152366c9dbc2109afd1437589b86..d80de635a6b407cf7f89b53627befab28060c5dc 100644 --- a/targets/RT/USER/rt_wrapper.c +++ b/targets/RT/USER/rt_wrapper.c @@ -78,8 +78,6 @@ void set_latency_target(void) { } -#ifndef RTAI - struct timespec interval, next, now, res; clockid_t clock_id = CLOCK_MONOTONIC; //other options are CLOCK_MONOTONIC, CLOCK_REALTIME, CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID RTIME rt_get_time_ns (void) @@ -257,12 +255,7 @@ int sched_getattr(pid_t pid,struct sched_attr *attr,unsigned int size, unsigned #endif -#else -int rt_sleep_ns(RTIME x) -{ - rt_sleep(nano2count(x)); - return(0); -} -#endif + + diff --git a/targets/RT/USER/rt_wrapper.h b/targets/RT/USER/rt_wrapper.h index d67632054b7ee2a14f7c555b7d509452d1851bba..ae668945fe3c526f8ea271eafe8fbf088a9272e8 100644 --- a/targets/RT/USER/rt_wrapper.h +++ b/targets/RT/USER/rt_wrapper.h @@ -28,7 +28,7 @@ *******************************************************************************/ /*! \file rt_wrapper.h -* \brief provides a wrapper for the timing function for real-time opeartions depending on weather RTAI is used or not. It also implements an API for the SCHED_DEADLINE kernel scheduler. +* \brief provides a wrapper for the timing function for real-time opeartions. It also implements an API for the SCHED_DEADLINE kernel scheduler. * \author F. Kaltenberger and Navid Nikaein * \date 2013 * \version 0.1 @@ -39,9 +39,8 @@ */ -void set_latency_target(void); -#ifndef RTAI +#define _GNU_SOURCE #include <time.h> #include <errno.h> #include <stdint.h> @@ -52,11 +51,26 @@ void set_latency_target(void); #include <linux/types.h> #include <syscall.h> #include <math.h> +#include <sched.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <sched.h> +#include <linux/sched.h> +#include <signal.h> +#include <execinfo.h> +#include <getopt.h> +#include <sys/sysinfo.h> + +#include "UTIL/LOG/log_extern.h" +#include "msc.h" #define RTIME long long int #define rt_printk printf +void set_latency_target(void); + RTIME rt_get_time_ns (void); int rt_sleep_ns (RTIME x); @@ -115,12 +129,3 @@ int sched_getattr(pid_t pid,struct sched_attr *attr,unsigned int size, unsigned #define gettid() syscall(__NR_gettid) // for gettid -#else -#include <rtai_hal.h> -#include <rtai_lxrt.h> -#include <rtai_sem.h> -#include <rtai_msg.h> - -int rt_sleep_ns(RTIME x); - -#endif