Just as a sort of sanity check, its not possible to context swap, or interrupt for that fact
in the middle of an ASM instruction right?
like mov eax,[0xAABBCCDD] will execute atomically right?
Asa
Just as a sort of sanity check, its not possible to context swap, or interrupt for that fact
in the middle of an ASM instruction right?
like mov eax,[0xAABBCCDD] will execute atomically right?
Asa
I’m not sure what you mean by an assembler instruction being atomic. In the
example you gave, you COULD take a page fault on the data access. This will
intrinsically cause a context swap (or a possible crash if you at IRQL
APC_LEVEL). You also could take a page fault and while the page fault is
processing, somebody modifies the code before the page fault handler returns
to it.
If your dword data is not aligned on a 4 byte boundary, I’d have to look at
the processor manual for whatever processor is applicable, but don’t believe
there is always a guarantee that another memory write could not happen that
modifies part of the dword your reading from say another processor. This is
especially true if the two parts of the dword cross a cache line boundary.
You could also take an interrupt or get a context switch BETWEEN the example
instruction and the one on either side.
An instruction being atomic usually refers to memory consistency. For
example:
inc, [aCounter]
There is no chance after the instruction executes that aCounter will be
anything than the previous value + 1 (ignoring overflow), although like I
said above, the misaligned case would take some research. Like in your mov
example though, a page fault could happen or interrupt/context switch could
happen. if the data is misaligned, there is also the case of the data
crossing a page boundary, and half of it (really a different cache line)
causing a page fault.
A good rule of thumb is not to expect data unit accesses being atomic unless
they are aligned on a natural boundary.
Usually the question in assembler is a SEQUENCE of instructions happening
atomically. For example:
mov eax,[aCounter]
add eax, 1
mov [aCounter],eax
There is no guarantee that something else will not try to change aCounter
while it’s in the eax register. So this sequence is not guaranteed to be
atomic.
Also note that modern processors execute highly out of order. This means if
you execute:
mov eax, [value1]
mov ebx, [value2]
There is no guarantee if value1 or value2 will actually be read from memory
first, although there is a guarantee of consistency in a single execution
stream, as in:
mov ecx,123
mov edx,456
mov [value1],ecx
mov [value1],edx
mov eax,[value1]
You can be assured eax will contain 456, assuming value1 is normal memory.
This matters if you are reading memory mapped from a device. You would need
an instruction stream that causes a “read barrier” between the value1/value2
example above if you wanted to assure the physical read ordering. This is
exactly what READ_REGISTER_ULONG has.
There are also long running instructions like rep movsb, that are designed
to be interruptible.
Hope I’ve added to your sanity.
Just as a sort of sanity check, its not possible to context swap, or
interrupt for that fact
in the middle of an ASM instruction right?
like mov eax,[0xAABBCCDD] will execute atomically right?
Awww man, that makes things hard, arrrrgg… oh well. Never planned on the ability to be interrupted in the middle of an instruction.
I knew the assembler for incrementing a memory location wasnt atomic, but i never thought that a single instruction could be
interrupted in the middle of it… that just means more work, oh well. thanks for the reply
asa
-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com]On Behalf Of Jan Bottorff
Sent: Monday, March 07, 2005 1:42 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Concurrency Issues
I’m not sure what you mean by an assembler instruction being atomic. In the example you gave, you COULD take a page fault on the data access. This will intrinsically cause a context swap (or a possible crash if you at IRQL >APC_LEVEL). You also could take a page fault and while the page fault is processing, somebody modifies the code before the page fault handler returns to it.
If your dword data is not aligned on a 4 byte boundary, I’d have to look at the processor manual for whatever processor is applicable, but don’t believe there is always a guarantee that another memory write could not happen that modifies part of the dword your reading from say another processor. This is especially true if the two parts of the dword cross a cache line boundary.
You could also take an interrupt or get a context switch BETWEEN the example instruction and the one on either side.
An instruction being atomic usually refers to memory consistency. For example:
inc, [aCounter]
There is no chance after the instruction executes that aCounter will be anything than the previous value + 1 (ignoring overflow), although like I said above, the misaligned case would take some research. Like in your mov example though, a page fault could happen or interrupt/context switch could happen. if the data is misaligned, there is also the case of the data crossing a page boundary, and half of it (really a different cache line) causing a page fault.
A good rule of thumb is not to expect data unit accesses being atomic unless they are aligned on a natural boundary.
Usually the question in assembler is a SEQUENCE of instructions happening atomically. For example:
mov eax,[aCounter]
add eax, 1
mov [aCounter],eax
There is no guarantee that something else will not try to change aCounter while it’s in the eax register. So this sequence is not guaranteed to be atomic.
Also note that modern processors execute highly out of order. This means if you execute:
mov eax, [value1]
mov ebx, [value2]
There is no guarantee if value1 or value2 will actually be read from memory first, although there is a guarantee of consistency in a single execution stream, as in:
mov ecx,123
mov edx,456
mov [value1],ecx
mov [value1],edx
mov eax,[value1]
You can be assured eax will contain 456, assuming value1 is normal memory. This matters if you are reading memory mapped from a device. You would need an instruction stream that causes a “read barrier” between the value1/value2 example above if you wanted to assure the physical read ordering. This is exactly what READ_REGISTER_ULONG has.
There are also long running instructions like rep movsb, that are designed to be interruptible.
Hope I’ve added to your sanity.
Just as a sort of sanity check, its not possible to context swap, or interrupt for that fact
in the middle of an ASM instruction right?
like mov eax,[0xAABBCCDD] will execute atomically right?
Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256
You are currently subscribed to ntdev as: unknown lmsubst tag argument: ‘’
To unsubscribe send a blank email to xxxxx@lists.osr.com
Well now wait a minute. It might help if you could explain exactly what
you’re trying to do or guard against. For example, for most situations
the page fault handler Jan mentioned usually shouldn’t be an issue that
requires special consideration – I can’t imagine off the top of my head
a situation where you would need extra work to deal specially with the
case of a memory access instruction not being “atomic” as a result of a
page fault. If you can give us a hint what you’re up to, we might be
able to save you some work.
Chuck
----- Original Message -----
From: “Asa Yeamans”
To: “Windows System Software Devs Interest List”
Sent: Monday, March 07, 2005 2:51 PM
Subject: RE: [ntdev] Concurrency Issues
Awww man, that makes things hard, arrrrgg… oh well. Never planned on
the ability to be interrupted in the middle of an instruction.
I knew the assembler for incrementing a memory location wasnt atomic,
but i never thought that a single instruction could be
interrupted in the middle of it… that just means more work, oh well.
thanks for the reply
asa
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of Jan Bottorff
Sent: Monday, March 07, 2005 1:42 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Concurrency Issues
I’m not sure what you mean by an assembler instruction being atomic. In
the example you gave, you COULD take a page fault on the data access.
This will intrinsically cause a context swap (or a possible crash if you
at IRQL >APC_LEVEL). You also could take a page fault and while the page
fault is processing, somebody modifies the code before the page fault
handler returns to it.
If your dword data is not aligned on a 4 byte boundary, I’d have to look
at the processor manual for whatever processor is applicable, but don’t
believe there is always a guarantee that another memory write could not
happen that modifies part of the dword your reading from say another
processor. This is especially true if the two parts of the dword cross a
cache line boundary.
You could also take an interrupt or get a context switch BETWEEN the
example instruction and the one on either side.
An instruction being atomic usually refers to memory consistency. For
example:
inc, [aCounter]
There is no chance after the instruction executes that aCounter will be
anything than the previous value + 1 (ignoring overflow), although like
I said above, the misaligned case would take some research. Like in your
mov example though, a page fault could happen or interrupt/context
switch could happen. if the data is misaligned, there is also the case
of the data crossing a page boundary, and half of it (really a different
cache line) causing a page fault.
A good rule of thumb is not to expect data unit accesses being atomic
unless they are aligned on a natural boundary.
Usually the question in assembler is a SEQUENCE of instructions
happening atomically. For example:
mov eax,[aCounter]
add eax, 1
mov [aCounter],eax
There is no guarantee that something else will not try to change
aCounter while it’s in the eax register. So this sequence is not
guaranteed to be atomic.
Also note that modern processors execute highly out of order. This means
if you execute:
mov eax, [value1]
mov ebx, [value2]
There is no guarantee if value1 or value2 will actually be read from
memory first, although there is a guarantee of consistency in a single
execution stream, as in:
mov ecx,123
mov edx,456
mov [value1],ecx
mov [value1],edx
mov eax,[value1]
You can be assured eax will contain 456, assuming value1 is normal
memory. This matters if you are reading memory mapped from a device. You
would need an instruction stream that causes a “read barrier” between
the value1/value2 example above if you wanted to assure the physical
read ordering. This is exactly what READ_REGISTER_ULONG has.
There are also long running instructions like rep movsb, that are
designed to be interruptible.
Hope I’ve added to your sanity.
- Jan
Just as a sort of sanity check, its not possible to context swap, or
interrupt for that fact
in the middle of an ASM instruction right?
like mov eax,[0xAABBCCDD] will execute atomically right?
Yes, No and Maybe.
Yes: if you prefix the instruction with the “lock” prefix, it’ll be
atomic.
No: If the memory access is not aligned, it won’t be atomic.
Maybe: Atomic with respect to what? IMHO The previous Yes is true with
respect to just about all interrupts which don’t involve bus errors.
Likewise, the previous No is definitely the case with respect to many
hardware interrupts, but *might* well be atomic from a “software” point
of view.
My point: If you need something like that to be Atomic, then there are
plenty of “InterlockedDoSomethingOrOther” functions.
What leads you to ask this question?
MH.
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Asa Yeamans
Sent: 07 March 2005 03:49
To: Windows System Software Devs Interest List
Subject: [ntdev] Concurrency Issues
Just as a sort of sanity check, its not possible to context swap, or
interrupt for that fact
in the middle of an ASM instruction right?
like mov eax,[0xAABBCCDD] will execute atomically right?
Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
You are currently subscribed to ntdev as: unknown lmsubst tag argument:
‘’
To unsubscribe send a blank email to xxxxx@lists.osr.com
This email and any attachments is confidential, may be legally privileged and is intended for the use of the addressee only. If you are not the intended recipient, please note that any use, disclosure, printing or copying of this email is strictly prohibited and may be unlawful. If received in error, please delete this email and any attachments and confirm this to the sender.
Asa Yeamans wrote:
Awww man, that makes things hard, arrrrgg… oh well. Never planned on
the ability to be interrupted in the middle of an instruction.
I knew the assembler for incrementing a memory location wasnt atomic,
but i never thought that a single instruction could be
interrupted in the middle of it… that just means more work, oh
well. thanks for the reply
I don’t see how this possibly changes anything, especially for your example:
mov eax, [0xAABBCCDD]
How would you know the difference? Whether an interrupt happens at the
beginning of the instruction, or the middle of the instruction, or the
end of the instruction, so what? Nothing can go wrong here. When the
instruction is complete, eax will contain the contents of 0xAABBCCDD.
Now, take this case as a counter-example:
xchg eax, [0xAABBCCDD]
This instruction involves two steps: a read from memory, and a write to
memory. Here, a worst case scenario would have some other process, or
some other processor, sneak in to the middle and alter AABBCCDD. The
net result would be information loss, with the old value of eax being
lost. However, the Pentium protects against this case by automatically
asserting the LOCK signal, so that the worst case scenario cannot
occur. You might get a page fault in referring to address AABBCCDD, but
by the time this instruction completes, eax will contain the value that
used to be in 0xAABBCCDD, and 0xAABBCCDD will contain the value that
used to be in eax.
So, as someone else asked, it would be interesting for you to share with
us the scenario that is causing you grief.
–
Not a situation yet, its partly a curiosity question of how much can
you assume about whats really going on. Obviously as everyone knows
concurrent programming is really hard, you have to think of everything
that could possibly happen at every moment and code with that in mind.
Basically at what level do you have to stop worry about getting interrupted?
I know its not the C statement level, because statements break down to
multiple processor instructions. I code most of the time with the understanding
that a ‘simple’ processor instruction will execute atomically. I can understand
how reading a value from memory could be interrupted by a page-fault, but from
what I understand, and correct me if im wrong, is that the page fault handler
runs, then the instrcution *reexecutes* and does so atomically. Now I can
understand how the complex instructions arent atomic, like the ones that copy
memory back and forth. Anyways, this is more of a curiosity question than
anything else, wondering how far down you have to go in order to get atomic
guarantees.
Asa
(i hope that makes sense)
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of Tim Roberts
Sent: Monday, March 07, 2005 12:29 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Concurrency Issues
Asa Yeamans wrote:
Awww man, that makes things hard, arrrrgg… oh well. Never planned on
the ability to be interrupted in the middle of an instruction.
I knew the assembler for incrementing a memory location wasnt atomic,
but i never thought that a single instruction could be
interrupted in the middle of it… that just means more work, oh
well. thanks for the reply
I don’t see how this possibly changes anything, especially for your example:
mov eax, [0xAABBCCDD]
How would you know the difference? Whether an interrupt happens at the
beginning of the instruction, or the middle of the instruction, or the
end of the instruction, so what? Nothing can go wrong here. When the
instruction is complete, eax will contain the contents of 0xAABBCCDD.
Now, take this case as a counter-example:
xchg eax, [0xAABBCCDD]
This instruction involves two steps: a read from memory, and a write to
memory. Here, a worst case scenario would have some other process, or
some other processor, sneak in to the middle and alter AABBCCDD. The
net result would be information loss, with the old value of eax being
lost. However, the Pentium protects against this case by automatically
asserting the LOCK signal, so that the worst case scenario cannot
occur. You might get a page fault in referring to address AABBCCDD, but
by the time this instruction completes, eax will contain the value that
used to be in 0xAABBCCDD, and 0xAABBCCDD will contain the value that
used to be in eax.
So, as someone else asked, it would be interesting for you to share with
us the scenario that is causing you grief.
–
Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256
You are currently subscribed to ntdev as: xxxxx@rivin.net
To unsubscribe send a blank email to xxxxx@lists.osr.com
Sorry for the tautology, but you have to worry about atomicity iff you
need to worry about atomicity. You really shouldn’t be thinking about it
at the instruction level, but at the logical level.
Under what circumstances do you *care* whether something happens
atomically? Typically, the only time is when you are worried about
corrupting a shared resource. All accesses to all shared resources
should always be protected by appropriate synchronization mechanisms
such as mutexes, spinlocks, etc. Period. And don’t try to muck with
memory being used for DMAs outside of the DMA routines… you’ll just
end up with grief.
About the only example of the kind of low-level atomicity that you seem
to be asking about is the InterlockedXXX functions. These result in a
bus locked instruction that are guaranteed to do the operation that they
are doing atomically, if you don’t go out of your way to frustrate them
(e.g. by using non-cached memory). That doesn’t mean that something else
might not be doing something at the same time, because it might it just
means that the memory location they are operating on is guaranteed to be
accessed atomically. And it doesn’t mean that you might not get
interrupted by a page fault, but as someone said, it will get restarted
and run atomically. The documentation says that these functions are only
atomic WRT other Interlocked functions. This is because it knows that
there are some circumstances (possibly on alternate architectures) where
it might have to replace the bus-locked instruction with a spinlock
protected version, but in most cases it will end up being globally atomic.
BTW, you won’t be able to use inline assembly in 64-bit Windows anyway,
so stick to the published APIs unless you have a very good reason not to.
Asa Yeamans wrote:
Not a situation yet, its partly a curiosity question of how much can
you assume about whats really going on. Obviously as everyone knows
concurrent programming is really hard, you have to think of everything
that could possibly happen at every moment and code with that in mind.
Basically at what level do you have to stop worry about getting interrupted?
I know its not the C statement level, because statements break down to
multiple processor instructions. I code most of the time with the understanding
that a ‘simple’ processor instruction will execute atomically. I can understand
how reading a value from memory could be interrupted by a page-fault, but from
what I understand, and correct me if im wrong, is that the page fault handler
runs, then the instrcution *reexecutes* and does so atomically. Now I can
understand how the complex instructions arent atomic, like the ones that copy
memory back and forth. Anyways, this is more of a curiosity question than
anything else, wondering how far down you have to go in order to get atomic
guarantees.Asa
(i hope that makes sense)
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of Tim Roberts
Sent: Monday, March 07, 2005 12:29 PM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Concurrency IssuesAsa Yeamans wrote:
>Awww man, that makes things hard, arrrrgg… oh well. Never planned on
>the ability to be interrupted in the middle of an instruction.
>I knew the assembler for incrementing a memory location wasnt atomic,
>but i never thought that a single instruction could be
>interrupted in the middle of it… that just means more work, oh
>well. thanks for the replyI don’t see how this possibly changes anything, especially for your example:
mov eax, [0xAABBCCDD]
How would you know the difference? Whether an interrupt happens at the
beginning of the instruction, or the middle of the instruction, or the
end of the instruction, so what? Nothing can go wrong here. When the
instruction is complete, eax will contain the contents of 0xAABBCCDD.Now, take this case as a counter-example:
xchg eax, [0xAABBCCDD]
This instruction involves two steps: a read from memory, and a write to
memory. Here, a worst case scenario would have some other process, or
some other processor, sneak in to the middle and alter AABBCCDD. The
net result would be information loss, with the old value of eax being
lost. However, the Pentium protects against this case by automatically
asserting the LOCK signal, so that the worst case scenario cannot
occur. You might get a page fault in referring to address AABBCCDD, but
by the time this instruction completes, eax will contain the value that
used to be in 0xAABBCCDD, and 0xAABBCCDD will contain the value that
used to be in eax.So, as someone else asked, it would be interesting for you to share with
us the scenario that is causing you grief.
–
…/ray..
Please remove “.spamblock” from my email address if you need to contact
me outside the newsgroup.