[Lazarus] thread safe

Hans-Peter Diettrich DrDiettrich1 at aol.com
Tue Jun 28 17:33:50 CEST 2011


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





More information about the Lazarus mailing list