On 25/10/2026 10:50, Konstantin Ananyev wrote:
       /* in use, busy wait till current RX/TX iteration is finished */
        if ((puse & BPF_ETH_CBI_INUSE) != 0) {
                RTE_WAIT_UNTIL_MASKED((__rte_atomic uint32_t *)(uintptr_t)&cbi->use,                         UINT32_MAX, !=, puse, rte_memory_order_acquire);
        }

Here, we are waiting when 'puse' will become not equal to 'cbi->use'.
So, any value except current puse is good.

If you look a the sequence diagram, there is no way to arrive here without the callback being removed and `cb` cleared in the DP thread, no matter how you move the arrows around.  So the DP thread will increment `use` once to make it even, and then will never ever reach the callback or increment anything again. We allow any value except current puse, but there are never any values except the current puse and the one after it. It's just these two values we can possibly see.

DP can (and most likely will) call rx/tx_burst again.
Just to give you an example:
--- DP thread:
cbi->use = 1;
                         --- CP thread:
                            read cbi->use (1)
By this time the callback is removed and `cb` is cleared.
--DP thread:
cbi->use = 2;
...
next rx burst:
cbi->use = 3;
How did we reach hear if `cb` is NULL?
                read cbi->use (3)

So CP sees an odd value (3), but it is ok to proceed, as previoud RX iteration (quiscent period) had already finished,
and in new one rx_burst will not see removed call-back.

Reply via email to