@ -1168,11 +1168,16 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no
return ;
return ;
}
}
std : : unique_lock < std : : mutex > lock ( mutex ) ;
// Local variables for handling Status PDU will be updated with lock
rlc_status_pdu_t status = { } ;
uint32_t i = 0 ;
uint32_t vt_s_local = 0 ;
{
std : : lock_guard < std : : mutex > lock ( mutex ) ;
logger . debug ( payload , nof_bytes , " %s Rx control PDU " , RB_NAME ) ;
logger . debug ( payload , nof_bytes , " %s Rx control PDU " , RB_NAME ) ;
rlc_status_pdu_t status ;
rlc_am_read_status_pdu ( payload , nof_bytes , & status ) ;
rlc_am_read_status_pdu ( payload , nof_bytes , & status ) ;
log_rlc_am_status_pdu_to_string ( logger . info , " %s Rx Status PDU: %s " , & status , RB_NAME ) ;
log_rlc_am_status_pdu_to_string ( logger . info , " %s Rx Status PDU: %s " , & status , RB_NAME ) ;
@ -1200,16 +1205,18 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no
retx_queue . clear ( ) ;
retx_queue . clear ( ) ;
}
}
// Handle ACKs and NACKs
i = vt_a ;
bool update_vt_a = true ;
vt_s_local = vt_s ;
uint32_t i = vt_a ;
}
while ( TX_MOD_BASE ( i ) < TX_MOD_BASE ( status . ack_sn ) & & TX_MOD_BASE ( i ) < TX_MOD_BASE ( vt_s ) ) {
bool update_vt_a = true ;
while ( TX_MOD_BASE ( i ) < TX_MOD_BASE ( status . ack_sn ) & & TX_MOD_BASE ( i ) < TX_MOD_BASE ( vt_s_local ) ) {
bool nack = false ;
bool nack = false ;
for ( uint32_t j = 0 ; j < status . N_nack ; j + + ) {
for ( uint32_t j = 0 ; j < status . N_nack ; j + + ) {
if ( status . nacks [ j ] . nack_sn = = i ) {
if ( status . nacks [ j ] . nack_sn = = i ) {
nack = true ;
nack = true ;
update_vt_a = false ;
update_vt_a = false ;
std : : lock_guard < std : : mutex > lock ( mutex ) ;
if ( tx_window . has_sn ( i ) ) {
if ( tx_window . has_sn ( i ) ) {
auto & pdu = tx_window [ i ] ;
auto & pdu = tx_window [ i ] ;
if ( not retx_queue . has_sn ( i ) ) {
if ( not retx_queue . has_sn ( i ) ) {
@ -1259,6 +1266,7 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no
if ( ! nack ) {
if ( ! nack ) {
// ACKed SNs get marked and removed from tx_window so PDCP get's only notified once
// ACKed SNs get marked and removed from tx_window so PDCP get's only notified once
std : : lock_guard < std : : mutex > lock ( mutex ) ;
if ( tx_window . has_sn ( i ) ) {
if ( tx_window . has_sn ( i ) ) {
update_notification_ack_info ( i ) ;
update_notification_ack_info ( i ) ;
logger . debug ( " Tx PDU SN=%zd being removed from tx window " , i ) ;
logger . debug ( " Tx PDU SN=%zd being removed from tx window " , i ) ;
@ -1273,16 +1281,17 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no
i = ( i + 1 ) % MOD ;
i = ( i + 1 ) % MOD ;
}
}
{
// Make sure vt_a points to valid SN
// Make sure vt_a points to valid SN
std : : lock_guard < std : : mutex > lock ( mutex ) ;
if ( not tx_window . empty ( ) & & not tx_window . has_sn ( vt_a ) ) {
if ( not tx_window . empty ( ) & & not tx_window . has_sn ( vt_a ) ) {
logger . error ( " %s vt_a=%d points to invalid position in Tx window. " , RB_NAME , vt_a ) ;
logger . error ( " %s vt_a=%d points to invalid position in Tx window. " , RB_NAME , vt_a ) ;
parent - > rrc - > protocol_failure ( ) ;
parent - > rrc - > protocol_failure ( ) ;
}
}
}
debug_state ( ) ;
debug_state ( ) ;
lock . unlock ( ) ;
// Notify PDCP without holding Tx mutex
// Notify PDCP without holding Tx mutex
if ( not notify_info_vec . empty ( ) ) {
if ( not notify_info_vec . empty ( ) ) {
parent - > pdcp - > notify_delivery ( parent - > lcid , notify_info_vec ) ;
parent - > pdcp - > notify_delivery ( parent - > lcid , notify_info_vec ) ;