From 6b79dc9ac30843b8af9a23c1055b83e7997e5b6a Mon Sep 17 00:00:00 2001 From: "Wilson W.K. Thong" <wilsonthong@astri.org> Date: Wed, 21 Dec 2016 10:29:47 +0800 Subject: [PATCH] fixing crash due to de-qeueueing the same PDCP SDU twice by two different threads see issue #164 --- openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c | 62 +++++++++++++++++++----- 1 file changed, 51 insertions(+), 11 deletions(-) diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c index 3a99c9acca..8a73c36728 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c @@ -41,6 +41,7 @@ extern int otg_enabled; #include "pdcp_primitives.h" #ifdef USER_MODE +#include <pthread.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> @@ -90,6 +91,21 @@ extern Packet_OTG_List_t *otg_pdcp_buffer; # include "gtpv1u_eNB_task.h" #endif +/* Prevent de-queueing the same PDCP SDU from the queue twice + * by multiple threads. This has happened in TDD when thread-odd + * is flushing a PDCP SDU after UE_RX() processing; whereas + * thread-even is at a special-subframe, skips the UE_RX() process + * and goes straight to the PDCP SDU flushing. The 2nd flushing + * dequeues the same SDU again causing unexpected behavior. + * + * comment out the MACRO below to disable this protection + */ +#define PDCP_SDU_FLUSH_LOCK + +#ifdef PDCP_SDU_FLUSH_LOCK +static pthread_mutex_t mtex = PTHREAD_MUTEX_INITIALIZER; +#endif + pdcp_data_req_header_t pdcp_read_header_g; //----------------------------------------------------------------------------- @@ -97,21 +113,13 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const ctxt_pP) { //----------------------------------------------------------------------------- - mem_block_t *sdu_p = list_get_head (&pdcp_sdu_list); - int bytes_wrote = 0; - int pdcp_nb_sdu_sent = 0; - uint8_t cont = 1; -#if defined(LINK_ENB_PDCP_TO_GTPV1U) - //MessageDef *message_p = NULL; -#endif - -#if defined(PDCP_USE_NETLINK) && defined(LINUX) +//#if defined(PDCP_USE_NETLINK) && defined(LINUX) int ret = 0; -#endif +//#endif #ifdef DEBUG_PDCP_FIFO_FLUSH_SDU #define THREAD_NAME_LEN 16 - char threadname[THREAD_NAME_LEN]; + static char threadname[THREAD_NAME_LEN]; ret = pthread_getname_np(pthread_self(), threadname, THREAD_NAME_LEN); if (ret != 0) { @@ -121,6 +129,34 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const ctxt_pP) #undef THREAD_NAME_LEN #endif +#ifdef PDCP_SDU_FLUSH_LOCK + ret = pthread_mutex_trylock(&mtex); + if (ret == EBUSY) { +#ifdef DEBUG_PDCP_FIFO_FLUSH_SDU + LOG_W(PDCP, "[%s] at SFN/SF=%d/%d wait for PDCP FIFO to be unlocked\n", + threadname, ctxt_pP->frame, ctxt_pP->subframe); +#endif + if (pthread_mutex_lock(&mtex)) { + exit_fun("PDCP_SDU_FLUSH_LOCK lock error!"); + } +#ifdef DEBUG_PDCP_FIFO_FLUSH_SDU + LOG_I(PDCP, "[%s] at SFN/SF=%d/%d PDCP FIFO is unlocked\n", + threadname, ctxt_pP->frame, ctxt_pP->subframe); +#endif + } else if (ret != 0) { + exit_fun("PDCP_SDU_FLUSH_LOCK trylock error!"); + } + +#endif + + mem_block_t *sdu_p = list_get_head (&pdcp_sdu_list); + int bytes_wrote = 0; + int pdcp_nb_sdu_sent = 0; + uint8_t cont = 1; +#if defined(LINK_ENB_PDCP_TO_GTPV1U) + //MessageDef *message_p = NULL; +#endif + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_FIFO_FLUSH, 1 ); while (sdu_p && cont) { @@ -332,6 +368,10 @@ int pdcp_fifo_flush_sdus(const protocol_ctxt_t* const ctxt_pP) #endif //PDCP_USE_RT_FIFO +#ifdef PDCP_SDU_FLUSH_LOCK + if (pthread_mutex_unlock(&mtex)) exit_fun("PDCP_SDU_FLUSH_LOCK unlock error!"); +#endif + return pdcp_nb_sdu_sent; } -- GitLab