Commit 654cffe3 authored by Bartosz Podrygajlo's avatar Bartosz Podrygajlo

Do not start processSlotTx before it is ready to run.

Implement run-to-completion for processSlotTX. This is achieved by using a new
dynamic_barrier_t which allows to specify callback after the first join has been
made.
parent ea0ea2ff
......@@ -43,7 +43,7 @@ include("cmake_targets/CPM.cmake")
option(CCACHE_ACTIVE "CCache" ON)
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND AND CCACHE_ACTIVE)
if(${CMAKE_VERSION} VERSION_LESS "3.4.0")
if(${CMAKE_VERSION} VERSION_LESS "3.4.0")
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
message(STATUS "Found ccache in ${CCACHE_FOUND}. Using ccache. CMake < 3.4")
else()
......@@ -105,13 +105,13 @@ add_list_string_option(CMAKE_BUILD_TYPE "RelWithDebInfo" "Choose the type of bui
# in case /proc/cpuinfo exists we want to inspect available Intrinsics
# -so not to go always through SIMDE emulation
# -so to avoid AVX512 instructions generation by gcc
# -so to avoid AVX512 instructions generation by gcc
if(EXISTS "/proc/cpuinfo" AND NOT CROSS_COMPILE)
file(STRINGS "/proc/cpuinfo" CPUFLAGS REGEX flags LIMIT_COUNT 1)
else()
message(WARNING "did not find /proc/cpuinfo -- not setting any x86-specific compilation variables")
endif()
eval_boolean(AUTODETECT_AVX512 DEFINED CPUFLAGS AND CPUFLAGS MATCHES "avx512")
add_boolean_option(AVX512 ${AUTODETECT_AVX512} "Whether AVX512 intrinsics is available on the host processor" ON)
......@@ -636,7 +636,7 @@ if (cap_FOUND)
target_link_libraries(UTIL PRIVATE cap)
target_compile_definitions(UTIL PRIVATE HAVE_LIB_CAP)
endif()
target_link_libraries(UTIL PUBLIC ${T_LIB} pthread LOG thread-pool utils)
target_link_libraries(UTIL PUBLIC ${T_LIB} pthread LOG thread-pool utils barrier)
set(SECURITY_SRC
${OPENAIR3_DIR}/SECU/secu_defs.c
......@@ -677,7 +677,7 @@ set(SCHED_NR_SRC
${OPENAIR1_DIR}/SCHED_NR/phy_frame_config_nr.c
)
add_library(SCHED_NR_LIB ${SCHED_NR_SRC})
target_link_libraries(SCHED_NR_LIB PRIVATE asn1_nr_rrc_hdrs)
target_link_libraries(SCHED_NR_LIB PRIVATE asn1_nr_rrc_hdrs UTIL)
set(SCHED_SRC_RU
${OPENAIR1_DIR}/SCHED/ru_procedures.c
......@@ -695,7 +695,7 @@ set(SCHED_SRC_UE
${OPENAIR1_DIR}/SCHED_UE/srs_pc.c
)
add_library(SCHED_UE_LIB ${SCHED_SRC_UE})
target_link_libraries(SCHED_UE_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
target_link_libraries(SCHED_UE_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs UTIL)
set(SCHED_SRC_NR_UE
${OPENAIR1_DIR}/SCHED_NR_UE/phy_procedures_nr_ue.c
......@@ -706,7 +706,7 @@ set(SCHED_SRC_NR_UE
${OPENAIR1_DIR}/SCHED_NR_UE/pucch_uci_ue_nr.c
)
add_library(SCHED_NR_UE_LIB ${SCHED_SRC_NR_UE})
target_link_libraries(SCHED_NR_UE_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
target_link_libraries(SCHED_NR_UE_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs UTIL)
# nFAPI
#################################
......@@ -758,7 +758,7 @@ set(NFAPI_USER_SRC
${NFAPI_USER_DIR}/gnb_ind_vars.c
)
add_library(NFAPI_USER_LIB ${NFAPI_USER_SRC})
target_link_libraries(NFAPI_USER_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
target_link_libraries(NFAPI_USER_LIB PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs UTIL)
include_directories(${NFAPI_USER_DIR})
# Layer 1
......@@ -1118,7 +1118,7 @@ set(PHY_SRC_UE ${PHY_SRC_UE} ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_llr_comp
add_library(PHY_COMMON ${PHY_SRC_COMMON})
target_link_libraries(PHY_COMMON PRIVATE shlib_loader)
add_dependencies(PHY_COMMON dfts)
target_link_libraries(PHY_COMMON PRIVATE asn1_lte_rrc_hdrs)
target_link_libraries(PHY_COMMON PRIVATE asn1_lte_rrc_hdrs PUBLIC UTIL)
add_library(PHY ${PHY_SRC})
target_link_libraries(PHY PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
......@@ -1127,7 +1127,7 @@ pkg_check_modules(blas REQUIRED blas)
pkg_check_modules(lapacke REQUIRED lapacke)
add_library(PHY_UE ${PHY_SRC_UE})
target_link_libraries(PHY_UE PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs)
target_link_libraries(PHY_UE PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs UTIL)
# RHEL needs also cblas, but Ubuntu does not have it. So `cblas_LIBRARIES` will
# be empty for Ubuntu, a no-op
pkg_check_modules(cblas cblas)
......@@ -1135,6 +1135,7 @@ target_link_libraries(PHY_UE PRIVATE ${blas_LIBRARIES} ${cblas_LIBRARIES} ${lapa
target_include_directories(PHY_UE PRIVATE ${blas_INCLUDE_DIRS} ${lapacke_INCLUDE_DIRS})
add_library(PHY_NR_COMMON ${PHY_NR_SRC_COMMON})
target_link_libraries(PHY_NR_COMMON PUBLIC UTIL)
add_library(PHY_NR ${PHY_NR_SRC})
target_link_libraries(PHY_NR nr_phy_common nr_common)
......@@ -1147,7 +1148,7 @@ add_library(PHY_NR_UE ${PHY_NR_UE_SRC})
target_link_libraries(PHY_NR_UE PRIVATE asn1_nr_rrc_hdrs nr_phy_common nr_common)
add_library(PHY_RU ${PHY_SRC_RU})
target_link_libraries(PHY_RU PRIVATE asn1_lte_rrc_hdrs)
target_link_libraries(PHY_RU PRIVATE asn1_lte_rrc_hdrs UTIL)
#Library for mex functions
#########################3
......@@ -1216,7 +1217,7 @@ set(NR_SDAP_SRC
${OPENAIR2_DIR}/SDAP/nr_sdap/nr_sdap.c
${OPENAIR2_DIR}/SDAP/nr_sdap/nr_sdap_entity.c
)
set(L2_SRC
${PDCP_DIR}/pdcp.c
${PDCP_DIR}/pdcp_fifo.c
......@@ -2064,7 +2065,7 @@ if(E2_AGENT)
target_link_libraries(nr-cuup PRIVATE e2_agent e2_agent_arg e2_ran_func_cuup)
target_compile_definitions(nr-cuup PRIVATE ${E2AP_VERSION} ${KPM_VERSION} E2_AGENT)
endif()
# nr-uesoftmodem is UE implementation
#######################################
......
......@@ -31,6 +31,16 @@ void dynamic_barrier_init(dynamic_barrier_t* barrier)
barrier->completed_jobs = 0;
}
void dynamic_barrier_reset(dynamic_barrier_t* barrier)
{
barrier->callback = NULL;
if (barrier->callback_arg != NULL) {
free(barrier->callback_arg);
}
barrier->callback_arg = NULL;
barrier->completed_jobs = 0;
}
void dynamic_barrier_join(dynamic_barrier_t* barrier)
{
int ret = pthread_mutex_lock(&barrier->barrier_lock);
......
......@@ -39,6 +39,10 @@ typedef struct dynamic_barrier_t {
/// @param barrier
void dynamic_barrier_init(dynamic_barrier_t* barrier);
/// @brief Reset the barrier
/// @param barrier
void dynamic_barrier_reset(dynamic_barrier_t* barrier);
/// @brief Perform join on the barrier. May run callback if it is already set
/// @param barrier
void dynamic_barrier_join(dynamic_barrier_t* barrier);
......
add_library(nr_common nr_common.c)
target_include_directories(nr_common PUBLIC .)
target_link_libraries(nr_common PRIVATE UTIL)
target_link_libraries(nr_common PUBLIC UTIL)
if (ENABLE_TESTS)
add_subdirectory(tests)
endif()
......@@ -53,7 +53,7 @@ message(STATUS "No specific telnet functions for 4Gue")
message(STATUS "Add 5Gue specific telnet functions in libtelnetsrv_5Gue.so")
add_library(telnetsrv_5Gue MODULE telnetsrv_5Gue_measurements.c)
add_dependencies(telnetsrv telnetsrv_5Gue)
target_link_libraries(telnetsrv_5Gue PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
target_link_libraries(telnetsrv_5Gue PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL)
message(STATUS "Add CI specific telnet functions in libtelnetsrv_ci.so")
add_library(telnetsrv_ci MODULE telnetsrv_ci.c)
......@@ -79,4 +79,3 @@ add_dependencies(telnetsrv telnetsrv_rrc)
set_target_properties(telnetsrv telnetsrv_enb telnetsrv_5Gue telnetsrv_ci telnetsrv_ciUE telnetsrv_bearer telnetsrv_rrc
PROPERTIES LIBRARY_OUTPUT_DIRECTORY ../../..
)
......@@ -99,6 +99,11 @@
static void *NRUE_phy_stub_standalone_pnf_task(void *arg);
static void start_process_slot_tx(void* arg) {
notifiedFIFO_elt_t *newTx = arg;
pushTpool(&(get_nrUE_params()->Tpool), newTx);
}
static size_t dump_L1_UE_meas_stats(PHY_VARS_NR_UE *ue, char *output, size_t max_len)
{
const char *begin = output;
......@@ -486,56 +491,10 @@ void processSlotTX(void *arg)
nr_phy_data_tx_t phy_data = {0};
bool sl_tx_action = false;
// Force sequential execution, even if we launch in // for all slots
// at least ULstatus variable is a pure race condition that is quickly detected by assert() in the code because one thread sets it
// to active, so the other thread try to steal&run the ul work
if (rxtxD->stream_status == STREAM_STATUS_SYNCED) {
notifiedFIFO_elt_t *res = pullNotifiedFIFO(UE->tx_resume_ind_fifo + proc->nr_slot_tx);
delNotifiedFIFO_elt(res);
}
if (UE->if_inst)
UE->if_inst->slot_indication(UE->Mod_id);
LOG_D(PHY,
"SlotTx %d.%d => slot type %d, wait: %d \n",
proc->frame_tx,
proc->nr_slot_tx,
proc->tx_slot_type,
rxtxD->tx_wait_for_dlsch);
if (proc->tx_slot_type == NR_UPLINK_SLOT || proc->tx_slot_type == NR_MIXED_SLOT) {
if (rxtxD->tx_wait_for_dlsch)
LOG_D(PHY, "enter wait for tx, slot %d, nb events to wait %d; ", proc->nr_slot_tx, rxtxD->tx_wait_for_dlsch);
// wait for rx slots to send indication (if any) that DLSCH decoding is finished
for(int i=0; i < rxtxD->tx_wait_for_dlsch; i++) {
notifiedFIFO_elt_t *res = pullNotifiedFIFO(UE->tx_resume_ind_fifo + proc->nr_slot_tx);
delNotifiedFIFO_elt(res);
}
LOG_D(PHY, "completed wait for tx, slot %d\n", proc->nr_slot_tx);
/*
This herafter code is costing some perfomance for a check that should be useless
But, we face today several bugs arround the matching between events in UE->tx_resume_ind_fifo[slot]
and the corresponding tx_wait_for_dlsch[slot]
The algorithm is we accumlate the actions that should end before processing a tx slot in tx_wait_for_dlsch[slot]
later, other threads push events in UE->tx_resume_ind_fifo[slot]
so, the tx encoding starts only when related actions are done (mainly DLSCH ACK/NACK to encode PUCCH)
if there is a bug that misses to send a event in UE->tx_resume_ind_fifo[slot], the process hangs, we detect the issue
if there is a bug that makes a extra event in UE->tx_resume_ind_fifo[slot], and if we drop the hereafter check
the system runs with random race conditions, very hard to debug
Likely we should later remove completly UE->tx_resume_ind_fifo with notifications,
instead,
we may run in place the processSlotTX() when the conditions are met (when a decreasing tx_wait_for_dlsch[slot] will become 0)
It will remove the condition signals (for a thread safe semaphore or counter) and make the system simpler
*/
notifiedFIFO_elt_t *res = pollNotifiedFIFO(UE->tx_resume_ind_fifo + proc->nr_slot_tx);
if (res)
LOG_E(NR_PHY,
"Internal error: extra event on Tx waiting queue for slot %d, event comes from rx slot %d\n",
proc->nr_slot_tx,
*(int *)NotifiedFifoData(res));
if (UE->sl_mode == 2 && proc->tx_slot_type == NR_SIDELINK_SLOT) {
// trigger L2 to run ue_sidelink_scheduler thru IF module
if (UE->if_inst != NULL && UE->if_inst->sl_indication != NULL) {
......@@ -584,13 +543,10 @@ void processSlotTX(void *arg)
}
}
notifiedFIFO_elt_t *newElt = newNotifiedFIFO_elt(sizeof(int), 0, NULL, NULL);
int *msgData = (int *)NotifiedFifoData(newElt);
int slots_per_frame = (UE->sl_mode == 2) ? UE->SL_UE_PHY_PARAMS.sl_frame_params.slots_per_frame
: UE->frame_parms.slots_per_frame;
int newslot = (proc->nr_slot_tx + 1) % slots_per_frame;
*msgData = newslot;
pushNotifiedFIFO(UE->tx_resume_ind_fifo + newslot, newElt);
int next_slot = (proc->nr_slot_tx + 1) % slots_per_frame;
dynamic_barrier_join(&UE->process_slot_tx_barriers[next_slot]);
RU_write(rxtxD, sl_tx_action);
}
......@@ -841,7 +797,7 @@ void *UE_thread(void *arg)
int num_ind_fifo = nb_slot_frame;
for(int i = 0; i < num_ind_fifo; i++) {
initNotifiedFIFO(UE->tx_resume_ind_fifo + i);
dynamic_barrier_init(&UE->process_slot_tx_barriers[i]);
}
int shiftForNextFrame = 0;
int intialSyncOffset = 0;
......@@ -956,9 +912,7 @@ void *UE_thread(void *arg)
// We have resynchronized, maybe after RF loss so we need to purge any existing context
memset(tx_wait_for_dlsch, 0, sizeof(tx_wait_for_dlsch));
for (int i = 0; i < num_ind_fifo; i++) {
notifiedFIFO_elt_t *res;
while ((res = pollNotifiedFIFO(UE->tx_resume_ind_fifo + i)))
delNotifiedFIFO_elt(res);
dynamic_barrier_reset(&UE->process_slot_tx_barriers[i]);
}
continue;
}
......@@ -1056,11 +1010,16 @@ void *UE_thread(void *arg)
curMsgTx->writeBlockSize = writeBlockSize;
curMsgTx->proc.timestamp_tx = writeTimestamp;
curMsgTx->UE = UE;
curMsgTx->tx_wait_for_dlsch = tx_wait_for_dlsch[curMsgTx->proc.nr_slot_tx];
curMsgTx->stream_status = stream_status;
int sync_to_previous_thread = stream_status == STREAM_STATUS_SYNCED ? 1 : 0;
int slot = curMsgTx->proc.nr_slot_tx;
dynamic_barrier_update(&UE->process_slot_tx_barriers[slot],
tx_wait_for_dlsch[slot] + sync_to_previous_thread,
start_process_slot_tx,
newTx);
stream_status = STREAM_STATUS_SYNCED;
tx_wait_for_dlsch[curMsgTx->proc.nr_slot_tx] = 0;
pushTpool(&(get_nrUE_params()->Tpool), newTx);
tx_wait_for_dlsch[slot] = 0;
}
return NULL;
......
......@@ -25,7 +25,6 @@
#include "PHY/defs_eNB.h"
#include "PHY/defs_UE.h"
#include "PHY/defs_gNB.h"
#include "PHY/defs_nr_UE.h"
#include "LTE_SystemInformationBlockType2.h"
//#include "RadioResourceConfigCommonSIB.h"
......
......@@ -53,7 +53,7 @@ if(ENABLE_UESCOPE OR ENABLE_ENBSCOPE OR ENABLE_NRSCOPE)
target_link_libraries(uescope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
add_library(nrscope MODULE nr_phy_scope.c)
target_link_libraries(nrscope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs)
target_link_libraries(nrscope PUBLIC forms PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs UTIL)
# all libraries should be written to root build dir (default creates the same hierarchie under build as existing for sources)
set_target_properties(enbscope uescope nrscope
......
......@@ -50,6 +50,7 @@
#include "common_lib.h"
#include "fapi_nr_ue_interface.h"
#include "assertions.h"
#include "barrier.h"
//#include "openair1/SCHED_NR_UE/defs.h"
#ifdef MEX
......@@ -74,16 +75,6 @@
#define openair_free(y,x) free((y))
#define PAGE_SIZE 4096
#ifdef NR_UNIT_TEST
#define FILE_NAME " "
#define LINE_FILE (0)
#define NR_TST_PHY_PRINTF(...) printf(__VA_ARGS__)
#else
#define FILE_NAME (__FILE__)
#define LINE_FILE (__LINE__)
#define NR_TST_PHY_PRINTF(...)
#endif
#define PAGE_MASK 0xfffff000
#define virt_to_phys(x) (x)
#define openair_sched_exit() exit(-1)
......@@ -530,7 +521,7 @@ typedef struct PHY_VARS_NR_UE_s {
void *phy_sim_pdsch_dl_ch_estimates_ext;
uint8_t *phy_sim_dlsch_b;
notifiedFIFO_t tx_resume_ind_fifo[NR_MAX_SLOTS_PER_FRAME];
dynamic_barrier_t process_slot_tx_barriers[NR_MAX_SLOTS_PER_FRAME];
// Gain change required for automation RX gain change
int adjust_rxgain;
......
......@@ -31,10 +31,19 @@
#include "PHY/defs_nr_common.h"
#include "PHY/defs_gNB.h"
#include "PHY/defs_nr_UE.h"
#include "SCHED_NR/phy_frame_config_nr.h"
#include "common/utils/nr/nr_common.h"
#ifdef NR_UNIT_TEST
#define FILE_NAME " "
#define LINE_FILE (0)
#define NR_TST_PHY_PRINTF(...) printf(__VA_ARGS__)
#else
#define FILE_NAME (__FILE__)
#define LINE_FILE (__LINE__)
#define NR_TST_PHY_PRINTF(...)
#endif
/*******************************************************************
*
* NAME : set_tdd_configuration
......
......@@ -632,18 +632,6 @@ static int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
return 0;
}
// This function release the Tx working thread for one pending information, like dlsch ACK/NACK
static void send_dl_done_to_tx_thread(notifiedFIFO_t *nf, int rx_slot)
{
if (nf) {
notifiedFIFO_elt_t *newElt = newNotifiedFIFO_elt(sizeof(int), 0, NULL, NULL);
// We put rx slot only for tracing purpose
int *msgData = (int *) NotifiedFifoData(newElt);
*msgData = rx_slot;
pushNotifiedFIFO(nf, newElt);
}
}
static uint32_t compute_csi_rm_unav_res(fapi_nr_dl_config_dlsch_pdu_rel15_t *dlsch_config)
{
uint32_t unav_res = 0;
......@@ -737,7 +725,7 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
// don't wait anymore
LOG_E(NR_PHY, "Internal error nr_ue_dlsch_procedure() called but no active cw on slot %d, harq %d\n", nr_slot_rx, harq_pid);
const int ack_nack_slot = (proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) % ue->frame_parms.slots_per_frame;
send_dl_done_to_tx_thread(ue->tx_resume_ind_fifo + ack_nack_slot, proc->nr_slot_rx);
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot]);
return false;
}
......@@ -873,7 +861,7 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
// DLSCH decoding finished! don't wait anymore in Tx process, we know if we should answer ACK/NACK PUCCH
if (dlsch[0].rnti_type == TYPE_C_RNTI_) {
const int ack_nack_slot = (proc->nr_slot_rx + dlsch[0].dlsch_config.k1_feedback) % ue->frame_parms.slots_per_frame;
send_dl_done_to_tx_thread(ue->tx_resume_ind_fifo + ack_nack_slot, proc->nr_slot_rx);
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot]);
}
if (ue->phy_sim_dlsch_b)
......@@ -1152,9 +1140,8 @@ void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_
nr_ue_dlsch_procedures(ue, proc, dlsch, llr, G);
else {
LOG_E(NR_PHY, "Demodulation impossible, internal error\n");
send_dl_done_to_tx_thread(
ue->tx_resume_ind_fifo + (proc->nr_slot_rx + dlsch_config->k1_feedback) % ue->frame_parms.slots_per_frame,
proc->nr_slot_rx);
int ack_nack_slot = (proc->nr_slot_rx + dlsch_config->k1_feedback) % ue->frame_parms.slots_per_frame;
dynamic_barrier_join(&ue->process_slot_tx_barriers[ack_nack_slot]);
LOG_W(NR_PHY, "nr_ue_pdsch_procedures failed in slot %d\n", proc->nr_slot_rx);
}
......
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