Jim Donelson wrote:
> >It's actually not the best, because when it returns "did not match"
> >you have to loop and try again.
>
> Not sure what else you would do?  The purpose of a spin lock is to
> avoid a more expensive kernel call

It's not a spinlock.

This loop is for a different reason.  You can tell it's different
because it spins when *unlocking* too; a spinlock never does that.

The "did not match" case for compare-exchange is to simulate an atomic
operation like this example:

    int atomic_dec_test(unsigned *mem)
    {
        do {
            old = *mem;
            new = old+1;
        } while (!compare_exchange(mem, old, new));

        return (new != 0);
    }

    void mutex_unlock(unsigned *mem)
    {
        if (atomic_dec_test(mem))
           futex(FUTEX_WAKE, mem);
    }

> > The amount of looping depends on contention level.
>
> The real secret is to reduce the time spent holding the mutex in general.

Think about the code above.  The amount of looping in
atomic_dec_test(), above, is not reduced by reducing the time spent
holding the mutex.

If you hold the mutex for shorter times in more places (moving the
mutex from large regions to small ones), paradoxically it will
*increase* the average amount of looping in atomic_dec_test() and the
other atomic ops.  Usually not by enough to care, but it depends on
the program.

That why compare-exchange (and load-locked/store-conditional CPU
instructions), though universally usable, doesn't have the same
performance characteristics as atomic read-modify-writed ops.  Though,
atomic ops are sometimes implemented as lock-locked/store-conditional
in the chip anyway.. it's a subtle area.

> The purpose of a spin lock is to avoid a more expensive kernel call
> if the mutex is released quickly (or not taken at all). Presumably
> you enter the kernel after n tries and sleep so that you are not
> using up quanta while spinning.

That doesn't work with a single processor.  While you are spinning,
it's impossible for the other thread to release the mutex until you
are preempted, so potential benefit from spinning is marginal and
often outweight by the benefit of not spinning.

> As for priority inversion (where a lower priority task gets to execute
> because is it holding a mutex that a higher priority thread is waiting
> on) that should be addressed in the kernel. The lower priority thread
> should get temporary priority elevation.

Yes, that's what the robust PI mutexes implemention does.

It uses futexes in userspace to avoid entering the kernel just like
the standard futex algorithms, but priority inheritance if it enters
the kernel, and cleverly if a thread or process crashes, the mutex is
safely recoverable too.

-- Jamie
_______________________________________________
uClinux-dev mailing list
uClinux-dev@uclinux.org
http://mailman.uclinux.org/mailman/listinfo/uclinux-dev
This message was resent by uclinux-dev@uclinux.org
To unsubscribe see:
http://mailman.uclinux.org/mailman/options/uclinux-dev

Reply via email to