Bluetooth: Mesh: Fix adv_send call before enabled.

Since the default syswork thread priority = `-1`.
`adv_send` will call when controller report advertising
sending completed, due to this process by BT RX task, will
maybe process this before `buf_send`, since, sysworkq will be
used by other place and defer by any place.

Note: secure beacon will be 40ms, and friend and lpn will be 20ms.

This problem is very easy to reproduce, especially in native posix.

Signed-off-by: Lingao Meng <menglingao@xiaomi.com>
This commit is contained in:
Lingao Meng 2022-03-23 14:54:01 +08:00 committed by Carles Cufí
commit b76d74cd64

View file

@ -33,6 +33,8 @@
enum {
/** Controller is currently advertising */
ADV_FLAG_ACTIVE,
/** Advertising sending completed */
ADV_FLAG_SENT,
/** Currently performing proxy advertising */
ADV_FLAG_PROXY,
/** The send-call has been scheduled. */
@ -208,6 +210,29 @@ static void send_pending_adv(struct k_work *work)
int err;
adv = CONTAINER_OF(work, struct bt_mesh_ext_adv, work.work);
if (atomic_test_and_clear_bit(adv->flags, ADV_FLAG_SENT)) {
/* Calling k_uptime_delta on a timestamp moves it to the current time.
* This is essential here, as schedule_send() uses the end of the event
* as a reference to avoid sending the next advertisement too soon.
*/
int64_t duration = k_uptime_delta(&adv->timestamp);
BT_DBG("Advertising stopped after %u ms", (uint32_t)duration);
atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
atomic_clear_bit(adv->flags, ADV_FLAG_PROXY);
if (adv->buf) {
net_buf_unref(adv->buf);
adv->buf = NULL;
}
(void)schedule_send(adv);
return;
}
atomic_clear_bit(adv->flags, ADV_FLAG_SCHEDULED);
while ((buf = bt_mesh_adv_buf_get_by_tag(adv->tag, K_NO_WAIT))) {
@ -334,23 +359,13 @@ static void adv_sent(struct bt_le_ext_adv *instance,
return;
}
/* Calling k_uptime_delta on a timestamp moves it to the current time.
* This is essential here, as schedule_send() uses the end of the event
* as a reference to avoid sending the next advertisement too soon.
*/
int64_t duration = k_uptime_delta(&adv->timestamp);
BT_DBG("Advertising stopped after %u ms", (uint32_t)duration);
atomic_clear_bit(adv->flags, ADV_FLAG_ACTIVE);
atomic_clear_bit(adv->flags, ADV_FLAG_PROXY);
if (adv->buf) {
net_buf_unref(adv->buf);
adv->buf = NULL;
if (!atomic_test_bit(adv->flags, ADV_FLAG_ACTIVE)) {
return;
}
(void)schedule_send(adv);
atomic_set_bit(adv->flags, ADV_FLAG_SENT);
k_work_submit(&adv->work.work);
}
#if defined(CONFIG_BT_MESH_GATT_SERVER)