Michael Schnell schrieb:
On 06/27/2011 07:52 PM, Hans-Peter Diettrich wrote:
You forget the strength of protection.
Maybe I seem to see what you mean.
You think, a critical section will not prevent that the data that is
accessed by both threads is duplicated in a register or in the Data
cache of the two (or more) CPUs that are trying to access the resource
(variable).
Big Q: *which* resource?
A critical section (process-local MUTEX) is not related to a specific
(memory) resource, except itself, consequently it can not protect any
*other* resource. It also does not block any other thread, not waiting
for entering the critical section, so that all resources are accessible
by all threads, except the critical section (or mutex...) itself.
Thus a concurrent access might erroneously offer a not
updated state to the other CPU.
Right. All threads keep running, except those waiting for a critical
section in use, so that concurrent access can occur in all threads.
Regarding Data Cache, AFAIK, the hardware prevents this. If one CPU
writes a value, an "invalidate" signal for the addresses in that cache
line is sent to all caches, and so all other CPUs will reread the data
from the main memory, which in turn will force a preliminary write from
cache to main memory for the cache line of the first CPU.
An invalidated cache line does not cause a reload from RAM. A reload
only occurs when the next read will result in an cache miss.
Thus "Locked" instructions (that force this mechanism, guaranteeing
proper read-modify-write access even if multiple instructions access the
same data are issued at the same time <overlapping execution> ) only are
necessary outside a critical section protecting the data in question.
That's wrong, since a critical section does not protect any range of
memory addresses.
A locking instruction most probably will invalidate the address in all
caches, before reading from or writing to the specified address. Since
the RAM is locked during the instruction, all other cores or processors
have to wait until the end of the instruction cycle, before they can
access the same address.
My conclusion is, that the said problem with linked lists results from
the pointers not being defined as "volatile".
No. In a bidirectionally linked list up to 4 pointers have to be updated
together, whenever an element is inserted or removed. This leaves much
room for race conditions, that cannot be cured by protecting every
single pointer. Instead the entire chain must be protected, by a MUTEX
or other synchronization means. And then it's only a *convention*, which
object or memory block shall be protected by a MUTEX, no memory barrier
prevents access without obtaining the MUTEX first. Kind of a memory
barrier can be established by putting the list object (head) into a
TThreadList, *provided that* no code will retain references to list
elements after releasing the list object.
And I really don't know
how this could be cured in Pascal other than doing ASM. (I was not aware
of this problem and I feel it should be discussed in the FPC mailing list.)
It's not a matter of the language, when a thread does *not* aquire a
lock before accessing the related resource. It's simply a design flaw,
when some piece of code does not obey the established rules.
DoDi
--
_______________________________________________
Lazarus mailing list
[email protected]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus