Subject: Re: Atomic ops API
To: Bang Jun-Young <junyoung@netbsd.org>
From: Johnny Billquist <bqt@softjar.se>
List: tech-kern
Date: 03/15/2007 13:54:01
Bang Jun-Young wrote:
> 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).
You are missing my point.
Your suggested implementation is the problem, since it isn't atomic, and
(as you yourself admitted), the *target might not be the same as when
the compare_and_store part is executed.
My point was that, as I pointed out, if the return value don't really
tell wether the store was performed or not, then the return value is
meaningless. If, however, you were to be sure that the return value
would tell this information, then the rest of your argument is valid.
But this requires that the whole function is performed atomically, and
not just parts of it.
Basically, I'm trying to say that your suggested implementation of cas
will not work, and any code you present the would use the cas function
is really depending on the cas function to be atomic, in the full
meaning of the word.
I don't know if I just am bad at explaining what I'm saying, but I don't
have any problems understanding how to use an atomic_cas(), nor the need
for it. My problem was that your implementation of the atomic_cas()
isn't atomic, and the breaks everything, including your example use of
the function.
You have said it yourself several times that *target can return
unexpected values. These values are then returned by your atomic_cas()
function. Now, if this function can return "unexpected values", how can
you then say that it is usable?
The whole point is that is must return correct values, otherwise it is
unusable. So therefore, between the readout of the old value, and the
writing of a new value, no other processor can be allowed to modify the
*target, or it is unusable and meaningless. Ie. it really needs to be
atomic all the way, and not just a single step of it. :-)
Johnny