Bluetooth: controller: split: Fix ull_disable hang

Under race conditions it is possible that there is no call
to k_sem_give to the waiting k_sem_take in the ull_disable
function.

ull_disable function checks for reference count before
using a mayfly to schedule lll_disable, which in turn
would close requested currently active role event leading
to done event being propogated to ULL. Done event would
then call the set disabled_cb callback when the reference
count is zero, giving the semaphore to the waiting
k_sem_give in the ull_disable.

Under race conditions if the reference count reached zero
after the reference count check and before the disabled_cb
was assigned in the ull_disable function, then there are
chances that a k_sem_give is not called while ull_disable
proceeds to waiting using k_sem_take.

Fixes #21586.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2020-01-10 16:13:16 +05:30 committed by Alberto Escolar
commit b5c63c69ca

View file

@ -1035,14 +1035,19 @@ int ull_disable(void *lll)
u32_t ret;
hdr = HDR_ULL(((struct lll_hdr *)lll)->parent);
if (!hdr || !hdr->ref) {
if (!hdr) {
return ULL_STATUS_SUCCESS;
}
k_sem_init(&sem, 0, 1);
hdr->disabled_param = &sem;
hdr->disabled_cb = disabled_cb;
if (!hdr->ref) {
return ULL_STATUS_SUCCESS;
}
mfy.param = lll;
ret = mayfly_enqueue(TICKER_USER_ID_THREAD, TICKER_USER_ID_LLL, 0,
&mfy);