Le Tue, Nov 19, 2024 at 04:34:58PM +0100, Valentin Schneider a écrit :
> +bool ct_set_cpu_work(unsigned int cpu, unsigned int work)
> +{
> +     struct context_tracking *ct = per_cpu_ptr(&context_tracking, cpu);
> +     unsigned int old;
> +     bool ret = false;
> +
> +     preempt_disable();
> +
> +     old = atomic_read(&ct->state);
> +     /*
> +      * Try setting the work until either
> +      * - the target CPU has entered kernelspace
> +      * - the work has been set
> +      */
> +     do {
> +             ret = atomic_try_cmpxchg(&ct->state, &old, old | (work << 
> CT_WORK_START));
> +     } while (!ret && ((old & CT_STATE_MASK) != CT_STATE_KERNEL));
> +
> +     preempt_enable();
> +     return ret;

Does it ignore the IPI even if:

     (ret && (old & CT_STATE_MASK) == CT_STATE_KERNEL))

?

And what about CT_STATE_IDLE?

Is the work ignored in those two cases?

But would it be cleaner to never set the work if the target is elsewhere
than CT_STATE_USER. So you don't need to clear the work on kernel exit
but rather on kernel entry.

That is:

bool ct_set_cpu_work(unsigned int cpu, unsigned int work)
{
        struct context_tracking *ct = per_cpu_ptr(&context_tracking, cpu);
        unsigned int old;
        bool ret = false;

        preempt_disable();

        old = atomic_read(&ct->state);

        /* Start with our best wishes */
        old &= ~CT_STATE_MASK;
        old |= CT_STATE_USER

        /*
         * Try setting the work until either
         * - the target CPU has exited userspace
         * - the work has been set
         */
        do {
                ret = atomic_try_cmpxchg(&ct->state, &old, old | (work << 
CT_WORK_START));
        } while (!ret && ((old & CT_STATE_MASK) == CT_STATE_USER));

        preempt_enable();

        return ret;
}

Thanks.

Reply via email to