Re: Teaching Assembly Language Programming
- From: "robertwessel2@xxxxxxxxx" <robertwessel2@xxxxxxxxx>
- Date: Thu, 21 Jun 2007 14:39:56 -0700
On Jun 21, 2:14 pm, zjrm <zjboyguard-newsg...@xxxxxxxxx> wrote:
After reading your response I finally went out and took a quick look
at the description of the "Test and Set"-ish instructions in the Intel
IS Reference. My naive expectation was that the instructions would be
implicitly atomic. However, this being the x86 IAS, I should have
known better. Apparently you can make *any* of the instructions ADD,
ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, DEC, INC, NEG, NOT, OR,
SBB, SUB, XOR, XADD, and XCHG atomic by throwing the LOCK prefix in
front of it. Why and under what circumstance you might want to do this
with all of these instructions was of course not covered since that's
not the type of detail a reference manual goes into.
The classic test-and-set in x86 is done with xchg, which, BTW, is
always locked (at least on anything more recent than a 80186) when
used with a memory operand.
The other atomic instructions can be very useful with lock-free
techniques. Not that you can't build everything starting with spin-
locks and a test-and-set. For example, let's say you're keeping a
count of some event. With only a mutex or a spin lock, the sequence
is acquire lock, increment counter, release lock. If you don't do
that, two inc instructions running on separate processors can step on
each other (IOW, both read the same old value, both increment that,
and then both write their updated value back to memory, which results
in a lost update). With an atomic increment, you can just do the
increment without the overhead of acquiring a lock or mutex.
Compare and swap (CMPXCHG), for example, can be used in a loop to
update a share data item (perhaps a pointer into a linked list, or
anything else). The trick is that CMPXCHG lets you see if the state
was still the same as when you started the update, and updates it only
if it is. If it isn't (because someone else updated it), you can then
retry. For example, lets say you have a pointer to the first element
of a linked list, and you want to add an item to that linked list. So
you get the first item pointer, build your new item with that its
"next" pointer pointing to the old "first" item, and then use CMPXCHG
to update the first item pointer top point to the new item, but only
if the first pointer is still the same as when you started. If not,
because someone else inserted (or removed) an item in the list, you
can retry the operation by adjusting the pointer in the new item
you're adding.
Compare and swap can be used to implement most of the other locked
operations, but if the task fits, the direct operations are usually
faster and simpler. For example, an atomic increment done with
compare-and-swap:
counter dd 0
mov eax,counter ;assumes aligned
retry:
mov ebx,eax
inc ebx
lock cmpxchg counter,ebx
jnz retry
While that works fine, a simple locked inc would be better.
.
- References:
- Teaching Assembly Language Programming
- From: randyhyde@xxxxxxxxxxxxx
- Re: Teaching Assembly Language Programming
- From: T.M. Sommers
- Re: Teaching Assembly Language Programming
- From: randyhyde@xxxxxxxxxxxxx
- Re: Teaching Assembly Language Programming
- From: zjrm
- Re: Teaching Assembly Language Programming
- From: randyhyde@xxxxxxxxxxxxx
- Re: Teaching Assembly Language Programming
- From: zjrm
- Teaching Assembly Language Programming
- Prev by Date: Re: Teaching Assembly Language Programming
- Next by Date: Re: The Twelve Assembly Lessons
- Previous by thread: Re: Teaching Assembly Language Programming
- Next by thread: Re: Teaching Assembly Language Programming
- Index(es):
Relevant Pages
|
|