Subject: Re: Atomic ops API
To: Johnny Billquist <bqt@softjar.se>
From: Bang Jun-Young <junyoung@netbsd.org>
List: tech-kern
Date: 03/15/2007 21:38:05
On 3/15/07, Johnny Billquist <bqt@softjar.se> wrote:
> Bang Jun-Young wrote:
> > On 3/15/07, Johnny Billquist <bqt@softjar.se> wrote:
> >
> >> Isn't the whole point of a function called "atomic_compare_and_store"
> >> that it would be atomic? Otherwise I would say that it was misnamed.
> >> So, it should not be possible for *target to be modified withing the
> >> atomic_compare_and_store by some other entity, or the function isn't
> >> atomic.
> >>
> >
> > The atomic function means "a function that performs an atomic
> > operation", not
> > "a funtion that is atomic itself."
>
> Then I think the name is stupid, and furthermore, that means that the
> return value of the function is meaningless. It will not tell you
> anything. Instead you will always have to check after the operation
> wether it performed the swap or not. But that in itself will not answer
> the question wether the swap was performed or not either, since the
> value that you were supposed to write in case of a match might be the
> value that was already there.

The return value _is_ very important, indeed. It's used to determine if
*target has been overwritten by another thread before the cas operation was
peformed. If it has, you should load the new value to *target and call
atomic_cas() again. This time if no other thread overwrites *target, the
call succeeds (and returns with the expected 'old' value).

>
> So in essence, your implementation of atomic_compare_and_swap() or
> atomic_compare_and_store becomes a maybe_store(), without you being able
> to tell wether you did the store or not, and without being able to know
> what the value was before the operation.

Actually, it's just not mine. :-) FreeBSD, Solaris, Windows, Linux, and all the
other OS'es making use of fine-grained locking have the almost same atomic
cas functions on i386 architecture.

> What would be the point of this function?

A lot. :-)

For another example, atomic_cas() is used to implement spinlock:

acquire_lock(lock)
{
        while (1)
                if (atomic_cas(lock, 0, 1) == 0)
                        break;

        /*
         * Lock is acquired.
         */
}

Now isn't it clear why the return value is important? :-)

Jun-Young