nRF5 SDK is not maintained anymore
More Info: Consider nRF Connect SDK for new designs

Bug in nrf_sortlist

I use App timer V2 in the nRF5 SDK and sometimes (not sure of the circumstances) it will insert a timer into the internal m_app_timer_sortlist that is already present in the list. With the nrf_sortlist implementation in nRF5 SDK 17.1.0 this sets the item's p_next to point to itself, and then the next time an item is added into the sortlist, nrf_sortlist_add gets stuck in the while loop. Here is my modification to resolve it:

void nrf_sortlist_add(nrf_sortlist_t const * p_list, nrf_sortlist_item_t * p_item)
{
    ASSERT(p_list);
    ASSERT(p_item);

    nrf_sortlist_item_t ** pp_curr = &(p_list->p_cb->p_head);


    while(*pp_curr != NULL)
    {
        if(*pp_curr == p_item) {
            NRF_LOG_INFO("List:%s, adding duplicate item:%08X, removing then re-adding to ensure order", p_list->p_name, p_item);
            // remove from list
            *pp_curr = p_item->p_next;
            // ensure we can't get stuck in a loop if item pointed to itself
            p_item->p_next = NULL;
            // restart
            pp_curr = &(p_list->p_cb->p_head);
        }
        if(!(p_list->compare_func(*pp_curr, p_item)))
        {
            // pp_curr (pointer to current next pointer) pointer value is higher than p_item, break
            break;
        }
        pp_curr = &((*pp_curr)->p_next);

        if(*pp_curr == p_list->p_cb->p_head) {
            // should never happen
            NRF_LOG_ERROR("List:%s, returned to list head, could not insert", p_list->p_name);
            return;
        }
    }

    // p_item next pointer is current item next pointer
    p_item->p_next = *pp_curr;
    // pp_curr next pointer should be p_item
    *pp_curr = p_item;

#if NRF_LOG_LEVEL >= 3
    nrf_sortlist_item_t *prev = NULL;
    if(pp_curr != &(p_list->p_cb->p_head)) {
        prev = (nrf_sortlist_item_t *)((uint8_t *)pp_curr - offsetof(nrf_sortlist_item_t, p_next));
    }

    NRF_LOG_INFO("List:%s, adding element:%08X after:%08X, before:%08X",
                                  p_list->p_name, p_item, prev, p_item->p_next);
#endif
}

Related