Commit e337a52e authored by Lionel Gauthier's avatar Lionel Gauthier

patches13/0007-cleanup-threads.patch

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@7053 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent a0fe962b
...@@ -186,9 +186,11 @@ typedef struct { ...@@ -186,9 +186,11 @@ typedef struct {
int frame_tx; int frame_tx;
/// frame to act upon for reception /// frame to act upon for reception
int frame_rx; int frame_rx;
/// instance count for tx processing thread /// \brief Instance count for tx processing thread.
/// \internal This variable is protected by \ref mutex_tx.
int instance_cnt_tx; int instance_cnt_tx;
/// instance count for rx processing thread /// \brief Instance count for rx processing thread.
/// \internal This variable is protected by \ref mutex_rx.
int instance_cnt_rx; int instance_cnt_rx;
/// pthread structure for tx processing thread /// pthread structure for tx processing thread
pthread_t pthread_tx; pthread_t pthread_tx;
...@@ -204,12 +206,16 @@ typedef struct { ...@@ -204,12 +206,16 @@ typedef struct {
pthread_mutex_t mutex_rx; pthread_mutex_t mutex_rx;
} eNB_proc_t; } eNB_proc_t;
/// Top-level PHY Data Structure for eNB //! \brief Number of eNB TX and RX threads.
//! This number must be equal to the number of LTE subframes (10). Each thread is responsible for a single subframe.
#define NUM_ENB_THREADS 10
/// Top-level PHY Data Structure for eNB
typedef struct PHY_VARS_eNB_s{ typedef struct PHY_VARS_eNB_s{
/// Module ID indicator for this instance /// Module ID indicator for this instance
module_id_t Mod_id; module_id_t Mod_id;
uint8_t CC_id; uint8_t CC_id;
eNB_proc_t proc[10]; eNB_proc_t proc[NUM_ENB_THREADS];
uint8_t local_flag; uint8_t local_flag;
uint32_t rx_total_gain_eNB_dB; uint32_t rx_total_gain_eNB_dB;
LTE_DL_FRAME_PARMS lte_frame_parms; LTE_DL_FRAME_PARMS lte_frame_parms;
......
...@@ -195,11 +195,11 @@ int sync_var=-1; ...@@ -195,11 +195,11 @@ int sync_var=-1;
struct sched_param sched_param_UE_thread; struct sched_param sched_param_UE_thread;
pthread_attr_t attr_eNB_proc_tx[MAX_NUM_CCs][10]; pthread_attr_t attr_eNB_proc_tx[MAX_NUM_CCs][NUM_ENB_THREADS];
pthread_attr_t attr_eNB_proc_rx[MAX_NUM_CCs][10]; pthread_attr_t attr_eNB_proc_rx[MAX_NUM_CCs][NUM_ENB_THREADS];
#ifndef LOWLATENCY #ifndef LOWLATENCY
struct sched_param sched_param_eNB_proc_tx[MAX_NUM_CCs][10]; struct sched_param sched_param_eNB_proc_tx[MAX_NUM_CCs][NUM_ENB_THREADS];
struct sched_param sched_param_eNB_proc_rx[MAX_NUM_CCs][10]; struct sched_param sched_param_eNB_proc_rx[MAX_NUM_CCs][NUM_ENB_THREADS];
#endif #endif
#ifdef XFORMS #ifdef XFORMS
static pthread_t forms_thread; //xforms static pthread_t forms_thread; //xforms
...@@ -922,36 +922,32 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) { ...@@ -922,36 +922,32 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) {
} }
int eNB_thread_tx_status[10]; /*!
static void * eNB_thread_tx(void *param) { * \brief The transmit thread of eNB.
* \ref NUM_ENB_THREADS threads of this type are active at the same time.
* \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_tx( void* param )
{
static int eNB_thread_tx_status[NUM_ENB_THREADS];
//unsigned long cpuid;
eNB_proc_t *proc = (eNB_proc_t*)param; eNB_proc_t *proc = (eNB_proc_t*)param;
// RTIME time_in,time_out;
// set default return value
eNB_thread_tx_status[proc->subframe] = 0;
#ifdef RTAI #ifdef RTAI
RT_TASK *task; RT_TASK *task;
char task_name[8]; char task_name[8];
#else
#ifdef LOWLATENCY
struct sched_attr attr;
unsigned int flags = 0;
#endif
#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,"TXC%dS%d",proc->CC_id,proc->subframe); sprintf(task_name,"TXC%dS%d",proc->CC_id,proc->subframe);
task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF); task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);
if (task==NULL) { if (task == NULL) {
LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_TX 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; return 0;
} }
else { else {
LOG_I(PHY,"[SCHED][eNB] eNB TX thread CC %d SF %d started with id %p\n", LOG_I(PHY,"[SCHED][eNB] eNB TX thread CC %d SF %d started with id %p\n",
proc->CC_id, proc->CC_id,
...@@ -960,160 +956,153 @@ static void * eNB_thread_tx(void *param) { ...@@ -960,160 +956,153 @@ static void * eNB_thread_tx(void *param) {
} }
#else #else
#ifdef LOWLATENCY #ifdef LOWLATENCY
struct sched_attr attr;
unsigned int flags = 0;
attr.size = sizeof(attr); attr.size = sizeof(attr);
attr.sched_flags = 0; attr.sched_flags = 0;
attr.sched_nice = 0; attr.sched_nice = 0;
attr.sched_priority = 0; attr.sched_priority = 0;
/* This creates a 1ms reservation every 10ms period*/ // This creates a 1ms reservation every 10ms period
attr.sched_policy = SCHED_DEADLINE; attr.sched_policy = SCHED_DEADLINE;
attr.sched_runtime = 0.9 * 1000000; // each tx thread requires 1ms to finish its job attr.sched_runtime = 0.9 * 1000000; // each tx thread requires 1ms to finish its job
attr.sched_deadline = 1 * 1000000; // each tx thread will finish within 1ms attr.sched_deadline = 1 * 1000000; // each tx thread will finish within 1ms
attr.sched_period = 1 * 10000000; // each tx thread has a period of 10ms from the starting point attr.sched_period = 1 * 10000000; // each tx thread has a period of 10ms from the starting point
if (sched_setattr(0, &attr, flags) < 0 ){ if (sched_setattr(0, &attr, flags) < 0 ) {
perror("[SCHED] eNB tx thread: sched_setattr failed\n"); perror("[SCHED] eNB tx thread: sched_setattr failed\n");
exit(-1); return &eNB_thread_tx_status[proc->subframe];
} }
LOG_I(HW,"[SCHED] eNB TX deadline thread %d(id %ld) started on CPU %d\n", LOG_I( HW, "[SCHED] eNB TX deadline thread %d(id %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
proc->subframe, gettid(),sched_getcpu());
#else #else
LOG_I(HW,"[SCHED] eNB TX thread %d started on CPU %d\n", LOG_I( HW, "[SCHED][eNB] TX thread %d started on CPU %d\n", proc->subframe, sched_getcpu() );
proc->subframe,sched_getcpu());
#endif #endif
#endif #endif
mlockall(MCL_CURRENT | MCL_FUTURE); mlockall(MCL_CURRENT | MCL_FUTURE);
//rt_set_runnable_on_cpuid(task,1);
//cpuid = rtai_cpuid();
#ifdef HARD_RT #ifdef HARD_RT
rt_make_hard_real_time(); rt_make_hard_real_time();
#endif #endif
while (!oai_exit){ while (!oai_exit) {
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe),0); 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);
// printf("Locking mutex for eNB proc %d (subframe_tx %d))\n",proc->subframe,proc->instance_cnt_tx);
if (pthread_mutex_lock(&proc->mutex_tx) != 0) { if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
LOG_E(PHY,"[SCHED][eNB] error locking mutex for eNB TX proc %d\n",proc->subframe); LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe );
exit_fun("nothing to add"); exit_fun("nothing to add");
break;
} }
else {
while (proc->instance_cnt_tx < 0) { 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 );
//printf("Waiting and unlocking mutex for eNB proc %d (subframe_tx %d)\n",proc->subframe,proc->instance_cnt_tx); }
pthread_cond_wait(&proc->cond_tx,&proc->mutex_tx); if (pthread_mutex_unlock(&proc->mutex_tx) != 0) {
} LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n",proc->subframe);
// LOG_I(PHY,"Waking up and unlocking mutex for eNB proc %d instance_cnt_tx %d\n",proc->subframe,proc->instance_cnt_tx); exit_fun("nothing to add");
if (pthread_mutex_unlock(&proc->mutex_tx) != 0) { break;
LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n",proc->subframe);
exit_fun("nothing to add");
}
} }
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_TX_ENB, proc->frame_tx);
start_meas(&softmodem_stats_tx_sf[proc->subframe]);
if (oai_exit) break; 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_TX_ENB, proc->frame_tx );
start_meas( &softmodem_stats_tx_sf[proc->subframe] );
if (oai_exit) break;
if ((((PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == TDD)&& if ((((PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == TDD)&&
(subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx)==SF_DL))|| (subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx)==SF_DL))||
(PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD))) { (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD))) {
phy_procedures_eNB_TX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay, NULL ); phy_procedures_eNB_TX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay, NULL );
} }
if ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx)==SF_S)) { if ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_tx) == SF_S)) {
phy_procedures_eNB_TX(proc->subframe,PHY_vars_eNB_g[0][proc->CC_id],0,no_relay,NULL); phy_procedures_eNB_TX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay, NULL );
} }
do_OFDM_mod_rt(proc->subframe_tx,PHY_vars_eNB_g[0][proc->CC_id]); do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] );
if (pthread_mutex_lock(&proc->mutex_tx) != 0) { if (pthread_mutex_lock(&proc->mutex_tx) != 0) {
printf("[openair][SCHED][eNB] error locking mutex for eNB TX proc %d\n",proc->subframe); LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe );
} exit_fun("nothing to add");
else { break;
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->instance_cnt_tx--;
proc->frame_tx++;
if (proc->frame_tx==1024) if (pthread_mutex_unlock(&proc->mutex_tx) != 0) {
proc->frame_tx=0; LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB TX proc %d\n", proc->subframe );
exit_fun("nothing to add");
break;
}
proc->frame_tx++;
if (proc->frame_tx==1024)
proc->frame_tx=0;
}
stop_meas( &softmodem_stats_tx_sf[proc->subframe] );
vcd_signal_dumper_dump_function_by_name( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe), 0 );
}
stop_meas(&softmodem_stats_tx_sf[proc->subframe]);
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_TX0+(2*proc->subframe),0);
#ifdef HARD_RT #ifdef HARD_RT
rt_make_soft_real_time(); rt_make_soft_real_time();
#endif #endif
#ifdef DEBUG_THREADS #ifdef DEBUG_THREADS
printf("Exiting eNB thread TX %d\n",proc->subframe); printf( "Exiting eNB thread TX %d\n", proc->subframe );
#endif #endif
// clean task // clean task
#ifdef RTAI #ifdef RTAI
rt_task_delete(task); rt_task_delete(task);
#else
eNB_thread_tx_status[proc->subframe]=0;
pthread_exit(&eNB_thread_tx_status[proc->subframe]);
#endif #endif
#ifdef DEBUG_THREADS eNB_thread_tx_status[proc->subframe] = 0;
printf("Exiting eNB TX thread %d\n",proc->subframe); return &eNB_thread_tx_status[proc->subframe];
#endif
} }
int eNB_thread_rx_status[10];
static void * eNB_thread_rx(void *param) {
//unsigned long cpuid; /*!
* \brief The receive thread of eNB.
* \ref NUM_ENB_THREADS threads of this type are active at the same time.
* \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_rx( void* param )
{
static int eNB_thread_rx_status[NUM_ENB_THREADS];
eNB_proc_t *proc = (eNB_proc_t*)param; eNB_proc_t *proc = (eNB_proc_t*)param;
// RTIME time_in,time_out;
// set default return value
eNB_thread_rx_status[proc->subframe] = 0;
#ifdef RTAI #ifdef RTAI
RT_TASK *task; RT_TASK *task;
char task_name[8]; char task_name[8];
#else
#ifdef LOWLATENCY
struct sched_attr attr;
unsigned int flags = 0;
#endif
#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,"RXC%1dS%1d",proc->CC_id,proc->subframe); sprintf(task_name,"RXC%1dS%1d",proc->CC_id,proc->subframe);
task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF); task = rt_task_init_schmod(nam2num(task_name), 0, 0, 0, SCHED_FIFO, 0xF);
if (task==NULL) { if (task==NULL) {
LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_RX thread_index %d (%s)!!!!\n",proc->subframe,task_name); LOG_E(PHY,"[SCHED][eNB] Problem starting eNB_proc_RX thread_index %d (%s)!!!!\n",proc->subframe,task_name);
return 0; return 0;
} }
else { else {
LOG_I(PHY,"[SCHED][eNB] eNB RX thread CC_id %d SF %d started with id %p\n", /* on CPU %d*/ LOG_I(PHY,"[SCHED][eNB] eNB RX thread CC_id %d SF %d started with id %p\n", /* on CPU %d*/
proc->CC_id, proc->CC_id,
proc->subframe, proc->subframe,
task); /*,rtai_cpuid()*/ task); /*,rtai_cpuid()*/
} }
#else #else
#ifdef LOWLATENCY #ifdef LOWLATENCY
struct sched_attr attr;
unsigned int flags = 0;
attr.size = sizeof(attr); attr.size = sizeof(attr);
attr.sched_flags = 0; attr.sched_flags = 0;
attr.sched_nice = 0; attr.sched_nice = 0;
...@@ -1121,75 +1110,72 @@ static void * eNB_thread_tx(void *param) { ...@@ -1121,75 +1110,72 @@ static void * eNB_thread_tx(void *param) {
/* This creates a 2ms reservation every 10ms period*/ /* This creates a 2ms reservation every 10ms period*/
attr.sched_policy = SCHED_DEADLINE; attr.sched_policy = SCHED_DEADLINE;
attr.sched_runtime = 0.9 * 1000000; // each rx thread must finish its job in the worst case in 2ms attr.sched_runtime = 0.9 * 1000000; // each rx thread must finish its job in the worst case in 2ms
attr.sched_deadline = 1 * 1000000; // each rx thread will finish within 2ms attr.sched_deadline = 1 * 1000000; // each rx thread will finish within 2ms
attr.sched_period = 1 * 10000000; // each rx thread has a period of 10ms from the starting point attr.sched_period = 1 * 10000000; // each rx thread has a period of 10ms from the starting point
if (sched_setattr(0, &attr, flags) < 0 ){ if (sched_setattr(0, &attr, flags) < 0 ){
perror("[SCHED] eNB RX sched_setattr failed\n"); perror("[SCHED] eNB RX sched_setattr failed\n");
exit(-1); return &eNB_thread_rx_status[proc->subframe];
} }
LOG_I(HW,"[SCHED] eNB RX deadline thread %d(id %ld) started on CPU %d\n", LOG_I( HW, "[SCHED] eNB RX deadline thread %d(id %ld) started on CPU %d\n", proc->subframe, gettid(), sched_getcpu() );
proc->subframe, gettid(),sched_getcpu());
#else #else
LOG_I(HW,"[SCHED][eNB] eNB RX thread %d started on CPU %d\n", LOG_I( HW, "[SCHED][eNB] RX thread %d started on CPU %d\n", proc->subframe, sched_getcpu() );
proc->subframe,sched_getcpu());
#endif
#endif #endif
#endif // RTAI
mlockall(MCL_CURRENT | MCL_FUTURE); mlockall(MCL_CURRENT | MCL_FUTURE);
//rt_set_runnable_on_cpuid(task,1);
//cpuid = rtai_cpuid();
#ifdef HARD_RT #ifdef HARD_RT
rt_make_hard_real_time(); rt_make_hard_real_time();
#endif #endif
while (!oai_exit){ while (!oai_exit) {
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe),0); 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_rx,&proc->mutex_rx);
if (pthread_mutex_lock(&proc->mutex_rx) != 0) { if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
LOG_E(PHY,"[SCHED][eNB] error locking mutex for eNB RX proc %d\n",proc->subframe); LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RX proc %d\n", proc->subframe );
exit_fun( "error locking mutex" );
break;
} }
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_rx,pthread_mutex_trylock(&proc->mutex_rx));
pthread_cond_wait(&proc->cond_rx,&proc->mutex_rx); while (proc->instance_cnt_rx < 0) {
} pthread_cond_wait( &proc->cond_rx, &proc->mutex_rx );
// LOG_I(PHY,"Waking up and unlocking mutex for eNB RX proc %d instance_cnt_rx %d\n",proc->subframe,proc->instance_cnt_rx);
if (pthread_mutex_unlock(&proc->mutex_rx) != 0) {
LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n",proc->subframe);
}
} }
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe),1);
vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx); if (pthread_mutex_unlock(&proc->mutex_rx) != 0) {
start_meas(&softmodem_stats_rx_sf[proc->subframe]); LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n", proc->subframe );
exit_fun( "error unlocking mutex" );
break;
}
vcd_signal_dumper_dump_function_by_name( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 1 );
vcd_signal_dumper_dump_variable_by_name( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx );
start_meas( &softmodem_stats_rx_sf[proc->subframe] );
if (oai_exit) break; if (oai_exit) break;
if ((((PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == TDD )&&(subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_rx)==SF_UL)) || if ((((PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == TDD )&&(subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_rx)==SF_UL)) ||
(PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD))){ (PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.frame_type == FDD))){
phy_procedures_eNB_RX(proc->subframe,PHY_vars_eNB_g[0][proc->CC_id],0,no_relay); phy_procedures_eNB_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay );
} }
if ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_rx)==SF_S)){ if ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms,proc->subframe_rx) == SF_S)){
phy_procedures_eNB_S_RX(proc->subframe,PHY_vars_eNB_g[0][proc->CC_id],0,no_relay); phy_procedures_eNB_S_RX( proc->subframe, PHY_vars_eNB_g[0][proc->CC_id], 0, no_relay );
} }
if (pthread_mutex_lock(&proc->mutex_rx) != 0) { if (pthread_mutex_lock(&proc->mutex_rx) != 0) {
printf("[openair][SCHED][eNB] error locking mutex for eNB RX proc %d\n",proc->subframe); LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB RX proc %d\n", proc->subframe );
exit_fun( "error locking mutex" );
break;
} }
else {
proc->instance_cnt_rx--; proc->instance_cnt_rx--;
if (pthread_mutex_unlock(&proc->mutex_rx) != 0) { if (pthread_mutex_unlock(&proc->mutex_rx) != 0) {
printf("[openair][SCHED][eNB] error unlocking mutex for eNB RX proc %d\n",proc->subframe); LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for eNB RX proc %d\n", proc->subframe );
} exit_fun( "error unlocking mutex" );
break;
} }
proc->frame_rx++; proc->frame_rx++;
...@@ -1197,68 +1183,64 @@ static void * eNB_thread_tx(void *param) { ...@@ -1197,68 +1183,64 @@ static void * eNB_thread_tx(void *param) {
proc->frame_rx=0; proc->frame_rx=0;
} }
stop_meas(&softmodem_stats_rx_sf[proc->subframe]);
vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe),0); stop_meas( &softmodem_stats_rx_sf[proc->subframe] );
vcd_signal_dumper_dump_function_by_name( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX0+(2*proc->subframe), 0 );
#ifdef HARD_RT #ifdef HARD_RT
rt_make_soft_real_time(); rt_make_soft_real_time();
#endif #endif
#ifdef DEBUG_THREADS #ifdef DEBUG_THREADS
printf("Exiting eNB thread RX %d\n",proc->subframe); printf( "Exiting eNB thread RX %d\n", proc->subframe );
#endif #endif
// clean task // clean task
#ifdef RTAI #ifdef RTAI
rt_task_delete(task); rt_task_delete(task);
#else
eNB_thread_rx_status[proc->subframe]=0;
pthread_exit(&eNB_thread_rx_status[proc->subframe]);
#endif #endif
#ifdef DEBUG_THREADS eNB_thread_rx_status[proc->subframe] = 0;
printf("Exiting eNB RX thread %d\n",proc->subframe); return &eNB_thread_rx_status[proc->subframe];
#endif
} }
void init_eNB_proc(void) { void init_eNB_proc(void)
{
int i; int i;
int CC_id; int CC_id;
for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) { for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
for (i=0;i<10;i++) { for (i=0; i<NUM_ENB_THREADS; i++) {
/*set the stack sizw */ // set the stack size
pthread_attr_init (&attr_eNB_proc_tx[CC_id][i]); pthread_attr_init( &attr_eNB_proc_tx[CC_id][i] );
if (pthread_attr_setstacksize(&attr_eNB_proc_tx[CC_id][i],PTHREAD_STACK_MIN) != 0) if (pthread_attr_setstacksize( &attr_eNB_proc_tx[CC_id][i], PTHREAD_STACK_MIN ) != 0)
perror("[ENB_PROC_TX] setting thread stack size failed\n"); perror("[ENB_PROC_TX] setting thread stack size failed\n");
pthread_attr_init( &attr_eNB_proc_rx[CC_id][i] );
pthread_attr_init (&attr_eNB_proc_rx[CC_id][i]); if (pthread_attr_setstacksize( &attr_eNB_proc_rx[CC_id][i], PTHREAD_STACK_MIN ) != 0)
if (pthread_attr_setstacksize(&attr_eNB_proc_rx[CC_id][i],PTHREAD_STACK_MIN) != 0)
perror("[ENB_PROC_RX] setting thread stack size failed\n"); perror("[ENB_PROC_RX] setting thread stack size failed\n");
/* set the kernel scheduling policy and priority */
#ifndef LOWLATENCY #ifndef LOWLATENCY
//attr_dlsch_threads.priority = 1; // set the kernel scheduling policy and priority
sched_param_eNB_proc_tx[CC_id][i].sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; sched_param_eNB_proc_tx[CC_id][i].sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY;
pthread_attr_setschedparam (&attr_eNB_proc_tx[CC_id][i], &sched_param_eNB_proc_tx[CC_id][i]); pthread_attr_setschedparam (&attr_eNB_proc_tx[CC_id][i], &sched_param_eNB_proc_tx[CC_id][i]);
pthread_attr_setschedpolicy (&attr_eNB_proc_tx[CC_id][i], SCHED_FIFO); pthread_attr_setschedpolicy (&attr_eNB_proc_tx[CC_id][i], SCHED_FIFO);
//attr_dlsch_threads.priority = 1;
sched_param_eNB_proc_rx[CC_id][i].sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY; sched_param_eNB_proc_rx[CC_id][i].sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY;
pthread_attr_setschedparam (&attr_eNB_proc_rx[CC_id][i], &sched_param_eNB_proc_rx[CC_id][i]); pthread_attr_setschedparam (&attr_eNB_proc_rx[CC_id][i], &sched_param_eNB_proc_rx[CC_id][i]);
pthread_attr_setschedpolicy (&attr_eNB_proc_rx[CC_id][i], SCHED_FIFO); pthread_attr_setschedpolicy (&attr_eNB_proc_rx[CC_id][i], SCHED_FIFO);
#endif #endif
PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_tx=-1; PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_tx = -1;
PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_rx=-1; PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_rx = -1;
PHY_vars_eNB_g[0][CC_id]->proc[i].subframe=i; PHY_vars_eNB_g[0][CC_id]->proc[i].subframe = i;
PHY_vars_eNB_g[0][CC_id]->proc[i].CC_id = CC_id; PHY_vars_eNB_g[0][CC_id]->proc[i].CC_id = CC_id;
pthread_mutex_init(&PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_tx,NULL); pthread_mutex_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_tx, NULL);
pthread_mutex_init(&PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_rx,NULL); pthread_mutex_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_rx, NULL);
pthread_cond_init(&PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx,NULL); pthread_cond_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx, NULL);
pthread_cond_init(&PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx,NULL); pthread_cond_init( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx, NULL);
pthread_create(&PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx,NULL,eNB_thread_tx,(void*)&PHY_vars_eNB_g[0][CC_id]->proc[i]); pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, NULL, eNB_thread_tx, &PHY_vars_eNB_g[0][CC_id]->proc[i] );
pthread_create(&PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx,NULL,eNB_thread_rx,(void*)&PHY_vars_eNB_g[0][CC_id]->proc[i]); pthread_create( &PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, NULL, eNB_thread_rx, &PHY_vars_eNB_g[0][CC_id]->proc[i] );
PHY_vars_eNB_g[0][CC_id]->proc[i].frame_tx = 0; PHY_vars_eNB_g[0][CC_id]->proc[i].frame_tx = 0;
PHY_vars_eNB_g[0][CC_id]->proc[i].frame_rx = 0; PHY_vars_eNB_g[0][CC_id]->proc[i].frame_rx = 0;
#ifdef EXMIMO #ifdef EXMIMO
...@@ -1289,43 +1271,69 @@ void init_eNB_proc(void) { ...@@ -1289,43 +1271,69 @@ void init_eNB_proc(void) {
} }
} }
void kill_eNB_proc(void) { /*!
* \brief Terminate eNB TX and RX threads.
int i; */
void *status_tx,*status_rx; void kill_eNB_proc(void)
int CC_id; {
int *status;
int result;
for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) for (int CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
for (i=0;i<10;i++) { for (int i=0; i<NUM_ENB_THREADS; i++) {
#ifdef DEBUG_THREADS #ifdef DEBUG_THREADS
printf("Killing TX CC_id %d thread %d\n",CC_id,i); printf( "Killing TX CC_id %d thread %d\n", CC_id, i );
#endif #endif
PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_tx=0;
pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx); PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_tx = 0; // FIXME data race!
pthread_cond_signal( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx );
#ifdef DEBUG_THREADS #ifdef DEBUG_THREADS
printf("Joining eNB TX CC_id %d thread %d...\n",CC_id,i); printf( "Joining eNB TX CC_id %d thread %d...\n", CC_id, i );
#endif #endif
pthread_join(PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx,&status_tx); result = pthread_join( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_tx, (void**)&status );
#ifdef DEBUG_THREADS #ifdef DEBUG_THREADS
if (status_tx) printf("status %p...\n",status_tx); if (result != 0) {
printf( "Error joining thread.\n" );
} else {
if (status) {
printf( "status %d\n", *status );
} else {
printf( "The thread was killed. No status available.\n" );
}
}
#endif #endif
#ifdef DEBUG_THREADS #ifdef DEBUG_THREADS
printf("Killing RX CC_id %d thread %d\n",CC_id,i); printf( "Killing RX CC_id %d thread %d\n", CC_id, i );
#endif #endif
PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_rx=0;
pthread_cond_signal(&PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx); PHY_vars_eNB_g[0][CC_id]->proc[i].instance_cnt_rx = 0; // FIXME data race!
pthread_cond_signal( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx );
#ifdef DEBUG_THREADS #ifdef DEBUG_THREADS
printf("Joining eNB RX CC_id %d thread %d...\n",CC_id,i); printf( "Joining eNB RX CC_id %d thread %d...\n", CC_id, i );
#endif #endif
pthread_join(PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx,&status_rx); result = pthread_join( PHY_vars_eNB_g[0][CC_id]->proc[i].pthread_rx, (void**)&status );
#ifdef DEBUG_THREADS #ifdef DEBUG_THREADS
if (status_rx) printf("status %p...\n",status_rx); if (result != 0) {
printf( "Error joining thread.\n" );
} else {
if (status) {
printf( "status %d\n", *status );
} else {
printf( "The thread was killed. No status available.\n" );
}
}
#endif #endif
pthread_mutex_destroy(&PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_tx);
pthread_mutex_destroy(&PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_rx); pthread_mutex_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_tx );
pthread_cond_destroy(&PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx); pthread_mutex_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].mutex_rx );
pthread_cond_destroy(&PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx); pthread_cond_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_tx );
pthread_cond_destroy( &PHY_vars_eNB_g[0][CC_id]->proc[i].cond_rx );
} }
} }
...@@ -1333,22 +1341,16 @@ void kill_eNB_proc(void) { ...@@ -1333,22 +1341,16 @@ void kill_eNB_proc(void) {
/* This is the main eNB thread. */
int eNB_thread_status;
/*!
static void *eNB_thread(void *arg) * \brief This is the main eNB thread.
* \param arg unused
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
*/
static void* eNB_thread( void* arg )
{ {
#ifdef RTAI UNUSED(arg);
RT_TASK *task; static int eNB_thread_status;
#else
#ifdef LOWLATENCY
struct sched_attr attr;
unsigned int flags = 0;
// unsigned long mask = 1; /* processor 0 */
#endif
#endif
#ifdef EXMIMO #ifdef EXMIMO
unsigned char slot=0; unsigned char slot=0;
...@@ -1375,8 +1377,7 @@ static void *eNB_thread(void *arg) ...@@ -1375,8 +1377,7 @@ static void *eNB_thread(void *arg)
int spp; int spp;
int tx_launched=0; int tx_launched=0;
// int tx_offset; void *rxp[2], *txp[2];
void *rxp[2],*txp[2];
int i; int i;
openair0_timestamp timestamp; openair0_timestamp timestamp;
...@@ -1397,9 +1398,12 @@ static void *eNB_thread(void *arg) ...@@ -1397,9 +1398,12 @@ static void *eNB_thread(void *arg)
*/ */
#ifdef RTAI #ifdef RTAI
task = rt_task_init_schmod(nam2num("eNBmain"), 0, 0, 0, SCHED_FIFO, 0xF); RT_TASK* task = rt_task_init_schmod(nam2num("eNBmain"), 0, 0, 0, SCHED_FIFO, 0xF);
#else #else
#ifdef LOWLATENCY #ifdef LOWLATENCY
struct sched_attr attr;
unsigned int flags = 0;
attr.size = sizeof(attr); attr.size = sizeof(attr);
attr.sched_flags = 0; attr.sched_flags = 0;
attr.sched_nice = 0; attr.sched_nice = 0;
...@@ -1751,14 +1755,13 @@ static void *eNB_thread(void *arg) ...@@ -1751,14 +1755,13 @@ static void *eNB_thread(void *arg)
// clean task // clean task
#ifdef RTAI #ifdef RTAI
rt_task_delete(task); rt_task_delete(task);
#else
eNB_thread_status = 0;
pthread_exit(&eNB_thread_status);
#endif #endif
#ifdef DEBUG_THREADS #ifdef DEBUG_THREADS
printf("eNB_thread deleted. returning\n"); printf("eNB_thread deleted. returning\n");
#endif #endif
return 0;
eNB_thread_status = 0;
return &eNB_thread_status;
} }
...@@ -2119,13 +2122,8 @@ static void get_options (int argc, char **argv) { ...@@ -2119,13 +2122,8 @@ static void get_options (int argc, char **argv) {
} }
} }
int main(int argc, char **argv) { 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,aa,card; int i,aa,card;
#if defined (XFORMS) || defined (EMOS) || defined (EXMIMO) #if defined (XFORMS) || defined (EMOS) || defined (EXMIMO)
void *status; void *status;
...@@ -2868,7 +2866,7 @@ int main(int argc, char **argv) { ...@@ -2868,7 +2866,7 @@ int main(int argc, char **argv) {
#ifdef RTAI #ifdef RTAI
main_eNB_thread = rt_thread_create(eNB_thread, NULL, PTHREAD_STACK_MIN); main_eNB_thread = rt_thread_create(eNB_thread, NULL, PTHREAD_STACK_MIN);
#else #else
error_code = pthread_create(&main_eNB_thread, &attr_dlsch_threads, eNB_thread, NULL); error_code = pthread_create( &main_eNB_thread, &attr_dlsch_threads, eNB_thread, NULL );
if (error_code!= 0) { if (error_code!= 0) {
LOG_D(HW,"[lte-softmodem.c] Could not allocate eNB_thread, error %d\n",error_code); LOG_D(HW,"[lte-softmodem.c] Could not allocate eNB_thread, error %d\n",error_code);
return(error_code); return(error_code);
...@@ -2958,11 +2956,20 @@ int main(int argc, char **argv) { ...@@ -2958,11 +2956,20 @@ int main(int argc, char **argv) {
#ifdef RTAI #ifdef RTAI
rt_thread_join(main_eNB_thread); rt_thread_join(main_eNB_thread);
#else #else
pthread_join(main_eNB_thread,(void**)&eNB_thread_status_p); int *eNB_thread_status_p;
int result = pthread_join( main_eNB_thread, (void**)&eNB_thread_status_p );
#ifdef DEBUG_THREADS #ifdef DEBUG_THREADS
printf("status %d\n",*eNB_thread_status_p); if (result != 0) {
#endif printf( "\nError joining main_eNB_thread.\n" );
#endif } else {
if (eNB_thread_status_p) {
printf( "status %d\n", *eNB_thread_status_p );
} else {
printf( "The thread was killed. No status available.\n");
}
}
#endif // DEBUG_THREADS
#endif // RTAI
if (multi_thread>0) { if (multi_thread>0) {
printf("Killing eNB processing threads\n"); printf("Killing eNB processing threads\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment