diff --git a/components/bt/esp_ble_mesh/common/atomic.c b/components/bt/esp_ble_mesh/common/atomic.c index 40f163ab45..9c856cc337 100644 --- a/components/bt/esp_ble_mesh/common/atomic.c +++ b/components/bt/esp_ble_mesh/common/atomic.c @@ -170,13 +170,10 @@ bt_mesh_atomic_val_t bt_mesh_atomic_inc(bt_mesh_atomic_t *target) return ret; } -bool bt_mesh_atomic_campare_and_set(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t excepted, bt_mesh_atomic_val_t new_val) +bool bt_mesh_atomic_cas(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t excepted, bt_mesh_atomic_val_t new_val) { - bt_mesh_atomic_val_t ret = 0; - bt_mesh_atomic_lock(); - ret = *target; if (*target == excepted) { *target = new_val; bt_mesh_atomic_unlock(); diff --git a/components/bt/esp_ble_mesh/common/include/mesh/atomic.h b/components/bt/esp_ble_mesh/common/include/mesh/atomic.h index c6ef0fc5ae..b284974363 100644 --- a/components/bt/esp_ble_mesh/common/include/mesh/atomic.h +++ b/components/bt/esp_ble_mesh/common/include/mesh/atomic.h @@ -159,19 +159,19 @@ extern bt_mesh_atomic_val_t bt_mesh_atomic_and(bt_mesh_atomic_t *target, bt_mesh * * @param target Address of atomic variable. * @param excepted Value of excepted. - * @param new_val Write value if compare sunncess. + * @param new_val Write if target value is equal to expected one. * * @return - * - true: write operation succeeded. - * - false: write operation failed. + * - true: Target value updated. + * - false: Target value not updated. */ #ifdef CONFIG_ATOMIC_OPERATIONS_BUILTIN -static inline bool bt_mesh_atomic_campare_and_set(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t excepted, bt_mesh_atomic_val_t new_val) +static inline bool bt_mesh_atomic_cas(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t excepted, bt_mesh_atomic_val_t new_val) { return __atomic_compare_exchange_n(target, &excepted, &new_val, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); } #else -extern bool bt_mesh_atomic_campare_and_set(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t excepted, bt_mesh_atomic_val_t new_val); +extern bool bt_mesh_atomic_cas(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t excepted, bt_mesh_atomic_val_t new_val); #endif /** diff --git a/components/bt/esp_ble_mesh/core/adv.c b/components/bt/esp_ble_mesh/core/adv.c index dbbda0ab14..79932a0582 100644 --- a/components/bt/esp_ble_mesh/core/adv.c +++ b/components/bt/esp_ble_mesh/core/adv.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -335,8 +335,7 @@ static void adv_thread(void *p) } /* busy == 0 means this was canceled */ - if (BLE_MESH_ADV(*buf)->busy) { - BLE_MESH_ADV(*buf)->busy = 0U; + if (bt_mesh_atomic_cas(&BLE_MESH_ADV_BUSY(*buf), 1, 0)) { #if !CONFIG_BLE_MESH_RELAY_ADV_BUF if (adv_send(*buf)) { BT_WARN("Failed to send adv packet"); @@ -449,7 +448,7 @@ static void bt_mesh_unref_buf(bt_mesh_msg_t *msg) if (msg->arg) { buf = (struct net_buf *)msg->arg; - BLE_MESH_ADV(buf)->busy = 0U; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 0); if (buf->ref > 1U) { buf->ref = 1U; } @@ -490,7 +489,7 @@ void bt_mesh_adv_send(struct net_buf *buf, uint8_t xmit, BLE_MESH_ADV(buf)->cb = cb; BLE_MESH_ADV(buf)->cb_data = cb_data; - BLE_MESH_ADV(buf)->busy = 1U; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 1); BLE_MESH_ADV(buf)->xmit = xmit; bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); @@ -589,7 +588,7 @@ void bt_mesh_relay_adv_send(struct net_buf *buf, uint8_t xmit, BLE_MESH_ADV(buf)->cb = cb; BLE_MESH_ADV(buf)->cb_data = cb_data; - BLE_MESH_ADV(buf)->busy = 1U; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 1); BLE_MESH_ADV(buf)->xmit = xmit; msg.arg = (void *)net_buf_ref(buf); @@ -753,7 +752,7 @@ static void bt_mesh_ble_adv_send(struct net_buf *buf, const struct bt_mesh_send_ BLE_MESH_ADV(buf)->cb = cb; BLE_MESH_ADV(buf)->cb_data = cb_data; - BLE_MESH_ADV(buf)->busy = 1U; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 1); bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); @@ -772,7 +771,7 @@ static void ble_adv_tx_reset(struct ble_adv_tx *tx, bool unref) } bt_mesh_atomic_set(tx->flags, 0); memset(&tx->param, 0, sizeof(tx->param)); - BLE_MESH_ADV(tx->buf)->busy = 0U; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(tx->buf), 0); if (unref) { net_buf_unref(tx->buf); } @@ -961,7 +960,8 @@ int bt_mesh_stop_ble_advertising(uint8_t index) /* busy 1, ref 1; busy 1, ref 2; * busy 0, ref 0; busy 0, ref 1; */ - if (BLE_MESH_ADV(tx->buf)->busy == 1U && + + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(tx->buf)) && tx->buf->ref == 1U) { unref = false; } diff --git a/components/bt/esp_ble_mesh/core/adv.h b/components/bt/esp_ble_mesh/core/adv.h index ab37ec3cda..33224d78b1 100644 --- a/components/bt/esp_ble_mesh/core/adv.h +++ b/components/bt/esp_ble_mesh/core/adv.h @@ -10,6 +10,7 @@ #ifndef _ADV_H_ #define _ADV_H_ +#include "mesh/atomic.h" #include "mesh/access.h" #include "mesh/adapter.h" @@ -24,6 +25,7 @@ extern "C" { #define BLE_MESH_ADV_USER_DATA_SIZE 4 #define BLE_MESH_ADV(buf) (*(struct bt_mesh_adv **)net_buf_user_data(buf)) +#define BLE_MESH_ADV_BUSY(buf) (BLE_MESH_ADV(buf)->busy) uint16_t bt_mesh_pdu_duration(uint8_t xmit); @@ -48,8 +50,10 @@ struct bt_mesh_adv { const struct bt_mesh_send_cb *cb; void *cb_data; - uint8_t type:3, - busy:1; + uint8_t type:3; + + bt_mesh_atomic_t busy; + uint8_t xmit; }; diff --git a/components/bt/esp_ble_mesh/core/friend.c b/components/bt/esp_ble_mesh/core/friend.c index fca3cf1358..b1a298d5a9 100644 --- a/components/bt/esp_ble_mesh/core/friend.c +++ b/components/bt/esp_ble_mesh/core/friend.c @@ -183,7 +183,7 @@ static void friend_clear(struct bt_mesh_friend *frnd, uint8_t reason) /* Cancel the sending if necessary */ if (frnd->pending_buf) { bt_mesh_adv_buf_ref_debug(__func__, frnd->last, 2U, BLE_MESH_BUF_REF_EQUAL); - BLE_MESH_ADV(frnd->last)->busy = 0U; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(frnd->last), 0); } else { bt_mesh_adv_buf_ref_debug(__func__, frnd->last, 1U, BLE_MESH_BUF_REF_EQUAL); } diff --git a/components/bt/esp_ble_mesh/core/prov_common.c b/components/bt/esp_ble_mesh/core/prov_common.c index 655c4712f2..bc75b447d2 100644 --- a/components/bt/esp_ble_mesh/core/prov_common.c +++ b/components/bt/esp_ble_mesh/core/prov_common.c @@ -359,7 +359,7 @@ static void free_segments(struct bt_mesh_prov_link *link) link->tx.buf[i] = NULL; bt_mesh_adv_buf_ref_debug(__func__, buf, 3U, BLE_MESH_BUF_REF_SMALL); /* Mark as canceled */ - BLE_MESH_ADV(buf)->busy = 0U; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(buf), 0); net_buf_unref(buf); } } @@ -474,7 +474,7 @@ static void prov_retransmit(struct k_work *work) break; } - if (BLE_MESH_ADV(buf)->busy) { + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(buf))) { continue; } diff --git a/components/bt/esp_ble_mesh/core/transport.c b/components/bt/esp_ble_mesh/core/transport.c index 64ac566ace..70589706da 100644 --- a/components/bt/esp_ble_mesh/core/transport.c +++ b/components/bt/esp_ble_mesh/core/transport.c @@ -2,7 +2,7 @@ /* * SPDX-FileCopyrightText: 2017 Intel Corporation - * SPDX-FileContributor: 2018-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2018-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -310,7 +310,15 @@ static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx) { bt_mesh_adv_buf_ref_debug(__func__, tx->seg[seg_idx], 3U, BLE_MESH_BUF_REF_SMALL); - BLE_MESH_ADV(tx->seg[seg_idx])->busy = 0U; + /** + * When cancelling a segment that is still in the adv sending queue, `tx->seg_pending` + * must else be decremented by one. More detailed information + * can be found in BLEMESH24-26. + */ + if (bt_mesh_atomic_cas(&BLE_MESH_ADV_BUSY(tx->seg[seg_idx]), 1, 0)) { + tx->seg_pending--; + } + net_buf_unref(tx->seg[seg_idx]); tx->seg[seg_idx] = NULL; tx->nack_count--; @@ -443,7 +451,7 @@ static void seg_tx_send_unacked(struct seg_tx *tx) continue; } - if (BLE_MESH_ADV(seg)->busy) { + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(seg))) { BT_DBG("Skipping segment that's still advertising"); continue; } diff --git a/components/bt/esp_ble_mesh/core/transport.enh.c b/components/bt/esp_ble_mesh/core/transport.enh.c index 6ef6c0a55d..a4a5130e21 100644 --- a/components/bt/esp_ble_mesh/core/transport.enh.c +++ b/components/bt/esp_ble_mesh/core/transport.enh.c @@ -350,7 +350,7 @@ static void seg_tx_done(struct seg_tx *tx, uint8_t seg_idx) */ bt_mesh_adv_buf_ref_debug(__func__, tx->seg[seg_idx], 4U, BLE_MESH_BUF_REF_SMALL); - BLE_MESH_ADV(tx->seg[seg_idx])->busy = 0U; + bt_mesh_atomic_set(&BLE_MESH_ADV_BUSY(tx->seg[seg_idx]), 0); net_buf_unref(tx->seg[seg_idx]); tx->seg[seg_idx] = NULL; @@ -498,7 +498,7 @@ static bool send_next_segment(struct seg_tx *tx, int *result) /* The segment may have already been transmitted, for example, the * Segment Retransmission timer is expired earlier. */ - if (BLE_MESH_ADV(seg)->busy) { + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(seg))) { return false; } @@ -768,7 +768,7 @@ static bool resend_unacked_seg(struct seg_tx *tx, int *result) * A is still going to be retransmitted, but at this moment we could * find that the "busy" flag of Segment A is 1. */ - if (BLE_MESH_ADV(seg)->busy) { + if (bt_mesh_atomic_get(&BLE_MESH_ADV_BUSY(seg))) { return false; }