Merge branch 'bugfix/ble_mesh_client_check_remain_time_v4.0' into 'release/v4.0'

ble_mesh: Client model check timer remaining time (v4.0)

See merge request espressif/esp-idf!7074
This commit is contained in:
Jiang Jiang Jian 2019-12-22 15:59:34 +08:00
commit b261647835
5 changed files with 85 additions and 41 deletions

View File

@ -268,8 +268,14 @@ s64_t k_uptime_get(void);
*/ */
void k_sleep(s32_t duration); void k_sleep(s32_t duration);
unsigned int bt_mesh_irq_lock(void); void bt_mesh_list_lock(void);
void bt_mesh_irq_unlock(unsigned int key); 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); void bt_mesh_k_init(void);

View File

@ -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) 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; bt_mesh_atomic_val_t ret;
key = bt_mesh_irq_lock(); bt_mesh_atomic_lock();
ret = *target; ret = *target;
*target = value; *target = value;
bt_mesh_irq_unlock(key); bt_mesh_atomic_unlock();
return ret; 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) 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; bt_mesh_atomic_val_t ret;
key = bt_mesh_irq_lock(); bt_mesh_atomic_lock();
ret = *target; ret = *target;
*target |= value; *target |= value;
bt_mesh_irq_unlock(key); bt_mesh_atomic_unlock();
return ret; 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) 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; bt_mesh_atomic_val_t ret;
key = bt_mesh_irq_lock(); bt_mesh_atomic_lock();
ret = *target; ret = *target;
*target &= value; *target &= value;
bt_mesh_irq_unlock(key); bt_mesh_atomic_unlock();
return ret; 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) bt_mesh_atomic_val_t bt_mesh_atomic_dec(bt_mesh_atomic_t *target)
{ {
unsigned int key;
bt_mesh_atomic_val_t ret; bt_mesh_atomic_val_t ret;
key = bt_mesh_irq_lock(); bt_mesh_atomic_lock();
ret = *target; ret = *target;
(*target)--; (*target)--;
bt_mesh_irq_unlock(key); bt_mesh_atomic_unlock();
return ret; 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) bt_mesh_atomic_val_t bt_mesh_atomic_inc(bt_mesh_atomic_t *target)
{ {
unsigned int key;
bt_mesh_atomic_val_t ret; bt_mesh_atomic_val_t ret;
key = bt_mesh_irq_lock(); bt_mesh_atomic_lock();
ret = *target; ret = *target;
(*target)++; (*target)++;
bt_mesh_irq_unlock(key); bt_mesh_atomic_unlock();
return ret; return ret;
} }

View File

@ -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) void net_buf_slist_put(sys_slist_t *list, struct net_buf *buf)
{ {
struct net_buf *tail; struct net_buf *tail;
unsigned int key;
NET_BUF_ASSERT(list); NET_BUF_ASSERT(list);
NET_BUF_ASSERT(buf); 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; tail->flags |= NET_BUF_FRAGS;
} }
key = bt_mesh_irq_lock(); bt_mesh_list_lock();
sys_slist_append_list(list, &buf->node, &tail->node); 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 *net_buf_slist_get(sys_slist_t *list)
{ {
struct net_buf *buf, *frag; struct net_buf *buf, *frag;
unsigned int key;
NET_BUF_ASSERT(list); NET_BUF_ASSERT(list);
key = bt_mesh_irq_lock(); bt_mesh_list_lock();
buf = (void *)sys_slist_get(list); buf = (void *)sys_slist_get(list);
bt_mesh_irq_unlock(key); bt_mesh_list_unlock();
if (!buf) { if (!buf) {
return NULL; return NULL;
@ -264,9 +262,9 @@ struct net_buf *net_buf_slist_get(sys_slist_t *list)
/* Get any fragments belonging to this buffer */ /* Get any fragments belonging to this buffer */
for (frag = buf; (frag->flags & NET_BUF_FRAGS); frag = frag->frags) { 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); frag->frags = (void *)sys_slist_get(list);
bt_mesh_irq_unlock(key); bt_mesh_list_unlock();
NET_BUF_ASSERT(frag->frags); 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 #endif
{ {
struct net_buf *buf = NULL; struct net_buf *buf = NULL;
unsigned int key;
int i; int i;
NET_BUF_ASSERT(pool); 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 /* We need to lock interrupts temporarily to prevent race conditions
* when accessing pool->uninit_count. * when accessing pool->uninit_count.
*/ */
key = bt_mesh_irq_lock(); bt_mesh_buf_lock();
/* If there are uninitialized buffers we're guaranteed to succeed /* If there are uninitialized buffers we're guaranteed to succeed
* with the allocation one way or another. * 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--) { for (i = pool->buf_count; i > 0; i--) {
buf = pool_get_uninit(pool, i); buf = pool_get_uninit(pool, i);
if (!buf->ref) { if (!buf->ref) {
bt_mesh_irq_unlock(key); bt_mesh_buf_unlock();
goto success; goto success;
} }
} }
} }
bt_mesh_irq_unlock(key); bt_mesh_buf_unlock();
NET_BUF_ERR("%s, Failed to get free buffer", __func__); NET_BUF_ERR("%s, Failed to get free buffer", __func__);
return NULL; return NULL;

View File

@ -24,7 +24,9 @@
#include "provisioner_prov.h" #include "provisioner_prov.h"
static osi_mutex_t bm_alarm_lock; 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 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 + \ static const size_t BLE_MESH_GENERAL_ALARM_HASH_MAP_SIZE = 20 + CONFIG_BLE_MESH_PBA_SAME_TIME + \
CONFIG_BLE_MESH_PBG_SAME_TIME; CONFIG_BLE_MESH_PBG_SAME_TIME;
@ -37,18 +39,34 @@ typedef struct alarm_t {
int64_t deadline_us; int64_t deadline_us;
} osi_alarm_t; } 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 osi_mutex_lock(&bm_list_lock, OSI_MUTEX_MAX_TIMEOUT);
* requirements of bt controller, we use task lock instead of IRQ lock.
*/
osi_mutex_lock(&bm_irq_lock, OSI_MUTEX_MAX_TIMEOUT);
return 0;
} }
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) s64_t k_uptime_get(void)
@ -76,7 +94,9 @@ void k_sleep(s32_t duration)
void bt_mesh_k_init(void) void bt_mesh_k_init(void)
{ {
osi_mutex_new(&bm_alarm_lock); 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, bm_alarm_hash_map = hash_map_new(BLE_MESH_GENERAL_ALARM_HASH_MAP_SIZE,
hash_function_pointer, NULL, hash_function_pointer, NULL,
(data_free_fn)osi_alarm_free, 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); alarm = osi_alarm_new("bt_mesh", (osi_alarm_callback_t)handler, (void *)&work->work, 0);
if (alarm == NULL) { if (alarm == NULL) {
BT_ERR("%s, Unable to create alarm", __func__); BT_ERR("%s, Unable to create alarm", __func__);
osi_mutex_unlock(&bm_alarm_lock);
return; return;
} }
if (!hash_map_set(bm_alarm_hash_map, work, (void *)alarm)) { 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; return -EINVAL;
} }
osi_alarm_cancel(alarm);
hash_map_erase(bm_alarm_hash_map, work); hash_map_erase(bm_alarm_hash_map, work);
return 0; return 0;
} }

View File

@ -28,19 +28,25 @@
static bt_mesh_client_node_t *bt_mesh_client_pick_node(sys_slist_t *list, u16_t tx_dst) 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)) { if (sys_slist_is_empty(list)) {
bt_mesh_list_unlock();
return NULL; return NULL;
} }
sys_snode_t *cur = NULL; bt_mesh_client_node_t *node = NULL;
for (cur = sys_slist_peek_head(list); for (cur = sys_slist_peek_head(list);
cur != NULL; cur = sys_slist_peek_next(cur)) { cur != NULL; cur = sys_slist_peek_next(cur)) {
node = (bt_mesh_client_node_t *)cur; node = (bt_mesh_client_node_t *)cur;
if (node->ctx.addr == tx_dst) { if (node->ctx.addr == tx_dst) {
bt_mesh_list_unlock();
return node; return node;
} }
} }
bt_mesh_list_unlock();
return NULL; return NULL;
} }
@ -103,24 +109,38 @@ bt_mesh_client_node_t *bt_mesh_is_client_recv_publish_msg(
return NULL; 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; return node;
} }
static bool bt_mesh_client_check_node_in_list(sys_slist_t *list, u16_t tx_dst) 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)) { if (sys_slist_is_empty(list)) {
bt_mesh_list_unlock();
return false; return false;
} }
sys_snode_t *cur = NULL; bt_mesh_client_node_t *node = NULL;
for (cur = sys_slist_peek_head(list); for (cur = sys_slist_peek_head(list);
cur != NULL; cur = sys_slist_peek_next(cur)) { cur != NULL; cur = sys_slist_peek_next(cur)) {
node = (bt_mesh_client_node_t *)cur; node = (bt_mesh_client_node_t *)cur;
if (node->ctx.addr == tx_dst) { if (node->ctx.addr == tx_dst) {
bt_mesh_list_unlock();
return true; return true;
} }
} }
bt_mesh_list_unlock();
return false; 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) { if ((err = bt_mesh_model_send(model, ctx, msg, cb, cb_data)) != 0) {
osi_free(node); osi_free(node);
} else { } else {
bt_mesh_list_lock();
sys_slist_append(&internal->queue, &node->client_node); sys_slist_append(&internal->queue, &node->client_node);
bt_mesh_list_unlock();
k_delayed_work_init(&node->timer, timer_handler); k_delayed_work_init(&node->timer, timer_handler);
k_delayed_work_submit(&node->timer, timeout ? timeout : CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT); 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 // Release the client node from the queue
bt_mesh_list_lock();
sys_slist_find_and_remove(&internal->queue, &node->client_node); sys_slist_find_and_remove(&internal->queue, &node->client_node);
bt_mesh_list_unlock();
// Free the node // Free the node
osi_free(node); osi_free(node);