]> granicus.if.org Git - esp-idf/commitdiff
ble_mesh: fix duplicate memory free during receiving status message
authorlly <lly@espressif.com>
Mon, 16 Sep 2019 07:05:14 +0000 (15:05 +0800)
committerlly <lly@espressif.com>
Mon, 16 Sep 2019 09:34:08 +0000 (17:34 +0800)
components/bt/esp_ble_mesh/btc/btc_ble_mesh_prov.c
components/bt/esp_ble_mesh/mesh_core/cfg_cli.c
components/bt/esp_ble_mesh/mesh_core/health_cli.c
components/bt/esp_ble_mesh/mesh_core/mesh_kernel.c
components/bt/esp_ble_mesh/mesh_models/client/client_common.c
components/bt/esp_ble_mesh/mesh_models/client/generic_client.c
components/bt/esp_ble_mesh/mesh_models/client/include/client_common.h
components/bt/esp_ble_mesh/mesh_models/client/lighting_client.c
components/bt/esp_ble_mesh/mesh_models/client/sensor_client.c
components/bt/esp_ble_mesh/mesh_models/client/time_scene_client.c

index a60fa6c0f737d29dff6776b8d6c8be83521a1248..c0a155bed0db7d7615cdddf03e7e704cd63a5387 100644 (file)
@@ -315,6 +315,8 @@ static void btc_ble_mesh_client_model_op_cb(struct bt_mesh_model *model,
         return;
     }
 
+    bt_mesh_client_model_lock();
+
     node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, false);
     if (node == NULL) {
         msg.act = ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT;
@@ -334,12 +336,21 @@ static void btc_ble_mesh_client_model_op_cb(struct bt_mesh_model *model,
 
     msg.sig = BTC_SIG_API_CB;
     msg.pid = BTC_PID_MODEL;
-    if (msg.act != ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT) {
-        // Don't forget to release the node at the end.
-        bt_mesh_client_free_node(&data->queue, node);
+    if (msg.act == ESP_BLE_MESH_CLIENT_MODEL_RECV_PUBLISH_MSG_EVT) {
+        ret = btc_transfer_context(&msg, &mesh_param,
+                sizeof(esp_ble_mesh_model_cb_param_t), btc_ble_mesh_model_copy_req_data);
+    } else {
+        if (!k_delayed_work_free(&node->timer)) {
+            ret = btc_transfer_context(&msg, &mesh_param,
+                    sizeof(esp_ble_mesh_model_cb_param_t), btc_ble_mesh_model_copy_req_data);
+            // Don't forget to release the node at the end.
+            bt_mesh_client_free_node(&data->queue, node);
+        } else {
+            ret = BT_STATUS_SUCCESS;
+        }
     }
-    ret = btc_transfer_context(&msg, &mesh_param,
-                               sizeof(esp_ble_mesh_model_cb_param_t), btc_ble_mesh_model_copy_req_data);
+
+    bt_mesh_client_model_unlock();
 
     if (ret != BT_STATUS_SUCCESS) {
         LOG_ERROR("%s, btc_transfer_context failed", __func__);
@@ -611,21 +622,29 @@ static void btc_ble_mesh_client_model_timeout_cb(struct k_work *work)
         return;
     }
 
-    mesh_param.client_send_timeout.opcode = node->opcode;
-    mesh_param.client_send_timeout.model = (esp_ble_mesh_model_t *)node->ctx.model;
-    mesh_param.client_send_timeout.ctx = (esp_ble_mesh_msg_ctx_t *)&node->ctx;
+    bt_mesh_client_model_lock();
 
-    msg.sig = BTC_SIG_API_CB;
-    msg.pid = BTC_PID_MODEL;
-    msg.act = ESP_BLE_MESH_CLIENT_MODEL_SEND_TIMEOUT_EVT;
-    ret = btc_transfer_context(&msg, &mesh_param,
-                               sizeof(esp_ble_mesh_model_cb_param_t), btc_ble_mesh_model_copy_req_data);
+    if (!k_delayed_work_free(&node->timer)) {
+        mesh_param.client_send_timeout.opcode = node->opcode;
+        mesh_param.client_send_timeout.model = (esp_ble_mesh_model_t *)node->ctx.model;
+        mesh_param.client_send_timeout.ctx = (esp_ble_mesh_msg_ctx_t *)&node->ctx;
 
-    if (ret != BT_STATUS_SUCCESS) {
-        LOG_ERROR("%s btc_transfer_context failed", __func__);
+        msg.sig = BTC_SIG_API_CB;
+        msg.pid = BTC_PID_MODEL;
+        msg.act = ESP_BLE_MESH_CLIENT_MODEL_SEND_TIMEOUT_EVT;
+
+        ret = btc_transfer_context(&msg, &mesh_param,
+                sizeof(esp_ble_mesh_model_cb_param_t), btc_ble_mesh_model_copy_req_data);
+        if (ret != BT_STATUS_SUCCESS) {
+            LOG_ERROR("%s btc_transfer_context failed", __func__);
+        }
+
+        // Don't forget to release the node at the end.
+        bt_mesh_client_free_node(&data->queue, node);
     }
-    // Don't forget to release the node at the end.
-    bt_mesh_client_free_node(&data->queue, node);
+
+    bt_mesh_client_model_unlock();
+
     return;
 }
 
index 3165ccb3f073019f924a4f79eddb2d09cf632929..2eb843e35cafcf8c985d0b2a124a93c24357cafc 100644 (file)
@@ -12,6 +12,7 @@
 #include <stdbool.h>
 
 #include "osi/allocator.h"
+#include "osi/mutex.h"
 #include "sdkconfig.h"
 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BLE_MESH_DEBUG_MODEL)
 
@@ -82,6 +83,28 @@ static const bt_mesh_client_op_pair_t cfg_op_pair[] = {
     { OP_NET_TRANSMIT_SET,     OP_NET_TRANSMIT_STATUS  },
 };
 
+static osi_mutex_t cfg_client_mutex;
+
+static void bt_mesh_cfg_client_mutex_new(void)
+{
+    static bool init;
+
+    if (!init) {
+        osi_mutex_new(&cfg_client_mutex);
+        init = true;
+    }
+}
+
+static void bt_mesh_cfg_client_lock(void)
+{
+    osi_mutex_lock(&cfg_client_mutex, OSI_MUTEX_MAX_TIMEOUT);
+}
+
+static void bt_mesh_cfg_client_unlock(void)
+{
+    osi_mutex_unlock(&cfg_client_mutex);
+}
+
 static void timeout_handler(struct k_work *work)
 {
     config_internal_data_t *internal = NULL;
@@ -108,10 +131,16 @@ static void timeout_handler(struct k_work *work)
         return;
     }
 
-    bt_mesh_config_client_cb_evt_to_btc(node->opcode,
-        BTC_BLE_MESH_EVT_CONFIG_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
+    bt_mesh_cfg_client_lock();
 
-    bt_mesh_client_free_node(&internal->queue, node);
+    if (!k_delayed_work_free(&node->timer)) {
+        bt_mesh_config_client_cb_evt_to_btc(node->opcode,
+            BTC_BLE_MESH_EVT_CONFIG_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
+        // Don't forget to release the node at the end.
+        bt_mesh_client_free_node(&internal->queue, node);
+    }
+
+    bt_mesh_cfg_client_unlock();
 
     return;
 }
@@ -139,6 +168,9 @@ static void cfg_client_cancel(struct bt_mesh_model *model,
     /* If it is a publish message, sent to the user directly. */
     buf.data = (u8_t *)status;
     buf.len  = (u16_t)len;
+
+    bt_mesh_cfg_client_lock();
+
     node = bt_mesh_is_client_recv_publish_msg(model, ctx, &buf, true);
     if (!node) {
         BT_DBG("Unexpected config status message 0x%x", ctx->recv_op);
@@ -199,12 +231,16 @@ static void cfg_client_cancel(struct bt_mesh_model *model,
             break;
         }
 
-        bt_mesh_config_client_cb_evt_to_btc(
-            node->opcode, evt_type, model, ctx, (const u8_t *)status, len);
-        // Don't forget to release the node at the end.
-        bt_mesh_client_free_node(&data->queue, node);
+        if (!k_delayed_work_free(&node->timer)) {
+            bt_mesh_config_client_cb_evt_to_btc(
+                node->opcode, evt_type, model, ctx, (const u8_t *)status, len);
+            // Don't forget to release the node at the end.
+            bt_mesh_client_free_node(&data->queue, node);
+        }
     }
 
+    bt_mesh_cfg_client_unlock();
+
     switch (ctx->recv_op) {
     case OP_DEV_COMP_DATA_STATUS: {
         struct bt_mesh_cfg_comp_data_status *val;
@@ -1653,5 +1689,7 @@ int bt_mesh_cfg_cli_init(struct bt_mesh_model *model, bool primary)
     /* Configuration Model security is device-key based */
     model->keys[0] = BLE_MESH_KEY_DEV;
 
+    bt_mesh_cfg_client_mutex_new();
+
     return 0;
 }
index 1e13befc64bac310bc22f7e6355de1847de5d02c..e652bdda5ef45f3685f4273442570bb53f8367a9 100644 (file)
@@ -12,6 +12,7 @@
 #include <stdbool.h>
 
 #include "osi/allocator.h"
+#include "osi/mutex.h"
 #include "sdkconfig.h"
 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BLE_MESH_DEBUG_MODEL)
 
@@ -38,6 +39,28 @@ static const bt_mesh_client_op_pair_t health_op_pair[] = {
     { OP_ATTENTION_SET,      OP_ATTENTION_STATUS     },
 };
 
+static osi_mutex_t health_client_mutex;
+
+static void bt_mesh_health_client_mutex_new(void)
+{
+    static bool init;
+
+    if (!init) {
+        osi_mutex_new(&health_client_mutex);
+        init = true;
+    }
+}
+
+static void bt_mesh_health_client_lock(void)
+{
+    osi_mutex_lock(&health_client_mutex, OSI_MUTEX_MAX_TIMEOUT);
+}
+
+static void bt_mesh_health_client_unlock(void)
+{
+    osi_mutex_unlock(&health_client_mutex);
+}
+
 static void timeout_handler(struct k_work *work)
 {
     health_internal_data_t *internal = NULL;
@@ -64,10 +87,16 @@ static void timeout_handler(struct k_work *work)
         return;
     }
 
-    bt_mesh_health_client_cb_evt_to_btc(node->opcode,
-        BTC_BLE_MESH_EVT_HEALTH_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
+    bt_mesh_health_client_lock();
 
-    bt_mesh_client_free_node(&internal->queue, node);
+    if (!k_delayed_work_free(&node->timer)) {
+        bt_mesh_health_client_cb_evt_to_btc(node->opcode,
+            BTC_BLE_MESH_EVT_HEALTH_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
+        // Don't forget to release the node at the end.
+        bt_mesh_client_free_node(&internal->queue, node);
+    }
+
+    bt_mesh_health_client_unlock();
 
     return;
 }
@@ -95,6 +124,9 @@ static void health_client_cancel(struct bt_mesh_model *model,
     /* If it is a publish message, sent to the user directly. */
     buf.data = (u8_t *)status;
     buf.len  = (u16_t)len;
+
+    bt_mesh_health_client_lock();
+
     node = bt_mesh_is_client_recv_publish_msg(model, ctx, &buf, true);
     if (!node) {
         BT_DBG("Unexpected health status message 0x%x", ctx->recv_op);
@@ -115,12 +147,16 @@ static void health_client_cancel(struct bt_mesh_model *model,
             break;
         }
 
-        bt_mesh_health_client_cb_evt_to_btc(
-            node->opcode, evt_type, model, ctx, (const u8_t *)status, len);
-        // Don't forget to release the node at the end.
-        bt_mesh_client_free_node(&data->queue, node);
+        if (!k_delayed_work_free(&node->timer)) {
+            bt_mesh_health_client_cb_evt_to_btc(
+                node->opcode, evt_type, model, ctx, (const u8_t *)status, len);
+            // Don't forget to release the node at the end.
+            bt_mesh_client_free_node(&data->queue, node);
+        }
     }
 
+    bt_mesh_health_client_unlock();
+
     switch (ctx->recv_op) {
     case OP_HEALTH_FAULT_STATUS: {
         struct bt_mesh_health_fault_status *val;
@@ -453,6 +489,8 @@ int bt_mesh_health_cli_init(struct bt_mesh_model *model, bool primary)
     client->op_pair = health_op_pair;
     client->internal_data = internal;
 
+    bt_mesh_health_client_mutex_new();
+
     /* Set the default health client pointer */
     if (!health_cli) {
         health_cli = client;
index 92b5cfa39f4c704a5d81a194c7e4c02f62dd132f..7ff4f75b8ac78d40e15548d4e6167687c82566ed 100644 (file)
@@ -38,14 +38,6 @@ typedef struct alarm_t {
     int64_t deadline_us;
 } osi_alarm_t;
 
-static void bt_mesh_alarm_cb(void *data)
-{
-    assert(data != NULL);
-    struct k_delayed_work *work = (struct k_delayed_work *)data;
-    work->work.handler(&work->work);
-    return;
-}
-
 unsigned int bt_mesh_irq_lock(void)
 {
 #if defined(CONFIG_BLE_MESH_IRQ_LOCK) && CONFIG_BLE_MESH_IRQ_LOCK
@@ -111,7 +103,7 @@ void k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler)
 
     osi_mutex_lock(&bm_alarm_lock, OSI_MUTEX_MAX_TIMEOUT);
     if (!hash_map_has_key(bm_alarm_hash_map, (void *)work)) {
-        alarm = osi_alarm_new("bt_mesh", bt_mesh_alarm_cb, (void *)work, 0);
+        alarm = osi_alarm_new("bt_mesh", (osi_alarm_callback_t)handler, (void *)work, 0);
         if (alarm == NULL) {
             BT_ERR("%s, Unable to create alarm", __func__);
             return;
index c2590935bcff342100b66fc5c903abb2434f4929..037dd98d07dccde39d74774e6013214bb4319a58 100644 (file)
@@ -16,6 +16,7 @@
 #include <errno.h>
 
 #include "osi/allocator.h"
+#include "osi/mutex.h"
 
 #include "mesh_access.h"
 #include "mesh_buf.h"
@@ -222,6 +223,28 @@ int bt_mesh_client_send_msg(struct bt_mesh_model *model,
     return err;
 }
 
+static osi_mutex_t client_model_mutex;
+
+static void bt_mesh_client_model_mutex_new(void)
+{
+    static bool init;
+
+    if (!init) {
+        osi_mutex_new(&client_model_mutex);
+        init = true;
+    }
+}
+
+void bt_mesh_client_model_lock(void)
+{
+    osi_mutex_lock(&client_model_mutex, OSI_MUTEX_MAX_TIMEOUT);
+}
+
+void bt_mesh_client_model_unlock(void)
+{
+    osi_mutex_unlock(&client_model_mutex);
+}
+
 int bt_mesh_client_init(struct bt_mesh_model *model)
 {
     bt_mesh_client_internal_data_t *data = NULL;
@@ -256,17 +279,18 @@ int bt_mesh_client_init(struct bt_mesh_model *model)
     cli->model = model;
     cli->internal_data = data;
 
+    bt_mesh_client_model_mutex_new();
+
     return 0;
 }
 
 int bt_mesh_client_free_node(sys_slist_t *queue, bt_mesh_client_node_t *node)
 {
     if (!queue || !node) {
+        BT_ERR("%s, Invalid parameter", __func__);
         return -EINVAL;
     }
 
-    // Free the node timer
-    k_delayed_work_free(&node->timer);
     // Release the client node from the queue
     sys_slist_find_and_remove(queue, &node->client_node);
     // Free the node
index f821fb3d93d875cb1e33e089a031e9f186e3ba1f..617083cbd204e3e2e53745f2aeb7481ce19c4bd2 100644 (file)
@@ -17,6 +17,7 @@
 #include <stdbool.h>
 
 #include "osi/allocator.h"
+#include "osi/mutex.h"
 #include "sdkconfig.h"
 
 #include "mesh_types.h"
@@ -119,6 +120,28 @@ static const bt_mesh_client_op_pair_t gen_op_pair[] = {
     { BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_GET, BLE_MESH_MODEL_OP_GEN_CLIENT_PROPERTIES_STATUS },
 };
 
+static osi_mutex_t generic_client_mutex;
+
+static void bt_mesh_generic_client_mutex_new(void)
+{
+    static bool init;
+
+    if (!init) {
+        osi_mutex_new(&generic_client_mutex);
+        init = true;
+    }
+}
+
+static void bt_mesh_generic_client_lock(void)
+{
+    osi_mutex_lock(&generic_client_mutex, OSI_MUTEX_MAX_TIMEOUT);
+}
+
+static void bt_mesh_generic_client_unlock(void)
+{
+    osi_mutex_unlock(&generic_client_mutex);
+}
+
 static void timeout_handler(struct k_work *work)
 {
     generic_internal_data_t *internal = NULL;
@@ -145,10 +168,16 @@ static void timeout_handler(struct k_work *work)
         return;
     }
 
-    bt_mesh_generic_client_cb_evt_to_btc(node->opcode,
-        BTC_BLE_MESH_EVT_GENERIC_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
+    bt_mesh_generic_client_lock();
 
-    bt_mesh_client_free_node(&internal->queue, node);
+    if (!k_delayed_work_free(&node->timer)) {
+        bt_mesh_generic_client_cb_evt_to_btc(node->opcode,
+            BTC_BLE_MESH_EVT_GENERIC_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
+        // Don't forget to release the node at the end.
+        bt_mesh_client_free_node(&internal->queue, node);
+    }
+
+    bt_mesh_generic_client_unlock();
 
     return;
 }
@@ -535,6 +564,9 @@ static void generic_status(struct bt_mesh_model *model,
 
     buf->data = val;
     buf->len  = len;
+
+    bt_mesh_generic_client_lock();
+
     node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, true);
     if (!node) {
         BT_DBG("Unexpected generic status message 0x%x", rsp);
@@ -580,11 +612,15 @@ static void generic_status(struct bt_mesh_model *model,
             break;
         }
 
-        bt_mesh_generic_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
-        // Don't forget to release the node at the end.
-        bt_mesh_client_free_node(&internal->queue, node);
+        if (!k_delayed_work_free(&node->timer)) {
+            bt_mesh_generic_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
+            // Don't forget to release the node at the end.
+            bt_mesh_client_free_node(&internal->queue, node);
+        }
     }
 
+    bt_mesh_generic_client_unlock();
+
     switch (rsp) {
     case BLE_MESH_MODEL_OP_GEN_USER_PROPERTIES_STATUS: {
         struct bt_mesh_gen_user_properties_status *status;
@@ -1181,6 +1217,8 @@ static int generic_client_init(struct bt_mesh_model *model, bool primary)
     client->op_pair = gen_op_pair;
     client->internal_data = internal;
 
+    bt_mesh_generic_client_mutex_new();
+
     return 0;
 }
 
index 384d08a05dc4fb28bb73942a5cee72393dc7ac11..d2b05e0c1ec2cc1dfc668e28fb4bc8e7cae6a84d 100644 (file)
@@ -78,6 +78,10 @@ typedef struct {
     void *cb_data;                      /* User defined callback value */
 } bt_mesh_client_common_param_t;
 
+void bt_mesh_client_model_lock(void);
+
+void bt_mesh_client_model_unlock(void);
+
 int bt_mesh_client_init(struct bt_mesh_model *model);
 
 /**
index b7b9a0413b73c8361318c6ba86c73c2c8a1a0107..c52f35e00e76d9631cc18f3b6e5567d350de79f6 100644 (file)
@@ -17,6 +17,7 @@
 #include <stdbool.h>
 
 #include "osi/allocator.h"
+#include "osi/mutex.h"
 #include "sdkconfig.h"
 
 #include "mesh_types.h"
@@ -128,6 +129,28 @@ static const bt_mesh_client_op_pair_t light_op_pair[] = {
     { BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_SET,           BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_STATUS           },
 };
 
+static osi_mutex_t light_client_mutex;
+
+static void bt_mesh_light_client_mutex_new(void)
+{
+    static bool init;
+
+    if (!init) {
+        osi_mutex_new(&light_client_mutex);
+        init = true;
+    }
+}
+
+static void bt_mesh_light_client_lock(void)
+{
+    osi_mutex_lock(&light_client_mutex, OSI_MUTEX_MAX_TIMEOUT);
+}
+
+static void bt_mesh_light_client_unlock(void)
+{
+    osi_mutex_unlock(&light_client_mutex);
+}
+
 static void timeout_handler(struct k_work *work)
 {
     light_internal_data_t *internal = NULL;
@@ -154,10 +177,16 @@ static void timeout_handler(struct k_work *work)
         return;
     }
 
-    bt_mesh_lighting_client_cb_evt_to_btc(node->opcode,
-        BTC_BLE_MESH_EVT_LIGHTING_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
+    bt_mesh_light_client_lock();
 
-    bt_mesh_client_free_node(&internal->queue, node);
+    if (!k_delayed_work_free(&node->timer)) {
+        bt_mesh_lighting_client_cb_evt_to_btc(node->opcode,
+            BTC_BLE_MESH_EVT_LIGHTING_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
+        // Don't forget to release the node at the end.
+        bt_mesh_client_free_node(&internal->queue, node);
+    }
+
+    bt_mesh_light_client_unlock();
 
     return;
 }
@@ -650,6 +679,9 @@ static void light_status(struct bt_mesh_model *model,
 
     buf->data = val;
     buf->len  = len;
+
+    bt_mesh_light_client_lock();
+
     node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, true);
     if (!node) {
         BT_DBG("Unexpected light status message 0x%x", rsp);
@@ -706,11 +738,15 @@ static void light_status(struct bt_mesh_model *model,
             break;
         }
 
-        bt_mesh_lighting_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
-        // Don't forget to release the node at the end.
-        bt_mesh_client_free_node(&internal->queue, node);
+        if (!k_delayed_work_free(&node->timer)) {
+            bt_mesh_lighting_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
+            // Don't forget to release the node at the end.
+            bt_mesh_client_free_node(&internal->queue, node);
+        }
     }
 
+    bt_mesh_light_client_unlock();
+
     switch (rsp) {
     case BLE_MESH_MODEL_OP_LIGHT_LC_PROPERTY_STATUS: {
         struct bt_mesh_light_lc_property_status *status;
@@ -1371,6 +1407,8 @@ static int light_client_init(struct bt_mesh_model *model, bool primary)
     client->op_pair = light_op_pair;
     client->internal_data = internal;
 
+    bt_mesh_light_client_mutex_new();
+
     return 0;
 }
 
index 3f95168c3a0a3a1698b2464a83118414a594ac20..3626a38dcd1d6288da7c5a442996f410d628a7c0 100644 (file)
@@ -17,6 +17,7 @@
 #include <stdbool.h>
 
 #include "osi/allocator.h"
+#include "osi/mutex.h"
 #include "sdkconfig.h"
 
 #include "mesh_types.h"
@@ -57,6 +58,28 @@ static const bt_mesh_client_op_pair_t sensor_op_pair[] = {
     { BLE_MESH_MODEL_OP_SENSOR_SERIES_GET,     BLE_MESH_MODEL_OP_SENSOR_SERIES_STATUS     },
 };
 
+static osi_mutex_t sensor_client_mutex;
+
+static void bt_mesh_sensor_client_mutex_new(void)
+{
+    static bool init;
+
+    if (!init) {
+        osi_mutex_new(&sensor_client_mutex);
+        init = true;
+    }
+}
+
+static void bt_mesh_sensor_client_lock(void)
+{
+    osi_mutex_lock(&sensor_client_mutex, OSI_MUTEX_MAX_TIMEOUT);
+}
+
+static void bt_mesh_sensor_client_unlock(void)
+{
+    osi_mutex_unlock(&sensor_client_mutex);
+}
+
 static void timeout_handler(struct k_work *work)
 {
     sensor_internal_data_t *internal = NULL;
@@ -83,10 +106,16 @@ static void timeout_handler(struct k_work *work)
         return;
     }
 
-    bt_mesh_sensor_client_cb_evt_to_btc(node->opcode,
-        BTC_BLE_MESH_EVT_SENSOR_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
+    bt_mesh_sensor_client_lock();
 
-    bt_mesh_client_free_node(&internal->queue, node);
+    if (!k_delayed_work_free(&node->timer)) {
+        bt_mesh_sensor_client_cb_evt_to_btc(node->opcode,
+            BTC_BLE_MESH_EVT_SENSOR_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
+        // Don't forget to release the node at the end.
+        bt_mesh_client_free_node(&internal->queue, node);
+    }
+
+    bt_mesh_sensor_client_unlock();
 
     return;
 }
@@ -262,6 +291,9 @@ static void sensor_status(struct bt_mesh_model *model,
 
     buf->data = val;
     buf->len  = len;
+
+    bt_mesh_sensor_client_lock();
+
     node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, true);
     if (!node) {
         BT_DBG("Unexpected sensor status message 0x%x", rsp);
@@ -284,11 +316,15 @@ static void sensor_status(struct bt_mesh_model *model,
             break;
         }
 
-        bt_mesh_sensor_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
-        // Don't forget to release the node at the end.
-        bt_mesh_client_free_node(&internal->queue, node);
+        if (!k_delayed_work_free(&node->timer)) {
+            bt_mesh_sensor_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
+            // Don't forget to release the node at the end.
+            bt_mesh_client_free_node(&internal->queue, node);
+        }
     }
 
+    bt_mesh_sensor_client_unlock();
+
     switch (rsp) {
     case BLE_MESH_MODEL_OP_SENSOR_DESCRIPTOR_STATUS: {
         struct bt_mesh_sensor_descriptor_status *status;
@@ -612,5 +648,7 @@ int bt_mesh_sensor_cli_init(struct bt_mesh_model *model, bool primary)
     client->op_pair = sensor_op_pair;
     client->internal_data = internal;
 
+    bt_mesh_sensor_client_mutex_new();
+
     return 0;
 }
\ No newline at end of file
index 275b29cc6b16d642114603c6082a1f8387161990..01f563994608fe0e15aea72feed35ed9ed2076a3 100644 (file)
@@ -17,6 +17,7 @@
 #include <stdbool.h>
 
 #include "osi/allocator.h"
+#include "osi/mutex.h"
 #include "sdkconfig.h"
 
 #include "mesh_types.h"
@@ -73,6 +74,28 @@ static const bt_mesh_client_op_pair_t time_scene_op_pair[] = {
     { BLE_MESH_MODEL_OP_SCHEDULER_ACT_SET,  BLE_MESH_MODEL_OP_SCHEDULER_ACT_STATUS  },
 };
 
+static osi_mutex_t time_scene_client_mutex;
+
+static void bt_mesh_time_scene_client_mutex_new(void)
+{
+    static bool init;
+
+    if (!init) {
+        osi_mutex_new(&time_scene_client_mutex);
+        init = true;
+    }
+}
+
+static void bt_mesh_time_scene_client_lock(void)
+{
+    osi_mutex_lock(&time_scene_client_mutex, OSI_MUTEX_MAX_TIMEOUT);
+}
+
+static void bt_mesh_time_scene_client_unlock(void)
+{
+    osi_mutex_unlock(&time_scene_client_mutex);
+}
+
 static void timeout_handler(struct k_work *work)
 {
     time_scene_internal_data_t *internal = NULL;
@@ -99,10 +122,16 @@ static void timeout_handler(struct k_work *work)
         return;
     }
 
-    bt_mesh_time_scene_client_cb_evt_to_btc(node->opcode,
-        BTC_BLE_MESH_EVT_TIME_SCENE_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
+    bt_mesh_time_scene_client_lock();
 
-    bt_mesh_client_free_node(&internal->queue, node);
+    if (!k_delayed_work_free(&node->timer)) {
+        bt_mesh_time_scene_client_cb_evt_to_btc(node->opcode,
+            BTC_BLE_MESH_EVT_TIME_SCENE_CLIENT_TIMEOUT, node->ctx.model, &node->ctx, NULL, 0);
+        // Don't forget to release the node at the end.
+        bt_mesh_client_free_node(&internal->queue, node);
+    }
+
+    bt_mesh_time_scene_client_unlock();
 
     return;
 }
@@ -299,6 +328,9 @@ static void time_scene_status(struct bt_mesh_model *model,
 
     buf->data = val;
     buf->len = len;
+
+    bt_mesh_time_scene_client_lock();
+
     node = bt_mesh_is_client_recv_publish_msg(model, ctx, buf, true);
     if (!node) {
         BT_DBG("Unexpected time scene status message 0x%x", rsp);
@@ -328,11 +360,15 @@ static void time_scene_status(struct bt_mesh_model *model,
             break;
         }
 
-        bt_mesh_time_scene_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
-        // Don't forget to release the node at the end.
-        bt_mesh_client_free_node(&internal->queue, node);
+        if (!k_delayed_work_free(&node->timer)) {
+            bt_mesh_time_scene_client_cb_evt_to_btc(node->opcode, evt, model, ctx, val, len);
+            // Don't forget to release the node at the end.
+            bt_mesh_client_free_node(&internal->queue, node);
+        }
     }
 
+    bt_mesh_time_scene_client_unlock();
+
     switch (rsp) {
     case BLE_MESH_MODEL_OP_SCENE_REGISTER_STATUS: {
         struct bt_mesh_scene_register_status *status;
@@ -675,6 +711,8 @@ static int time_scene_client_init(struct bt_mesh_model *model, bool primary)
     client->op_pair = time_scene_op_pair;
     client->internal_data = internal;
 
+    bt_mesh_time_scene_client_mutex_new();
+
     return 0;
 }