Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF5 SDK16: FDS Register() atomic variable incremented after checking for the variable

Hello, 

The fds.c fds_register() has suspicious usage of atomic variables. 

ret_code_t fds_register(fds_cb_t cb)
{
    ret_code_t ret;

    if (m_users == FDS_MAX_USERS)
    {
        ret = FDS_ERR_USER_LIMIT_REACHED;
    }
    else
    {
        m_cb_table[m_users] = cb;
        (void) nrf_atomic_u32_add(&m_users, 1);

        ret = NRF_SUCCESS;
    }

    return ret;
}

It is first checked if there is space in the m_cb_table, then m_cb_table is modified and only then atomic add operation is completed. 

It seems to me that the intention here was to do some sort of atomic compare-and-swap when checking for the users, for example

if (FDS_MAX_USERS <= nrf_atomic_u32_add(&m_users, 1))

But even that solution does not protect against e.g. interrupt trying to register another user to fds and incrementing m_users before m_cb_table is modified. I'm just nitpicking here in case m_users is atomic for some very good reason, so far I've never seen an issue which could be tracked down to concurrency problems here. On the other hand this function is the only place where atomic m_users is used, elsewhere the callback table is read until first NULL is found or max_users is reached. 

Related