Re: how atomic is the atomic set instruction?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


Oh thanks Mr.Gatliff, and Mr. King.

I think i've lost myself in the big picture, I had a trouble with a small
atomic set.
How i came to this point is that i want to implement a lock-free
algorithm in armv5 architecture.
Since i couldn't find an compare and swap instruction to use in lock-free
code, I've delved into kernel code.
Then i forget what actually i want to do and stucked to atomic_set.

I thought:

v->counter = i;
is compiled as something like that:

load r1, [i]
// hımm!!, what if switching occurs here and another thread changes the
value "i". It is a wrong behaviour.
store r,1[counter]

Then i saw it in my nightmares till i ask it here.

Anyway, i now understand, the atomicity depends on your code design.
"atomic" in atomic_set is just a kind of hint to help developers. Thanks a
lot again, I've learnt more than i asked.

So, then let me come to the actual point.What i want to do is similar like
the following: a lock-free stack

Push(T item)
{
  Node<T> *oldHead;
  Node<T> * newHead =  new Node<T>(item);

  do
  {
     oldhead = Head;
     newHead->next = oldHead;
  } while
    (!CompAndSwap(&Head, oldHead, newHead));
}

What do you advice me for CompAndSwap? I think something like this is not
possible without disabling interrupts and reenabling interrupts as in
atomic_cmpxchg.
Thanks again.





On Mon, Nov 10, 2008 at 4:14 AM, Bill Gatliff <bgat@xxxxxxxxxxxxxxx> wrote:

> Russell King - ARM Linux wrote:
>
> >
> > Actually, that's not correct.  As I've already said:
> >
> >       val = atomic_read(&foo);
> >       manipulate val
> >       atomic_set(val, &foo);
> >
> > is _not_ atomic, and never will be.  Just because something's called
> > "atomic" does not make it overall atomic.
>
> Correct.  That's the same thing I said.  Well, almost.
>
> The atomic_read() is guaranteed uninterruptible per the API
> definition, as is the atomic_set().  But we agree that your three-line
> snippet of code is _not_ uninterruptible in total, and there is no
> (proper) way to make it uninterruptible using any atomic_*() facility,
> because that's not what the facility is for.
>
> If what you are after is an uninterruptible read-modify-write
> sequence, then you need to implement the whole sequence of
> instructions inside of a _critical_section_--- at which point that
> sequence might be described as "atomic".  Which facility you choose to
> implement the critical section depends on what you need protection
> from, but the choices include mutexes and spinlocks--- but not
> anything from atomic_*().
>
> (However, I can see some utility from an atomic_modify() function.  It
> would be a convenience function, just like condition variables, but
> one that when implemented manually might be more error-prone.
> Something to think about).
>
> > No.  The "store to memory" operation is always atomic if it can be only
> > viewed from elsewhere in the system as being either not committed or
> > fully committed.  That is generally the case with ARMs 'STR' instruction.
>
> Correct.
>
> > But... why use atomic_set() just to store a value?  Wouldn't using a
> > standard pointer be sufficient?  It'll generate the same code.
>
> On ARM, yes.  But not in the general case.
>
> Think about an 8-bit machine that implements 32-bit ints using four
> consecutive bytes--- maybe an H8/300, for example.  Such a machine
> would probably not have an instruction to do even an atomic_t assignment.
>
> So in the general case, if what you are doing absolutely depends on
> the ability to do an uninterruptible assignment, etc. then you really
> need to use the atomic_*() functions--- even if today you are working
> on a machine that provides for atomic assignments via normal C
> expressions.  The use of atomic_*() tells the developers who come
> along after you that you _require_ that operation to be atomic for
> some reason, so if they port the code elsewhere they need to preserve
> that behavior.
>
> Where might an example like that show up?  A lock-less ring buffer of
> bytes is one that readily comes to mind.  Without an atomic_t, you
> have to implement the head/tail index updates manually, perhaps inside
> of critical sections provided by spinlocks.  That's unnecessary on
> ARM, or course, because that machine can do atomic reads and writes
> via STR--- and the compiler tends to use that instruction.  But you
> absolutely have to do it on other processors, so it's nice when the
> details are all hidden inside the atomic_*() API.  The same source
> code works properly everywhere.
>
> In other words, in this situation you really do want to forget about
> the host CPU.  If the operation has to be atomic, use atomic_*() and
> let the compiler and kernel do the work on your behalf when necessary.
>
> > And that's my point - if you're trying to use atomic_set() to make
> > something "atomic" then you're being silly.  atomic_set() is just a
> > plain CPU store - it has no overall guaranteed atomicity apart from
> > the fact that it'll issue a store.
>
> Right.  Weeeeelllll, almost right.  On CPUs that can't do a "plain
> store" to an atomic_t object, then atomic_set() does more.  ARM's
> "plain store" instruction is atomic, however, because that's how the
> CPU and compiler work.  (Except in the packed structure case, perhaps,
> but I digress).
>
> > It doesn't make the surrounding operations somehow magically atomic.
>
> Put another way, atomic_*() functions don't magically create
> uninterruptible sections of code beyond what is minimally necessary to
> implement the atomic_*() function itself.
>
> > So, the original question asking about "how atomic atomic_set is"
> > rings very loud alarm bells to me, bringing up big concerns about
> > what the OP wants to do.  If you need to know how atomic atomic_set
> > is, you ARE doing something wrong.
>
> Actually, I think it's a fairly interesting and important question---
> though I agree that you have to answer it very carefully.
>
> If what you want (perhaps without realizing it) is a critical section
> of code, then there's nothing in atomic_*() for you.  If you don't
> realize that and proceed anyway, then we end up with broken code.  I
> prefer to avoid that outcome, and one way to do that is through
> education about what the term "atomic" might mean.
>
> At least the OP put forth the effort to go look at the implementation
> of atomic_set()--- that's more than we get here most days!
>
>
>
> b.g.
> --
> Bill Gatliff
> bgat@xxxxxxxxxxxxxxx
>
-------------------------------------------------------------------
List admin: http://lists.arm.linux.org.uk/mailman/listinfo/linux-arm
FAQ:        http://www.arm.linux.org.uk/mailinglists/faq.php
Etiquette:  http://www.arm.linux.org.uk/mailinglists/etiquette.php


[Linux ARM]     [Linux ARM MSM]     [Linux ARM Kernel]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

Add to Google Follow linuxarm on Twitter