ble_mesh: Add lock for segmented msg operations
Add mutex to protect some variables of the mesh segmented messages. Currently the timeout handler of mesh will be executed in the btc task, while the received mesh messages will be handled in the btu task. In case some variables are set to NULL when handled in the btu task, meanwhile these variables are also accessed in the timeout handler, so we add mutex to protect these variables and related operations.
This commit is contained in:
parent
367677c3bb
commit
08a463907e
1 changed files with 44 additions and 0 deletions
|
@ -114,6 +114,7 @@ static u8_t seg_rx_buf_data[(CONFIG_BLE_MESH_RX_SEG_MSG_COUNT *
|
|||
static u16_t hb_sub_dst = BLE_MESH_ADDR_UNASSIGNED;
|
||||
|
||||
static bt_mesh_mutex_t tx_seg_lock;
|
||||
static bt_mesh_mutex_t rx_seg_lock;
|
||||
|
||||
static void bt_mesh_tx_seg_mutex_new(void)
|
||||
{
|
||||
|
@ -137,6 +138,28 @@ static void bt_mesh_tx_seg_unlock(void)
|
|||
bt_mesh_mutex_unlock(&tx_seg_lock);
|
||||
}
|
||||
|
||||
static void bt_mesh_rx_seg_mutex_new(void)
|
||||
{
|
||||
if (!rx_seg_lock.mutex) {
|
||||
bt_mesh_mutex_create(&rx_seg_lock);
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_mesh_rx_seg_mutex_free(void)
|
||||
{
|
||||
bt_mesh_mutex_free(&rx_seg_lock);
|
||||
}
|
||||
|
||||
static void bt_mesh_rx_seg_lock(void)
|
||||
{
|
||||
bt_mesh_mutex_lock(&rx_seg_lock);
|
||||
}
|
||||
|
||||
static void bt_mesh_rx_seg_unlock(void)
|
||||
{
|
||||
bt_mesh_mutex_unlock(&rx_seg_lock);
|
||||
}
|
||||
|
||||
u8_t bt_mesh_get_seg_retrans_num(void)
|
||||
{
|
||||
return SEG_RETRANSMIT_ATTEMPTS;
|
||||
|
@ -910,7 +933,9 @@ static int trans_ack(struct bt_mesh_net_rx *rx, u8_t hdr,
|
|||
while ((bit = find_lsb_set(ack))) {
|
||||
if (tx->seg[bit - 1]) {
|
||||
BT_DBG("seg %u/%u acked", bit - 1, tx->seg_n);
|
||||
bt_mesh_tx_seg_lock();
|
||||
seg_tx_done(tx, bit - 1);
|
||||
bt_mesh_tx_seg_unlock();
|
||||
}
|
||||
|
||||
ack &= ~BIT(bit - 1);
|
||||
|
@ -1257,6 +1282,8 @@ static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
|
|||
{
|
||||
BT_DBG("rx %p", rx);
|
||||
|
||||
bt_mesh_rx_seg_lock();
|
||||
|
||||
k_delayed_work_cancel(&rx->ack);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BLE_MESH_FRIEND) && rx->obo &&
|
||||
|
@ -1278,6 +1305,8 @@ static void seg_rx_reset(struct seg_rx *rx, bool full_reset)
|
|||
rx->src = BLE_MESH_ADDR_UNASSIGNED;
|
||||
rx->dst = BLE_MESH_ADDR_UNASSIGNED;
|
||||
}
|
||||
|
||||
bt_mesh_rx_seg_unlock();
|
||||
}
|
||||
|
||||
static u32_t incomplete_timeout(struct seg_rx *rx)
|
||||
|
@ -1306,16 +1335,29 @@ static void seg_ack(struct k_work *work)
|
|||
|
||||
BT_DBG("rx %p", rx);
|
||||
|
||||
bt_mesh_rx_seg_lock();
|
||||
|
||||
if (k_uptime_get_32() - rx->last > incomplete_timeout(rx)) {
|
||||
BT_WARN("Incomplete timer expired");
|
||||
bt_mesh_rx_seg_unlock();
|
||||
seg_rx_reset(rx, false);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Add this check in case the timeout handler is just executed
|
||||
* after the seg_rx_reset() which may reset rx->sub to NULL.
|
||||
*/
|
||||
if (rx->sub == NULL) {
|
||||
bt_mesh_rx_seg_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
send_ack(rx->sub, rx->dst, rx->src, rx->ttl, &rx->seq_auth,
|
||||
rx->block, rx->obo);
|
||||
|
||||
k_delayed_work_submit(&rx->ack, ack_timeout(rx));
|
||||
|
||||
bt_mesh_rx_seg_unlock();
|
||||
}
|
||||
|
||||
static inline u8_t seg_len(bool ctl)
|
||||
|
@ -1814,6 +1856,7 @@ void bt_mesh_trans_init(void)
|
|||
}
|
||||
|
||||
bt_mesh_tx_seg_mutex_new();
|
||||
bt_mesh_rx_seg_mutex_new();
|
||||
}
|
||||
|
||||
void bt_mesh_trans_deinit(bool erase)
|
||||
|
@ -1841,6 +1884,7 @@ void bt_mesh_trans_deinit(bool erase)
|
|||
}
|
||||
|
||||
bt_mesh_tx_seg_mutex_free();
|
||||
bt_mesh_rx_seg_mutex_free();
|
||||
}
|
||||
|
||||
void bt_mesh_rpl_clear(void)
|
||||
|
|
Loading…
Reference in a new issue