rlc_am_lte: reduce time holding Tx mutex when processing status PDUs

the patch is a re-implementation of the customer-specific optimization
we did in order to reduce the time the RLC holds the Tx mutex when
processing an incoming status PDU.

The patch makes sure to never operate on a raw mutex but instead
uses the deadlock-avoiding RAII lock.
master
Andre Puschmann 3 years ago
parent 9c60ef092c
commit 83bf5dcd49

@ -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);

Loading…
Cancel
Save