diff --git a/components/bt/esp_ble_mesh/mesh_common/include/mesh_kernel.h b/components/bt/esp_ble_mesh/mesh_common/include/mesh_kernel.h index 7d00d64269..5e95e3b1a0 100644 --- a/components/bt/esp_ble_mesh/mesh_common/include/mesh_kernel.h +++ b/components/bt/esp_ble_mesh/mesh_common/include/mesh_kernel.h @@ -268,8 +268,14 @@ s64_t k_uptime_get(void); */ void k_sleep(s32_t duration); -unsigned int bt_mesh_irq_lock(void); -void bt_mesh_irq_unlock(unsigned int key); +void bt_mesh_list_lock(void); +void bt_mesh_list_unlock(void); + +void bt_mesh_buf_lock(void); +void bt_mesh_buf_unlock(void); + +void bt_mesh_atomic_lock(void); +void bt_mesh_atomic_unlock(void); void bt_mesh_k_init(void); diff --git a/components/bt/esp_ble_mesh/mesh_common/mesh_atomic.c b/components/bt/esp_ble_mesh/mesh_common/mesh_atomic.c index ce73638053..6c2e940a19 100644 --- a/components/bt/esp_ble_mesh/mesh_common/mesh_atomic.c +++ b/components/bt/esp_ble_mesh/mesh_common/mesh_atomic.c @@ -55,15 +55,14 @@ bt_mesh_atomic_val_t bt_mesh_atomic_get(const bt_mesh_atomic_t *target) */ bt_mesh_atomic_val_t bt_mesh_atomic_set(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t value) { - unsigned int key; bt_mesh_atomic_val_t ret; - key = bt_mesh_irq_lock(); + bt_mesh_atomic_lock(); ret = *target; *target = value; - bt_mesh_irq_unlock(key); + bt_mesh_atomic_unlock(); return ret; } @@ -83,15 +82,14 @@ bt_mesh_atomic_val_t bt_mesh_atomic_set(bt_mesh_atomic_t *target, bt_mesh_atomic */ bt_mesh_atomic_val_t bt_mesh_atomic_or(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t value) { - unsigned int key; bt_mesh_atomic_val_t ret; - key = bt_mesh_irq_lock(); + bt_mesh_atomic_lock(); ret = *target; *target |= value; - bt_mesh_irq_unlock(key); + bt_mesh_atomic_unlock(); return ret; } @@ -111,15 +109,14 @@ bt_mesh_atomic_val_t bt_mesh_atomic_or(bt_mesh_atomic_t *target, bt_mesh_atomic_ */ bt_mesh_atomic_val_t bt_mesh_atomic_and(bt_mesh_atomic_t *target, bt_mesh_atomic_val_t value) { - unsigned int key; bt_mesh_atomic_val_t ret; - key = bt_mesh_irq_lock(); + bt_mesh_atomic_lock(); ret = *target; *target &= value; - bt_mesh_irq_unlock(key); + bt_mesh_atomic_unlock(); return ret; } @@ -137,15 +134,14 @@ bt_mesh_atomic_val_t bt_mesh_atomic_and(bt_mesh_atomic_t *target, bt_mesh_atomic */ bt_mesh_atomic_val_t bt_mesh_atomic_dec(bt_mesh_atomic_t *target) { - unsigned int key; bt_mesh_atomic_val_t ret; - key = bt_mesh_irq_lock(); + bt_mesh_atomic_lock(); ret = *target; (*target)--; - bt_mesh_irq_unlock(key); + bt_mesh_atomic_unlock(); return ret; } @@ -163,15 +159,14 @@ bt_mesh_atomic_val_t bt_mesh_atomic_dec(bt_mesh_atomic_t *target) */ bt_mesh_atomic_val_t bt_mesh_atomic_inc(bt_mesh_atomic_t *target) { - unsigned int key; bt_mesh_atomic_val_t ret; - key = bt_mesh_irq_lock(); + bt_mesh_atomic_lock(); ret = *target; (*target)++; - bt_mesh_irq_unlock(key); + bt_mesh_atomic_unlock(); return ret; } diff --git a/components/bt/esp_ble_mesh/mesh_common/mesh_buf.c b/components/bt/esp_ble_mesh/mesh_common/mesh_buf.c index 9e5f6c184b..885c489f57 100644 --- a/components/bt/esp_ble_mesh/mesh_common/mesh_buf.c +++ b/components/bt/esp_ble_mesh/mesh_common/mesh_buf.c @@ -233,7 +233,6 @@ void net_buf_simple_reserve(struct net_buf_simple *buf, size_t reserve) void net_buf_slist_put(sys_slist_t *list, struct net_buf *buf) { struct net_buf *tail; - unsigned int key; NET_BUF_ASSERT(list); NET_BUF_ASSERT(buf); @@ -242,21 +241,20 @@ void net_buf_slist_put(sys_slist_t *list, struct net_buf *buf) tail->flags |= NET_BUF_FRAGS; } - key = bt_mesh_irq_lock(); + bt_mesh_list_lock(); sys_slist_append_list(list, &buf->node, &tail->node); - bt_mesh_irq_unlock(key); + bt_mesh_list_unlock(); } struct net_buf *net_buf_slist_get(sys_slist_t *list) { struct net_buf *buf, *frag; - unsigned int key; NET_BUF_ASSERT(list); - key = bt_mesh_irq_lock(); + bt_mesh_list_lock(); buf = (void *)sys_slist_get(list); - bt_mesh_irq_unlock(key); + bt_mesh_list_unlock(); if (!buf) { return NULL; @@ -264,9 +262,9 @@ struct net_buf *net_buf_slist_get(sys_slist_t *list) /* Get any fragments belonging to this buffer */ for (frag = buf; (frag->flags & NET_BUF_FRAGS); frag = frag->frags) { - key = bt_mesh_irq_lock(); + bt_mesh_list_lock(); frag->frags = (void *)sys_slist_get(list); - bt_mesh_irq_unlock(key); + bt_mesh_list_unlock(); NET_BUF_ASSERT(frag->frags); @@ -373,7 +371,6 @@ struct net_buf *net_buf_alloc_len(struct net_buf_pool *pool, size_t size, #endif { struct net_buf *buf = NULL; - unsigned int key; int i; NET_BUF_ASSERT(pool); @@ -384,7 +381,7 @@ struct net_buf *net_buf_alloc_len(struct net_buf_pool *pool, size_t size, /* We need to lock interrupts temporarily to prevent race conditions * when accessing pool->uninit_count. */ - key = bt_mesh_irq_lock(); + bt_mesh_buf_lock(); /* If there are uninitialized buffers we're guaranteed to succeed * with the allocation one way or another. @@ -394,13 +391,13 @@ struct net_buf *net_buf_alloc_len(struct net_buf_pool *pool, size_t size, for (i = pool->buf_count; i > 0; i--) { buf = pool_get_uninit(pool, i); if (!buf->ref) { - bt_mesh_irq_unlock(key); + bt_mesh_buf_unlock(); goto success; } } } - bt_mesh_irq_unlock(key); + bt_mesh_buf_unlock(); NET_BUF_ERR("%s, Failed to get free buffer", __func__); return NULL; diff --git a/components/bt/esp_ble_mesh/mesh_common/mesh_kernel.c b/components/bt/esp_ble_mesh/mesh_common/mesh_kernel.c index 1ee0aa0d76..2e1803bdf0 100644 --- a/components/bt/esp_ble_mesh/mesh_common/mesh_kernel.c +++ b/components/bt/esp_ble_mesh/mesh_common/mesh_kernel.c @@ -24,7 +24,9 @@ #include "provisioner_prov.h" static osi_mutex_t bm_alarm_lock; -static osi_mutex_t bm_irq_lock; +static osi_mutex_t bm_list_lock; +static osi_mutex_t bm_buf_lock; +static osi_mutex_t bm_atomic_lock; static hash_map_t *bm_alarm_hash_map; static const size_t BLE_MESH_GENERAL_ALARM_HASH_MAP_SIZE = 20 + CONFIG_BLE_MESH_PBA_SAME_TIME + \ CONFIG_BLE_MESH_PBG_SAME_TIME; @@ -37,18 +39,34 @@ typedef struct alarm_t { int64_t deadline_us; } osi_alarm_t; -unsigned int bt_mesh_irq_lock(void) +void bt_mesh_list_lock(void) { - /* Changed by Espressif. In BLE Mesh, in order to improve the real-time - * requirements of bt controller, we use task lock instead of IRQ lock. - */ - osi_mutex_lock(&bm_irq_lock, OSI_MUTEX_MAX_TIMEOUT); - return 0; + osi_mutex_lock(&bm_list_lock, OSI_MUTEX_MAX_TIMEOUT); } -void bt_mesh_irq_unlock(unsigned int key) +void bt_mesh_list_unlock(void) { - osi_mutex_unlock(&bm_irq_lock); + osi_mutex_unlock(&bm_list_lock); +} + +void bt_mesh_buf_lock(void) +{ + osi_mutex_lock(&bm_buf_lock, OSI_MUTEX_MAX_TIMEOUT); +} + +void bt_mesh_buf_unlock(void) +{ + osi_mutex_unlock(&bm_buf_lock); +} + +void bt_mesh_atomic_lock(void) +{ + osi_mutex_lock(&bm_atomic_lock, OSI_MUTEX_MAX_TIMEOUT); +} + +void bt_mesh_atomic_unlock(void) +{ + osi_mutex_unlock(&bm_atomic_lock); } s64_t k_uptime_get(void) @@ -76,7 +94,9 @@ void k_sleep(s32_t duration) void bt_mesh_k_init(void) { osi_mutex_new(&bm_alarm_lock); - osi_mutex_new(&bm_irq_lock); + osi_mutex_new(&bm_list_lock); + osi_mutex_new(&bm_buf_lock); + osi_mutex_new(&bm_atomic_lock); bm_alarm_hash_map = hash_map_new(BLE_MESH_GENERAL_ALARM_HASH_MAP_SIZE, hash_function_pointer, NULL, (data_free_fn)osi_alarm_free, NULL); @@ -96,6 +116,7 @@ void k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler) alarm = osi_alarm_new("bt_mesh", (osi_alarm_callback_t)handler, (void *)&work->work, 0); if (alarm == NULL) { BT_ERR("%s, Unable to create alarm", __func__); + osi_mutex_unlock(&bm_alarm_lock); return; } if (!hash_map_set(bm_alarm_hash_map, work, (void *)alarm)) { @@ -173,6 +194,7 @@ int k_delayed_work_free(struct k_delayed_work *work) return -EINVAL; } + osi_alarm_cancel(alarm); hash_map_erase(bm_alarm_hash_map, work); return 0; } diff --git a/components/bt/esp_ble_mesh/mesh_models/client/client_common.c b/components/bt/esp_ble_mesh/mesh_models/client/client_common.c index bd7231ead2..5f9374b340 100644 --- a/components/bt/esp_ble_mesh/mesh_models/client/client_common.c +++ b/components/bt/esp_ble_mesh/mesh_models/client/client_common.c @@ -28,19 +28,25 @@ static bt_mesh_client_node_t *bt_mesh_client_pick_node(sys_slist_t *list, u16_t tx_dst) { + bt_mesh_client_node_t *node = NULL; + sys_snode_t *cur = NULL; + + bt_mesh_list_lock(); if (sys_slist_is_empty(list)) { + bt_mesh_list_unlock(); return NULL; } - sys_snode_t *cur = NULL; bt_mesh_client_node_t *node = NULL; for (cur = sys_slist_peek_head(list); cur != NULL; cur = sys_slist_peek_next(cur)) { node = (bt_mesh_client_node_t *)cur; if (node->ctx.addr == tx_dst) { + bt_mesh_list_unlock(); return node; } } + bt_mesh_list_unlock(); return NULL; } @@ -103,24 +109,38 @@ bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg( return NULL; } + if (k_delayed_work_remaining_get(&node->timer) == 0) { + BT_DBG("Unexpected status message 0x%x", ctx->recv_op); + if (cli->publish_status && need_pub) { + cli->publish_status(ctx->recv_op, model, ctx, buf); + } + return NULL; + } + return node; } static bool bt_mesh_client_check_node_in_list(sys_slist_t *list, u16_t tx_dst) { + bt_mesh_client_node_t *node = NULL; + sys_snode_t *cur = NULL; + + bt_mesh_list_lock(); if (sys_slist_is_empty(list)) { + bt_mesh_list_unlock(); return false; } - sys_snode_t *cur = NULL; bt_mesh_client_node_t *node = NULL; for (cur = sys_slist_peek_head(list); cur != NULL; cur = sys_slist_peek_next(cur)) { node = (bt_mesh_client_node_t *)cur; if (node->ctx.addr == tx_dst) { + bt_mesh_list_unlock(); return true; } } + bt_mesh_list_unlock(); return false; } @@ -192,7 +212,9 @@ int bt_mesh_client_send_msg(struct bt_mesh_model *model, if ((err = bt_mesh_model_send(model, ctx, msg, cb, cb_data)) != 0) { osi_free(node); } else { + bt_mesh_list_lock(); sys_slist_append(&internal->queue, &node->client_node); + bt_mesh_list_unlock(); k_delayed_work_init(&node->timer, timer_handler); k_delayed_work_submit(&node->timer, timeout ? timeout : CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT); } @@ -285,7 +307,9 @@ int bt_mesh_client_free_node(bt_mesh_client_node_t *node) } // Release the client node from the queue + bt_mesh_list_lock(); sys_slist_find_and_remove(&internal->queue, &node->client_node); + bt_mesh_list_unlock(); // Free the node osi_free(node);