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

Reply via email to