Commit 23f8ca6d authored by tyhsu's avatar tyhsu

threading_push

parent bc4e26c7
......@@ -3,7 +3,7 @@
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
......@@ -29,6 +29,18 @@
\note
\warning
*/
/*! \file PHY/defs.h
\brief Based on OAI structure definitions and add structure def. for multi-threads of PHY DL
\author Terng-Yin Hsu, Shao-Ying Yeh (fdragon)
\date 2018
\version 0.1, based on 67df8e0e
\company NCTU
\email: tyhsu@cs.nctu.edu.tw, fdragon.cs96g@g2.nctu.edu.tw
\note
\warning
*/
#ifndef __PHY_DEFS__H__
#define __PHY_DEFS__H__
......@@ -457,6 +469,36 @@ typedef struct {
UE_rxtx_proc_t proc_rxtx[RX_NB_TH];
} UE_proc_t;
// ----------------Part of TX procedure----------------
typedef struct{
pthread_t pthread_m2p;
pthread_cond_t cond_tx;
pthread_mutex_t mutex_tx;
pthread_attr_t attr_m2p;
//=====//
}mac2phy;
typedef struct{
pthread_t pthread_cch;
pthread_cond_t cond_tx;
pthread_mutex_t mutex_tx;
pthread_attr_t attr_cch;
//=====//
relaying_type_t r_type;
int do_pdcch_flag;
PHY_VARS_RN *rn;
}control_channel;
typedef struct{
pthread_t pthread_tx;
pthread_cond_t cond_tx;
pthread_mutex_t mutex_tx;
pthread_attr_t attr_sch;
//=====//
int id;
}multi_share_channel;
// [end] ----------------Part of TX procedure----------------
/// Top-level PHY Data Structure for eNB
typedef struct PHY_VARS_eNB_s {
/// Module ID indicator for this instance
......@@ -682,6 +724,23 @@ typedef struct PHY_VARS_eNB_s {
openair0_device ifdevice;
/// Pointer for ifdevice buffer struct
if_buffer_t ifbuffer;
//---------------- [start] Part of TX procedure----------------
// Thread
mac2phy thread_m2p;
control_channel thread_cch;
multi_share_channel thread_g[2];
//Thread 0 for even,
//Thread 1 for odd
//DONE
volatile uint8_t complete_m2p;
volatile uint8_t complete_dci;
volatile uint8_t complete_cch;
volatile uint8_t complete_sch_SR;
volatile uint8_t complete_pdsch[2];
//---------------- [end] Part of TX procedure----------------
} PHY_VARS_eNB;
......
......@@ -3,7 +3,7 @@
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
......@@ -29,6 +29,17 @@
* \note
* \warning
*/
/*! \file phy_procedures_lte_eNB.c
* \brief Design the function of "phy_procedures_eNB_TX" as PHY-DL master threads
* \author Terng-Yin Hsu, Shao-Ying Yeh (fdragon)
* \date 2018
* \version 0.1, based on 67df8e0e
* \company NCTU
* \email: tyhsu@cs.nctu.edu.tw, fdragon.cs96g@g2.nctu.edu.tw
* \note
* \warning
*/
#include "PHY/defs.h"
#include "PHY/extern.h"
......@@ -75,6 +86,19 @@
#define PUCCH 1
//DLSH thread
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <semaphore.h>
#include <sys/sysinfo.h>
#include <sys/signal.h>
#include <assert.h>
#include <sched.h>
#include <pthread.h>
void exit_fun(const char* s);
extern int exit_openair;
......@@ -1169,25 +1193,25 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
eNB_rxtx_proc_t *proc,
relaying_type_t r_type,
relaying_type_t r_type,
PHY_VARS_RN *rn,
int do_meas,
int do_pdcch_flag)
{
UNUSED(rn);
int frame=proc->frame_tx;
//int frame=proc->frame_tx;
int subframe=proc->subframe_tx;
// uint16_t input_buffer_length;
uint32_t i,j,aa;
uint8_t harq_pid;
DCI_PDU *DCI_pdu;
DCI_PDU DCI_pdu_tmp;
int8_t UE_id=0;
uint8_t num_pdcch_symbols=0;
uint8_t ul_subframe;
uint32_t ul_frame;
//uint32_t i,j,aa;
//uint8_t harq_pid;
//DCI_PDU *DCI_pdu;
//DCI_PDU DCI_pdu_tmp;
//int8_t UE_id=0;
//uint8_t num_pdcch_symbols=0;
//uint8_t ul_subframe;
//uint32_t ul_frame;
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
DCI_ALLOC_t *dci_alloc=(DCI_ALLOC_t *)NULL;
//DCI_ALLOC_t *dci_alloc=(DCI_ALLOC_t *)NULL;
int offset = eNB->CC_id;//proc == &eNB->proc.proc_rxtx[0] ? 0 : 1;
......@@ -1205,328 +1229,27 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
T(T_ENB_PHY_DL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
// If we've dropped the UE, go back to PRACH mode for this UE
if ((frame==0)&&(subframe==0)) {
if (eNB->UE_stats[i].crnti > 0) {
LOG_I(PHY,"UE %d : rnti %x\n",i,eNB->UE_stats[i].crnti);
}
}
if (eNB->UE_stats[i].ulsch_consecutive_errors == ULSCH_max_consecutive_errors) {
LOG_W(PHY,"[eNB %d, CC %d] frame %d, subframe %d, UE %d: ULSCH consecutive error count reached %u, triggering UL Failure\n",
eNB->Mod_id,eNB->CC_id,frame,subframe, i, eNB->UE_stats[i].ulsch_consecutive_errors);
eNB->UE_stats[i].ulsch_consecutive_errors=0;
mac_xface->UL_failure_indication(eNB->Mod_id,
eNB->CC_id,
frame,
eNB->UE_stats[i].crnti,
subframe);
}
}
// Get scheduling info for next subframe
// This is called only for the CC_id = 0 and triggers scheduling for all CC_id's
if (eNB->mac_enabled==1) {
if (eNB->CC_id == 0) {
mac_xface->eNB_dlsch_ulsch_scheduler(eNB->Mod_id,0,frame,subframe);//,1);
}
}
// clear the transmit data array for the current subframe
if (eNB->abstraction_flag==0) {
for (aa=0; aa<fp->nb_antenna_ports_eNB; aa++) {
memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
}
}
if (is_pmch_subframe(frame,subframe,fp)) {
pmch_procedures(eNB,proc,rn,r_type);
}
else {
// this is not a pmch subframe, so generate PSS/SSS/PBCH
common_signal_procedures(eNB,proc);
}
#if defined(SMBV)
// PBCH takes one allocation
if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
if (subframe==0)
smbv_alloc_cnt++;
}
#endif
if (eNB->mac_enabled==1) {
// Parse DCI received from MAC
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
DCI_pdu = mac_xface->get_dci_sdu(eNB->Mod_id,
eNB->CC_id,
frame,
subframe);
}
else {
DCI_pdu = &DCI_pdu_tmp;
#ifdef EMOS_CHANNEL
fill_dci_emos(DCI_pdu,eNB);
#else
fill_dci(DCI_pdu,eNB,proc);
// clear previous allocation information for all UEs
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
if (eNB->dlsch[i][0]){
for (j=0; j<8; j++)
eNB->dlsch[i][0]->harq_processes[j]->round = 0;
}
}
#endif
}
// clear existing ulsch dci allocations before applying info from MAC (this is table
ul_subframe = pdcch_alloc2ul_subframe(fp,subframe);
ul_frame = pdcch_alloc2ul_frame(fp,frame,subframe);
if ((subframe_select(fp,ul_subframe)==SF_UL) ||
(fp->frame_type == FDD)) {
harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
// clear DCI allocation maps for new subframe
for (i=0; i<NUMBER_OF_UE_MAX; i++)
if (eNB->ulsch[i]) {
eNB->ulsch[i]->harq_processes[harq_pid]->dci_alloc=0;
eNB->ulsch[i]->harq_processes[harq_pid]->rar_alloc=0;
}
}
// clear previous allocation information for all UEs
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
if (eNB->dlsch[i][0])
eNB->dlsch[i][0]->subframe_tx[subframe] = 0;
}
/* save old HARQ information needed for PHICH generation */
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
if (eNB->ulsch[i]) {
/* Store first_rb and n_DMRS for correct PHICH generation below.
* For PHICH generation we need "old" values of last scheduling
* for this HARQ process. 'generate_eNB_dlsch_params' below will
* overwrite first_rb and n_DMRS and 'generate_phich_top', done
* after 'generate_eNB_dlsch_params', would use the "new" values
* instead of the "old" ones.
*
* This has been tested for FDD only, may be wrong for TDD.
*
* TODO: maybe we should restructure the code to be sure it
* is done correctly. The main concern is if the code
* changes and first_rb and n_DMRS are modified before
* we reach here, then the PHICH processing will be wrong,
* using wrong first_rb and n_DMRS values to compute
* ngroup_PHICH and nseq_PHICH.
*
* TODO: check if that works with TDD.
*/
if ((subframe_select(fp,ul_subframe)==SF_UL) ||
(fp->frame_type == FDD)) {
harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
eNB->ulsch[i]->harq_processes[harq_pid]->previous_first_rb =
eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
eNB->ulsch[i]->harq_processes[harq_pid]->previous_n_DMRS =
eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS;
}
}
}
// loop over all DCIs for this subframe to generate DLSCH allocations
for (i=0; i<DCI_pdu->Num_dci; i++) {
LOG_D(PHY,"[eNB] Subframe %d: DCI %d/%d : rnti %x, CCEind %d\n",subframe,i,DCI_pdu->Num_dci,DCI_pdu->dci_alloc[i].rnti,DCI_pdu->dci_alloc[i].firstCCE);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->dci_alloc[i].rnti);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->dci_alloc[i].format);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->dci_alloc[i].firstCCE);
dci_alloc = &DCI_pdu->dci_alloc[i];
if ((dci_alloc->rnti<= P_RNTI) &&
(dci_alloc->ra_flag!=1)) {
if (eNB->mac_enabled==1)
UE_id = find_ue((int16_t)dci_alloc->rnti,eNB);
else
UE_id = i;
}
else UE_id=0;
generate_eNB_dlsch_params(eNB,proc,dci_alloc,UE_id);
}
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe);
// Apply physicalConfigDedicated if needed
// This is for UEs that have received this IE, which changes these DL and UL configuration, we apply after a delay for the eNodeB UL parameters
phy_config_dedicated_eNB_step2(eNB);
// Now loop again over the DCIs for UL configuration
for (i=0; i<DCI_pdu->Num_dci; i++) {
dci_alloc = &DCI_pdu->dci_alloc[i];
if (dci_alloc->format == format0) { // this is a ULSCH allocation
if (eNB->mac_enabled==1)
UE_id = find_ue((int16_t)dci_alloc->rnti,eNB);
else
UE_id = i;
if (UE_id<0) { // should not happen, log an error and exit, this is a fatal error
LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",eNB->Mod_id,frame,dci_alloc->rnti);
mac_xface->macphy_exit("FATAL\n");
}
generate_eNB_ulsch_params(eNB,proc,dci_alloc,UE_id);
}
}
// if we have DCI to generate do it now
if (DCI_pdu->Num_dci>0) {
} else { // for emulation!!
eNB->num_ue_spec_dci[(subframe)&1]=0;
eNB->num_common_dci[(subframe)&1]=0;
}
if (eNB->abstraction_flag == 0) {
if (do_pdcch_flag) {
if (DCI_pdu->Num_dci > 0) {
LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (Num_dci=%d)\n",eNB->Mod_id,frame, subframe,
DCI_pdu->Num_dci);
}
num_pdcch_symbols = generate_dci_top(DCI_pdu->Num_dci,
DCI_pdu->dci_alloc,
0,
AMP,
fp,
eNB->common_vars.txdataF[0],
subframe);
}
else {
num_pdcch_symbols = DCI_pdu->num_pdcch_symbols;
LOG_D(PHY,"num_pdcch_symbols %"PRIu8" (Num_dci %d)\n",num_pdcch_symbols,
DCI_pdu->Num_dci);
}
}
#ifdef PHY_ABSTRACTION // FIXME this ifdef seems suspicious
else {
LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_to_emul\n",eNB->Mod_id,frame, subframe);
num_pdcch_symbols = generate_dci_top_emul(eNB,DCI_pdu->Num_dci,DCI_pdu->dci_alloc,subframe);
}
#endif
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->num_pdcch_symbols);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
#if defined(SMBV)
// Sets up PDCCH and DCI table
if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4) && (DCI_pdu->Num_dci>0)) {
LOG_D(PHY,"[SMBV] Frame %3d, SF %d PDCCH, number of DCIs %d\n",frame,subframe,DCI_pdu->Num_dci);
dump_dci(fp,&DCI_pdu->dci_alloc[0]);
smbv_configure_pdcch(smbv_fname,(smbv_frame_cnt*10) + (subframe),num_pdcch_symbols,DCI_pdu->Num_dci);
}
#endif
// Check for SI activity
if ((eNB->dlsch_SI) && (eNB->dlsch_SI->active == 1)) {
pdsch_procedures(eNB,proc,eNB->dlsch_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,num_pdcch_symbols);
#if defined(SMBV)
// Configures the data source of allocation (allocation is configured by DCI)
if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
LOG_D(PHY,"[SMBV] Frame %3d, Configuring SI payload in SF %d alloc %"PRIu8"\n",frame,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt);
smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), DLSCH_pdu, input_buffer_length);
}
#endif
}
// Check for RA activity
if ((eNB->dlsch_ra) && (eNB->dlsch_ra->active == 1)) {
#if defined(SMBV)
// Configures the data source of allocation (allocation is configured by DCI)
if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
LOG_D(PHY,"[SMBV] Frame %3d, Configuring RA payload in SF %d alloc %"PRIu8"\n",frame,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt);
smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), dlsch_input_buffer, input_buffer_length);
}
#endif
LOG_D(PHY,"[eNB %"PRIu8"][RAPROC] Frame %d, subframe %d: Calling generate_dlsch (RA),Msg3 frame %"PRIu32", Msg3 subframe %"PRIu8"\n",
eNB->Mod_id,
frame, subframe,
eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
pdsch_procedures(eNB,proc,eNB->dlsch_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,num_pdcch_symbols);
eNB->dlsch_ra->active = 0;
}
// Now scan UE specific DLSCH
for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++)
{
if ((eNB->dlsch[(uint8_t)UE_id][0])&&
(eNB->dlsch[(uint8_t)UE_id][0]->rnti>0)&&
(eNB->dlsch[(uint8_t)UE_id][0]->active == 1)) {
pdsch_procedures(eNB,proc,eNB->dlsch[(uint8_t)UE_id][0],eNB->dlsch[(uint8_t)UE_id][1],&eNB->UE_stats[(uint32_t)UE_id],0,num_pdcch_symbols);
}
else if ((eNB->dlsch[(uint8_t)UE_id][0])&&
(eNB->dlsch[(uint8_t)UE_id][0]->rnti>0)&&
(eNB->dlsch[(uint8_t)UE_id][0]->active == 0)) {
// clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later)
eNB->dlsch[(uint8_t)UE_id][0]->subframe_tx[subframe]=0;
}
}
// if we have PHICH to generate
if (is_phich_subframe(fp,subframe))
{
generate_phich_top(eNB,
proc,
AMP,
0);
}
/*
if (frame>=10 && subframe>=9) {
write_output("/tmp/txsigF0.m","txsF0", &eNB->common_vars.txdataF[0][0][0],120*eNB->frame_parms.ofdm_symbol_size,1,1);
write_output("/tmp/txsigF1.m","txsF1", &eNB->common_vars.txdataF[0][0][0],120*eNB->frame_parms.ofdm_symbol_size,1,1);
abort();
}
*/
eNB->complete_m2p = 0;
eNB->complete_dci = 0;
eNB->complete_sch_SR = 0;
pthread_cond_signal(&eNB->thread_m2p.cond_tx);
while(eNB->complete_m2p!=1);
eNB->thread_cch.r_type = r_type;
eNB->thread_cch.do_pdcch_flag = do_pdcch_flag;
eNB->thread_cch.rn = rn;
eNB->complete_cch = 0;
pthread_cond_signal(&eNB->thread_cch.cond_tx);
while(eNB->complete_dci!=1);
eNB->complete_pdsch[0]=0;
eNB->complete_pdsch[1]=0;
pthread_cond_signal(&eNB->thread_g[0].cond_tx);
pthread_cond_signal(&eNB->thread_g[1].cond_tx);
while(!eNB->complete_pdsch[0]||!eNB->complete_pdsch[1]);
while(eNB->complete_cch!=1);
while(eNB->complete_sch_SR!=1);
#ifdef EMOS
phy_procedures_emos_eNB_TX(subframe, eNB);
......
......@@ -3,7 +3,7 @@
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
......@@ -29,6 +29,18 @@
* \note
* \warning
*/
/*! \file lte-enb.c
* \brief Based on top-level threads for eNodeB and include multi-threads of PHY DL
* \author Terng-Yin Hsu, Shao-Ying Yeh (fdragon)
* \date 2018
* \version 0.1, based on 67df8e0e
* \company NCTU
* \email: tyhsu@cs.nctu.edu.tw, fdragon.cs96g@g2.nctu.edu.tw
* \note
* \warning
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
......@@ -45,6 +57,12 @@
#include <sys/sysinfo.h>
#include "rt_wrapper.h"
// DLSH thread
#include <semaphore.h>
#include <assert.h>
#include <pthread.h>
//=====
#include "time_utils.h"
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
......@@ -1748,6 +1766,539 @@ static void* eNB_thread_single( void* param ) {
extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *);
extern void init_td_thread(PHY_VARS_eNB *, pthread_attr_t *);
extern void init_te_thread(PHY_VARS_eNB *, pthread_attr_t *);
extern void pdsch_procedures(PHY_VARS_eNB *,eNB_rxtx_proc_t *,LTE_eNB_DLSCH_t *, LTE_eNB_DLSCH_t *,LTE_eNB_UE_stats *,int ,int );
extern void pmch_procedures(PHY_VARS_eNB *,eNB_rxtx_proc_t *,PHY_VARS_RN *,relaying_type_t );
extern void common_signal_procedures (PHY_VARS_eNB *,eNB_rxtx_proc_t *);
extern void generate_eNB_dlsch_params(PHY_VARS_eNB *,eNB_rxtx_proc_t *,DCI_ALLOC_t *,const int );
extern void generate_eNB_ulsch_params(PHY_VARS_eNB *,eNB_rxtx_proc_t *,DCI_ALLOC_t *,const int );
//----------------Part of TX procedure----------------
static void *mac2phy_proc(void *ptr){
PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][0];
eNB_rxtx_proc_t *proc;
int frame;
int subframe;
uint32_t i,j,aa;
uint8_t harq_pid;
DCI_PDU *DCI_pdu;
DCI_PDU DCI_pdu_tmp;
int8_t UE_id=0;
uint8_t num_pdcch_symbols=0;
uint8_t ul_subframe;
uint32_t ul_frame;
LTE_DL_FRAME_PARMS *fp;
DCI_ALLOC_t *dci_alloc=(DCI_ALLOC_t *)NULL;
static int mac2phy_proc_status = 0;
/**********************************************************************/
cpu_set_t cpuset;
//the CPU we whant to use
int cpu = 1;
int s;
CPU_ZERO(&cpuset); //clears the cpuset
CPU_SET( cpu , &cpuset); //set CPU 0~7 on 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");
}
s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
if (s != 0) {
perror( "pthread_getaffinity_np");
exit_fun("Error getting processor affinity ");
}
printf("[SCHED][eNB] MAC to PHY thread started on CPU %d TID %ld\n",sched_getcpu(),gettid());
/**********************************************************************/
while(!oai_exit){
// wait signal
while(pthread_cond_wait(&eNB->thread_m2p.cond_tx, &eNB->thread_m2p.mutex_tx)!=0);
// start mac2phy
proc = &eNB->proc.proc_rxtx[0];
fp=&eNB->frame_parms;
frame = proc->frame_tx;
subframe = proc->subframe_tx;
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
// If we've dropped the UE, go back to PRACH mode for this UE
if ((frame==0)&&(subframe==0)) {
if (eNB->UE_stats[i].crnti > 0) {
LOG_I(PHY,"UE %d : rnti %x\n",i,eNB->UE_stats[i].crnti);
}
}
if (eNB->UE_stats[i].ulsch_consecutive_errors == ULSCH_max_consecutive_errors) {
LOG_W(PHY,"[eNB %d, CC %d] frame %d, subframe %d, UE %d: ULSCH consecutive error count reached %u, triggering UL Failure\n",
eNB->Mod_id,eNB->CC_id,frame,subframe, i, eNB->UE_stats[i].ulsch_consecutive_errors);
eNB->UE_stats[i].ulsch_consecutive_errors=0;
mac_xface->UL_failure_indication(eNB->Mod_id,
eNB->CC_id,
frame,
eNB->UE_stats[i].crnti,
subframe);
}
}
// Get scheduling info for next subframe
// This is called only for the CC_id = 0 and triggers scheduling for all CC_id's
if (eNB->mac_enabled==1) {
if (eNB->CC_id == 0) {
mac_xface->eNB_dlsch_ulsch_scheduler(eNB->Mod_id,0,frame,subframe);//,1);
}
}
// clear the transmit data array for the current subframe
if (eNB->abstraction_flag==0) {
for (aa=0; aa<fp->nb_antenna_ports_eNB; aa++) {
memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
}
}
eNB->complete_m2p = 1; ///////////////////////////////////////
if (eNB->mac_enabled==1) {
// Parse DCI received from MAC
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
DCI_pdu = mac_xface->get_dci_sdu(eNB->Mod_id,
eNB->CC_id,
frame,
subframe);
}
else {
DCI_pdu = &DCI_pdu_tmp;
#ifdef EMOS_CHANNEL
fill_dci_emos(DCI_pdu,eNB);
#else
fill_dci(DCI_pdu,eNB,proc);
// clear previous allocation information for all UEs
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
if (eNB->dlsch[i][0]){
for (j=0; j<8; j++)
eNB->dlsch[i][0]->harq_processes[j]->round = 0;
}
}
#endif
}
// clear existing ulsch dci allocations before applying info from MAC (this is table
ul_subframe = pdcch_alloc2ul_subframe(fp,subframe);
ul_frame = pdcch_alloc2ul_frame(fp,frame,subframe);
if ((subframe_select(fp,ul_subframe)==SF_UL) ||
(fp->frame_type == FDD)) {
harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
// clear DCI allocation maps for new subframe
for (i=0; i<NUMBER_OF_UE_MAX; i++)
if (eNB->ulsch[i]) {
eNB->ulsch[i]->harq_processes[harq_pid]->dci_alloc=0;
eNB->ulsch[i]->harq_processes[harq_pid]->rar_alloc=0;
}
}
// clear previous allocation information for all UEs
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
if (eNB->dlsch[i][0])
eNB->dlsch[i][0]->subframe_tx[subframe] = 0;
}
/* save old HARQ information needed for PHICH generation */
for (i=0; i<NUMBER_OF_UE_MAX; i++) {
if (eNB->ulsch[i]) {
/* Store first_rb and n_DMRS for correct PHICH generation below.
* For PHICH generation we need "old" values of last scheduling
* for this HARQ process. 'generate_eNB_dlsch_params' below will
* overwrite first_rb and n_DMRS and 'generate_phich_top', done
* after 'generate_eNB_dlsch_params', would use the "new" values
* instead of the "old" ones.
*
* This has been tested for FDD only, may be wrong for TDD.
*
* TODO: maybe we should restructure the code to be sure it
* is done correctly. The main concern is if the code
* changes and first_rb and n_DMRS are modified before
* we reach here, then the PHICH processing will be wrong,
* using wrong first_rb and n_DMRS values to compute
* ngroup_PHICH and nseq_PHICH.
*
* TODO: check if that works with TDD.
*/
if ((subframe_select(fp,ul_subframe)==SF_UL) ||
(fp->frame_type == FDD)) {
harq_pid = subframe2harq_pid(fp,ul_frame,ul_subframe);
eNB->ulsch[i]->harq_processes[harq_pid]->previous_first_rb =
eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
eNB->ulsch[i]->harq_processes[harq_pid]->previous_n_DMRS =
eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS;
}
}
}
/*///////////////////////////////////////////////
num_pdcch_symbols = DCI_pdu->num_pdcch_symbols;
LOG_D(PHY,"num_pdcch_symbols %"PRIu8",(dci common %"PRIu8", dci uespec %"PRIu8"\n",num_pdcch_symbols,
DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci);
#if defined(SMBV)
// Sets up PDCCH and DCI table
if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4) && ((DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci)>0)) {
LOG_D(PHY,"[SMBV] Frame %3d, SF %d PDCCH, number of DCIs %d\n",frame,subframe,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci);
dump_dci(fp,&DCI_pdu->dci_alloc[0]);
smbv_configure_pdcch(smbv_fname,(smbv_frame_cnt*10) + (subframe),num_pdcch_symbols,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci);
}
#endif
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->num_pdcch_symbols);
///////////////////////////////////////////////*/
// loop over all DCIs for this subframe to generate DLSCH allocations
for (i=0; i<DCI_pdu->Num_dci; i++) {
LOG_D(PHY,"[eNB] Subframe %d: DCI %d/%d : rnti %x, CCEind %d\n",subframe,i,DCI_pdu->Num_dci,DCI_pdu->dci_alloc[i].rnti,DCI_pdu->dci_alloc[i].firstCCE);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->dci_alloc[i].rnti);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->dci_alloc[i].format);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,DCI_pdu->dci_alloc[i].firstCCE);
dci_alloc = &DCI_pdu->dci_alloc[i];
if ((dci_alloc->rnti<= P_RNTI) &&
(dci_alloc->ra_flag!=1)) {
if (eNB->mac_enabled==1)
UE_id = find_ue((int16_t)dci_alloc->rnti,eNB);
else
UE_id = i;
}
else UE_id=0;
generate_eNB_dlsch_params(eNB,proc,dci_alloc,UE_id);
}
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_DCI_INFO,(frame*10)+subframe);
// Apply physicalConfigDedicated if needed
// This is for UEs that have received this IE, which changes these DL and UL configuration, we apply after a delay for the eNodeB UL parameters
phy_config_dedicated_eNB_step2(eNB);
// Now loop again over the DCIs for UL configuration
for (i=0; i<DCI_pdu->Num_dci; i++) {
dci_alloc = &DCI_pdu->dci_alloc[i];
if (dci_alloc->format == format0) { // this is a ULSCH allocation
if (eNB->mac_enabled==1)
UE_id = find_ue((int16_t)dci_alloc->rnti,eNB);
else
UE_id = i;
if (UE_id<0) { // should not happen, log an error and exit, this is a fatal error
LOG_E(PHY,"[eNB %"PRIu8"] Frame %d: Unknown UE_id for rnti %"PRIx16"\n",eNB->Mod_id,frame,dci_alloc->rnti);
mac_xface->macphy_exit("FATAL\n");
}
generate_eNB_ulsch_params(eNB,proc,dci_alloc,UE_id);
}
}
// if we have DCI to generate do it now
if (DCI_pdu->Num_dci>0) {
} else { // for emulation!!
eNB->num_ue_spec_dci[(subframe)&1]=0;
eNB->num_common_dci[(subframe)&1]=0;
}
eNB->complete_dci = 1; ///////////////////////////////////////
num_pdcch_symbols = get_num_pdcch_symbols(DCI_pdu->Num_dci,DCI_pdu->dci_alloc,fp,subframe);
// Check for SI activity
if ((eNB->dlsch_SI) && (eNB->dlsch_SI->active == 1)) {
pdsch_procedures(eNB,proc,eNB->dlsch_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,num_pdcch_symbols);
#if defined(SMBV)
// Configures the data source of allocation (allocation is configured by DCI)
if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
LOG_D(PHY,"[SMBV] Frame %3d, Configuring SI payload in SF %d alloc %"PRIu8"\n",frame,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt);
smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), DLSCH_pdu, input_buffer_length);
}
#endif
}
// Check for RA activity
if ((eNB->dlsch_ra) && (eNB->dlsch_ra->active == 1)) {
#if defined(SMBV)
// Configures the data source of allocation (allocation is configured by DCI)
if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
LOG_D(PHY,"[SMBV] Frame %3d, Configuring RA payload in SF %d alloc %"PRIu8"\n",frame,(smbv_frame_cnt*10) + (subframe),smbv_alloc_cnt);
smbv_configure_datalist_for_alloc(smbv_fname, smbv_alloc_cnt++, (smbv_frame_cnt*10) + (subframe), dlsch_input_buffer, input_buffer_length);
}
#endif
LOG_D(PHY,"[eNB %"PRIu8"][RAPROC] Frame %d, subframe %d: Calling generate_dlsch (RA),Msg3 frame %"PRIu32", Msg3 subframe %"PRIu8"\n",
eNB->Mod_id,
frame, subframe,
eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
pdsch_procedures(eNB,proc,eNB->dlsch_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,num_pdcch_symbols);
eNB->dlsch_ra->active = 0;
}
eNB->complete_sch_SR = 1; ///////////////////////////////////////
}
printf( "Exiting eNB thread mac2phy\n");
return &mac2phy_proc_status;
}
static void *cch_proc(void *ptr){
control_channel *cch = (control_channel*)ptr;
PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][0];
eNB_rxtx_proc_t *proc;
relaying_type_t r_type;
PHY_VARS_RN *rn;
int frame;
int subframe;
// uint32_t i,j;
DCI_PDU *DCI_pdu;
DCI_PDU DCI_pdu_tmp;
uint8_t num_pdcch_symbols=0;
LTE_DL_FRAME_PARMS *fp;
static int control_channel_status = 0;
int do_pdcch_flag;
/**********************************************************************/
cpu_set_t cpuset;
//the CPU we whant to use
int cpu = 2;
int s;
CPU_ZERO(&cpuset); //clears the cpuset
CPU_SET( cpu , &cpuset); //set CPU 0~7 on 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");
}
s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
if (s != 0) {
perror( "pthread_getaffinity_np");
exit_fun("Error getting processor affinity ");
}
printf("[SCHED][eNB] Control_channel thread started on CPU %d TID %ld\n",sched_getcpu(),gettid());
/**********************************************************************/
while(!oai_exit)
{
// wait signal
while(pthread_cond_wait(&eNB->thread_cch.cond_tx, &eNB->thread_cch.mutex_tx)!=0);
// start cch
proc = &eNB->proc.proc_rxtx[0];
fp=&eNB->frame_parms;
frame = proc->frame_tx;
subframe = proc->subframe_tx;
r_type = cch->r_type;
do_pdcch_flag = cch->do_pdcch_flag;
rn = cch->rn;
UNUSED(rn);
if (is_pmch_subframe(frame,subframe,fp)) {
pmch_procedures(eNB,proc,rn,r_type);
}
else {
// this is not a pmch subframe, so generate PSS/SSS/PBCH
common_signal_procedures(eNB,proc);
}
#if defined(SMBV)
// PBCH takes one allocation
if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4)) {
if (subframe==0)
smbv_alloc_cnt++;
}
#endif
if (eNB->mac_enabled==1) {
// Parse DCI received from MAC
DCI_pdu = mac_xface->get_dci_sdu(eNB->Mod_id,
eNB->CC_id,
frame,
subframe);
}
else {
DCI_pdu = &DCI_pdu_tmp;
#ifdef EMOS_CHANNEL
fill_dci_emos(DCI_pdu,eNB);
#else
fill_dci(DCI_pdu,eNB,proc);
#endif
}
if (eNB->abstraction_flag == 0) {
if (do_pdcch_flag) {
if (DCI_pdu->Num_dci > 0) {
LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (Num_dci=%d)\n",eNB->Mod_id,frame, subframe,
DCI_pdu->Num_dci);
}
num_pdcch_symbols = generate_dci_top(DCI_pdu->Num_dci,
DCI_pdu->dci_alloc,
0,
AMP,
fp,
eNB->common_vars.txdataF[0],
subframe);
}
else {
num_pdcch_symbols = DCI_pdu->num_pdcch_symbols;
LOG_D(PHY,"num_pdcch_symbols %"PRIu8" (Num_dci %d)\n",num_pdcch_symbols,
DCI_pdu->Num_dci);
}
}
#ifdef PHY_ABSTRACTION // FIXME this ifdef seems suspicious
else {
LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_to_emul\n",eNB->Mod_id,frame, subframe);
num_pdcch_symbols = generate_dci_top_emul(eNB,DCI_pdu->Num_dci,DCI_pdu->dci_alloc,subframe);
}
#endif
#if defined(SMBV)
// Sets up PDCCH and DCI table
if (smbv_is_config_frame(frame) && (smbv_frame_cnt < 4) && (DCI_pdu->Num_dci>0)) {
LOG_D(PHY,"[SMBV] Frame %3d, SF %d PDCCH, number of DCIs %d\n",frame,subframe,DCI_pdu->Num_dci);
dump_dci(fp,&DCI_pdu->dci_alloc[0]);
smbv_configure_pdcch(smbv_fname,(smbv_frame_cnt*10) + (subframe),num_pdcch_symbols,DCI_pdu->Num_dci);
}
#endif
// if we have PHICH to generate
if (is_phich_subframe(fp,subframe))
{
generate_phich_top(eNB,
proc,
AMP,
0);
}
eNB->complete_cch = 1;
}
printf( "Exiting eNB thread control_channel\n");
return &control_channel_status;
}
static void *multi_sch_proc(void *ptr){
multi_share_channel *sch =(multi_share_channel*) ptr;
PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][0];
eNB_rxtx_proc_t *proc;
int frame;
int subframe;
DCI_PDU *DCI_pdu;
DCI_PDU DCI_pdu_tmp;
int UE_id=0;
int num_pdcch_symbols=0;
LTE_DL_FRAME_PARMS *fp;
static int multi_sch_proc_status = 0;
/**********************************************************************/
cpu_set_t cpuset;
//the CPU we whant to use
int cpu = 3+UE_id;
int s;
CPU_ZERO(&cpuset); //clears the cpuset
CPU_SET( cpu , &cpuset); //set CPU 0~7 on 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");
}
s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
if (s != 0) {
perror( "pthread_getaffinity_np");
exit_fun("Error getting processor affinity ");
}
printf("[SCHED][eNB] PDSCH thread %d started on CPU %d TID %ld\n",UE_id,sched_getcpu(),gettid());
/**********************************************************************/
while(!oai_exit){
// wait signal
while(pthread_cond_wait(&eNB->thread_g[sch->id].cond_tx,&eNB->thread_g[sch->id].mutex_tx)!=0);
// start sch
proc=&eNB->proc.proc_rxtx[0];
frame = proc->frame_tx;
subframe = proc->subframe_tx;
fp=&eNB->frame_parms;
if (eNB->mac_enabled==1) {
// Parse DCI received from MAC
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
DCI_pdu = mac_xface->get_dci_sdu(eNB->Mod_id,
eNB->CC_id,
frame,
subframe);
}
else {
DCI_pdu = &DCI_pdu_tmp;
#ifdef EMOS_CHANNEL
fill_dci_emos(DCI_pdu,eNB);
#else
fill_dci(DCI_pdu,eNB,proc);
#endif
}
num_pdcch_symbols = get_num_pdcch_symbols(DCI_pdu->Num_dci,DCI_pdu->dci_alloc,fp,subframe);
// Now scan UE specific DLSCH
for (UE_id=sch->id; UE_id<NUMBER_OF_UE_MAX; UE_id+=2)
{
if ((eNB->dlsch[(uint8_t)UE_id][0])&&
(eNB->dlsch[(uint8_t)UE_id][0]->rnti>0)&&
(eNB->dlsch[(uint8_t)UE_id][0]->active == 1)) {
pdsch_procedures(eNB,proc,eNB->dlsch[(uint8_t)UE_id][0],eNB->dlsch[(uint8_t)UE_id][1],&eNB->UE_stats[(uint32_t)UE_id],0,num_pdcch_symbols);
}
else if ((eNB->dlsch[(uint8_t)UE_id][0])&&
(eNB->dlsch[(uint8_t)UE_id][0]->rnti>0)&&
(eNB->dlsch[(uint8_t)UE_id][0]->active == 0)) {
// clear subframe TX flag since UE is not scheduled for PDSCH in this subframe (so that we don't look for PUCCH later)
eNB->dlsch[(uint8_t)UE_id][0]->subframe_tx[subframe]=0;
}
}
eNB->complete_pdsch[sch->id]=1;
}
printf( "Exiting eNB thread multi_sch_proc %d\n",sch->id);
multi_sch_proc_status=0;
return &multi_sch_proc_status;
}
// ===================================================
void init_eNB_proc(int inst) {
......@@ -1793,6 +2344,18 @@ void init_eNB_proc(int inst) {
pthread_cond_init( &proc->cond_FH, NULL);
pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
pthread_cond_init( &proc->cond_synch,NULL);
//----------------Part of TX procedure----------------
pthread_mutex_init( &eNB->thread_m2p.mutex_tx, NULL);
pthread_mutex_init( &(eNB->thread_cch.mutex_tx), NULL);
pthread_mutex_init( &eNB->thread_g[0].mutex_tx, NULL);
pthread_mutex_init( &eNB->thread_g[1].mutex_tx, NULL);
pthread_cond_init( &eNB->thread_m2p.cond_tx, NULL);
pthread_cond_init( &(eNB->thread_cch.cond_tx), NULL);
pthread_cond_init( &eNB->thread_g[0].cond_tx, NULL);
pthread_cond_init( &eNB->thread_g[1].cond_tx, NULL);
//====================================================
pthread_attr_init( &proc->attr_FH);
pthread_attr_init( &proc->attr_prach);
......@@ -1804,6 +2367,14 @@ void init_eNB_proc(int inst) {
pthread_attr_init( &proc->attr_te);
pthread_attr_init( &proc_rxtx[0].attr_rxtx);
pthread_attr_init( &proc_rxtx[1].attr_rxtx);
//----------------Part of TX procedure----------------
pthread_attr_init( &eNB->thread_m2p.attr_m2p);
pthread_attr_init( &eNB->thread_cch.attr_cch);
pthread_attr_init( &eNB->thread_g[0].attr_sch);
pthread_attr_init( &eNB->thread_g[1].attr_sch);
//====================================================
#ifndef DEADLINE_SCHEDULER
attr0 = &proc_rxtx[0].attr_rxtx;
attr1 = &proc_rxtx[1].attr_rxtx;
......@@ -1836,8 +2407,16 @@ void init_eNB_proc(int inst) {
pthread_create( &proc->pthread_asynch_rxtx, attr_asynch, eNB_thread_asynch_rxtx, &eNB->proc );
//----------------Part of TX procedure----------------
pthread_create(&(eNB->thread_m2p.pthread_m2p),&eNB->thread_m2p.attr_m2p,mac2phy_proc,NULL);
pthread_create(&(eNB->thread_cch.pthread_cch),&eNB->thread_cch.attr_cch,cch_proc,&eNB->thread_cch);
pthread_create(&(eNB->thread_g[0].pthread_tx),&eNB->thread_g[0].attr_sch,multi_sch_proc,&eNB->thread_g[0]);
pthread_create(&(eNB->thread_g[1].pthread_tx),&eNB->thread_g[1].attr_sch,multi_sch_proc,&eNB->thread_g[1]);
//====================================================
char name[16];
char name[32];
if (eNB->single_thread_flag == 0) {
snprintf( name, sizeof(name), "RXTX0 %d", i );
pthread_setname_np( proc_rxtx[0].pthread_rxtx, name );
......@@ -1850,6 +2429,17 @@ void init_eNB_proc(int inst) {
snprintf( name, sizeof(name), " %d", i );
pthread_setname_np( proc->pthread_single, name );
}
//----------------Part of TX procedure----------------
snprintf( name, sizeof(name), "MAC to PHY thread");
pthread_setname_np(eNB->thread_m2p.pthread_m2p, name );
snprintf( name, sizeof(name), "Control_channel thread");
pthread_setname_np(eNB->thread_cch.pthread_cch, name );
snprintf( name, sizeof(name), "PDSCH thread 0");
pthread_setname_np(eNB->thread_g[0].pthread_tx, name );
snprintf( name, sizeof(name), "PDSCH thread 1");
pthread_setname_np(eNB->thread_g[1].pthread_tx, name );
//====================================================
}
//for multiple CCs: setup master and slaves
......@@ -1905,6 +2495,13 @@ void kill_eNB_proc(int inst) {
pthread_cond_signal( &proc->cond_prach );
pthread_cond_signal( &proc->cond_FH );
pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
//----------------Part of TX procedure----------------
pthread_cond_signal(&eNB->thread_m2p.cond_tx);
pthread_cond_signal(&eNB->thread_cch.cond_tx);
pthread_cond_signal(&eNB->thread_g[0].cond_tx);
pthread_cond_signal(&eNB->thread_g[1].cond_tx);
//====================================================
pthread_join( proc->pthread_FH, (void**)&status );
pthread_mutex_destroy( &proc->mutex_FH );
......@@ -1920,6 +2517,24 @@ void kill_eNB_proc(int inst) {
pthread_mutex_destroy( &proc_rxtx[i].mutex_rxtx );
pthread_cond_destroy( &proc_rxtx[i].cond_rxtx );
}
//----------------Part of TX procedure----------------
pthread_join(eNB->thread_m2p.pthread_m2p,(void**)&status);
pthread_mutex_destroy(&eNB->thread_m2p.mutex_tx);
pthread_cond_destroy(&eNB->thread_m2p.cond_tx);
pthread_join(eNB->thread_cch.pthread_cch,(void**)&status);
pthread_mutex_destroy(&eNB->thread_cch.mutex_tx);
pthread_cond_destroy(&eNB->thread_cch.cond_tx);
pthread_join(eNB->thread_g[0].pthread_tx,(void**)&status);
pthread_mutex_destroy( &(eNB->thread_g[0].mutex_tx) );
pthread_cond_destroy( &(eNB->thread_g[0].cond_tx) );
pthread_join(eNB->thread_g[1].pthread_tx,(void**)&status);
pthread_mutex_destroy( &(eNB->thread_g[1].mutex_tx) );
pthread_cond_destroy( &(eNB->thread_g[1].cond_tx) );
//====================================================
}
}
......@@ -2075,6 +2690,11 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst
eNB->ts_offset = 0;
eNB->in_synch = 0;
eNB->is_slave = (wait_for_sync>0) ? 1 : 0;
//----------------Part of TX procedure----------------
eNB->thread_g[0].id = 0;
eNB->thread_g[1].id = 1;
//====================================================
#ifndef OCP_FRAMEWORK
......
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