mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-10-13 01:17:23 +00:00
l2cap/coc: make coc_continue_tx() thread safe
ble_l2cap_coc_continue_tx() is executed in different tasks: it is (i) called from ble_l2cap_coc_send() in one or more different task contexts from user application(s) and (ii) called from ble_l2cap_coc_le_credits_update() from the NimBLE host task. Typically, the host task has a higher priority then the user tasks, so that ble_l2cap_coc_continue_tx() can be interrupted by itself. This leads to potentially inconsistent state for `chan->coc_tx->credits` and `chan->coc_tx->data_offset`, consequently leading to dropped packets. This commit fixes this by putting all the code code working on these variables into a critical section.
This commit is contained in:
committed by
Hauke Petersen
parent
5aa31b5569
commit
46ed0658a6
@@ -403,9 +403,12 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
|
||||
uint16_t sdu_size_offset;
|
||||
int rc;
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
/* If there is no data to send, just return success */
|
||||
tx = &chan->coc_tx;
|
||||
if (!tx->sdu) {
|
||||
ble_hs_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -458,10 +461,8 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
ble_hs_lock();
|
||||
conn = ble_hs_conn_find_assert(chan->conn_handle);
|
||||
rc = ble_l2cap_tx(conn, chan, txom);
|
||||
ble_hs_unlock();
|
||||
|
||||
if (rc) {
|
||||
/* txom is consumed by l2cap */
|
||||
@@ -491,14 +492,18 @@ ble_l2cap_coc_continue_tx(struct ble_l2cap_chan *chan)
|
||||
if (tx->sdu) {
|
||||
/* Not complete SDU sent, wait for credits */
|
||||
tx->flags |= BLE_L2CAP_COC_FLAG_STALLED;
|
||||
ble_hs_unlock();
|
||||
return BLE_HS_ESTALLED;
|
||||
}
|
||||
|
||||
ble_hs_unlock();
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
os_mbuf_free_chain(tx->sdu);
|
||||
tx->sdu = NULL;
|
||||
ble_hs_unlock();
|
||||
|
||||
os_mbuf_free_chain(txom);
|
||||
if (tx->flags & BLE_L2CAP_COC_FLAG_STALLED) {
|
||||
ble_l2cap_event_coc_unstalled(chan, rc);
|
||||
|
||||
Reference in New Issue
Block a user