Re: [fpc-devel] volatile variables
On 30 Jun 2011, at 14:26, Michael Schnell wrote: On 06/30/2011 11:52 AM, Jonas Maebe wrote: On 30 Jun 2011, at 10:38, Michael Schnell wrote: But e.g. if you use a TThreadList instance "myList" with multiple threads it can't be the way to go to include any occurrence of myList.xxx by a critical section just to make sure that the cache synchronization has happened and the instance variable itself in fact is valid. That's where optimization comes in, Very wrong assumption. I simply misunderstood you (I thought you meant that there should be a solution to avoid having to use critical sections around all accesses to fields that may be accessed from multiple threads). However, what is a wrong assumption on your part is that when I replied to fpc-other with you in CC, explicitly mentioning "moved to fpc-other because unrelated to developing FPC", that it's ok to reply back to fpc-devel (moreover removing that remark in the process). This thread has gone off topic for long enough now on this list, and further posts on this topic to this list will be rejected. Jonas FPC mailing lists admin ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
Am 30.06.2011 14:53, schrieb Michael Schnell: On 06/30/2011 11:45 AM, Jonas Maebe wrote: There is none. FPC has a "volatile" modifier in svn trunk, but it currently only affects the node tree optimizer. ... Its only use is for memory mapped I/O. I don't suppose the node tree optimizer is memory mapped I/O ??? No, but the node tree optimizer might optimize away two consecutive reads from or writes to a "memory mapped" variable which might be necessary for the hardware... e.g. (theoretical pseudo code scenario) === source begin === var a: Integer; volatile; absolute $42; b: Integer; begin b := a; // this might be necessary for the hardware, but the optimizer will remove the first statement if it doesn't know about "volatile" b := a; end; === source end === Regards, Sven ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/30/2011 03:29 PM, Andrew Brunner wrote: In a case I observed, it did cause a significant problem to the server. Yes, it was disastrous, and ONLY evident during stress tests. ... which encourages me to suggest that it is a nasty bug _somewhere_. Maybe even in the hardware used. I can't believe that the Posix specs allow for such problem to occur. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Thu, Jun 30, 2011 at 8:04 AM, Michael Schnell wrote: > - if the potential cache incoherency would not be handled by Hardware / OS > / Libraries on behalf of user land programs, I feel that this would so > disastrous and ubiquitous that it result in so many programs not working on > SMP systems that it would be a really well known issue. I agree. This problem when encountered was hidden during steady state testing. The list was consistently working as expected. Where it failed was when the core was ~80% usage and it walked - and it was on my test system here using daily Ubuntu x64 builds - lord knows what kernel it had those days. Infact, it could possibly be an ubiquitous exploit waiting for disaster when code normally running code encounters stale values across cores. You can imagine systems designed to never fail - fail for no known reason at all... In a case I observed, it did cause a significant problem to the server. Yes, it was disastrous, and ONLY evident during stress tests. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/30/2011 11:31 AM, Hans-Peter Diettrich wrote: Consider the shareable bi-linked list, where insertion requires code like this: list.Lock; //prevent concurrent access ... //determine affected list elements new.prev := prev; //prev must be guaranteed to be valid new.next := next; prev.next := new; next.prev := new; list.Unlock; I really would like to see a test case proving my assumption wrong that this in fact just woks We found that - my original "volatile" question is invalid, as the function calls done with list.lock and list.unlock are a "volatile barrier" preventing the compiler from caching some value inappropriately in a register, simply because they are function calls. - the MUTEX operations done with list.lock and list.unlock (at least on PCs in Linux and Windows) use library calls that includes memory barriers - if the potential cache incoherency would not be handled by Hardware / OS / Libraries on behalf of user land programs, I feel that this would so disastrous and ubiquitous that it result in so many programs not working on SMP systems that it would be a really well known issue. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/30/2011 11:45 AM, Jonas Maebe wrote: There is none. FPC has a "volatile" modifier in svn trunk, but it currently only affects the node tree optimizer. ... Its only use is for memory mapped I/O. I don't suppose the node tree optimizer is memory mapped I/O ??? -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/29/2011 09:44 PM, Vinzent Höfler wrote: If they are accessed by only one thread, I'd assert that each core's view on its own cache is not susceptible to memory ordering issues I don't suppose this is that simple. AFAIK, the cache does not work on byte addresses, but on entities of cache lines that are 128 byte or whatever. So a cache can't see if a certain variable is accessed by another thread, but needs to store and reload a complete line. Thus one CPU might modify a value and write back the cache line while another CPU modified a value of another variable in the same cache line. As this situation obviously is handled by the hardware, I do suppose that the case of multiple CPUs modifying the same variable is handled, too (but of course without software considerations not regarding the hardcore cases like an atomic read-modify-write access or cycle-level memory ordering). -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/30/2011 11:52 AM, Jonas Maebe wrote: On 30 Jun 2011, at 10:38, Michael Schnell wrote: Regarding FPC, TCriticalSection is a decent encapsulation for pthread_mutex_... when used in this way. But e.g. if you use a TThreadList instance "myList" with multiple threads it can't be the way to go to include any occurrence of myList.xxx by a critical section just to make sure that the cache synchronization has happened and the instance variable itself in fact is valid. That's where optimization comes in, Very wrong assumption. Optimization is not the question here it's just working vs. not working. In a previous post the claim was that if the variable is not in the cache of the appropriate CPU, a cache synchronization is not automatically done by the underling system (Hardware / OS / Libraries) and thus the variable has an erroneous value unless the application program uses some special means to provide coherency. In fact I doubt this, but this was the claim and thus needs to be discussed here. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Thu, Jun 30, 2011 at 4:31 AM, Hans-Peter Diettrich wrote: > > After these considerations I'd understand that using Interlocked > instructions in the code would ensure such read/write-through, but merely as > a side effect - they also lock the bus for every instruction, what's not > required when concurrent access has been excluded by other means before. I too have come to that conclusion. It remains to be seen/decided though, who's responsibility is it to ensure/enforce coherency? Jonas was suggesting that the posix implementation (but he probably meant kernel) was already doing that via CriticalSection. > Furthermore we need concrete examples[2], how (to what extent) it's required > to use these special instructions/procedures, in examples like above. When > cache synchronization is a big issue, then the usage of related > (thread-unaware) objects should be discussed as well, i.e. how to ensure > that their use will cause no trouble, e.g. by invalidating the entire cache > before. Some FPC work may have been done in this area - intentional or not. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 30 Jun 2011, at 10:42, Michael Schnell wrote: On 06/29/2011 09:44 PM, Vinzent Höfler wrote: That's Ada's definition of "volatile". C's definition is less stronger, but should basically have the same effect. Nice and what is the FPC definition ? There is none. FPC has a "volatile" modifier in svn trunk, but it currently only affects the node tree optimizer. There are many other parts of the compiler that completely ignore it (from the inliner to the i386 assembler peephole optimizer), and hence it is probably not that useful in its current incarnation. If such functionality were properly implemented, the final behaviour and definition would however probably be pretty much the same as the ADA definition Vinzent posted. However, as has been mentioned several times before: "volatile" has absolutely no use to make programs thread safe. Its only use is for memory mapped I/O. Jonas___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
30.06.2011 13:31, Hans-Peter Diettrich: If so, would it help to enclose above instructions in e.g. Synchronized begin update the links... end; If by such hypothetical "synchronized" operator you mean just memory barriers and nothing else, then AFAICS this would not be of much use in practice, because in case of strictly one thread barriers are unneeded anyway, and in case of 2 or more threads barriers are typically insufficient (because most of the time threads would also need race protection, which is not provided by barriers alone). If what you mean here is rather a full-blown critical section with just some more elegant and generic syntax (i.e. a replacement of EnterCriticalSection/LeaveCriticalSection a la java), then yes, it might be nice, but mostly aesthetic-wise. Nikolai ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/29/2011 09:44 PM, Vinzent Höfler wrote: On Wed, 29 Jun 2011 13:28:20 +0200, Hans-Peter Diettrich Ada2005 RM: |C.6(16): For a volatile object all reads and updates of the object as | a whole are performed directly to memory. |C.6(20): The external effect [...] is defined to include each read and | update of a volatile or atomic object. The implementation shall | not generate any memory reads or updates of atomic or volatile | objects other than those specified by the program. That's Ada's definition of "volatile". C's definition is less stronger, but should basically have the same effect. Nice and what is the FPC definition ? Thanks, -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/29/2011 09:00 PM, Vinzent Höfler wrote: POSIX: pthread_mutex_(un)lock() & Co. Or, maybe I didn't understand the question... I suppose, you did understand what I intended to say. Regarding FPC, TCriticalSection is a decent encapsulation for pthread_mutex_... when used in this way. But e.g. if you use a TThreadList instance "myList" with multiple threads it can't be the way to go to include any occurrence of myList.xxx by a critical section just to make sure that the cache synchronization has happened and the instance variable itself in fact is valid. Moreover I don't think it can be the way to go to enforce the application programmer to plan his software in a way that somehow else he needs to make sure that such an instance variable arrives in the appropriate CPU's cache. So I do hope that the constructors of the hardware, the OS and the libraries already somehow did take care of this issue O:-) , -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
Vinzent Höfler schrieb: Question is, what makes one variable use read/write-through, while other variables can be read from the cache, with lazy-write? Synchronisation. Memory barriers. That's what they are for. And this doesn't happen out of thin air. How else? Ok, maybe I misunderstood your question. Normally, these days every memory access is cached (and that's of course independent from compiler optimizations). This should be "normal" (speedy) behaviour. But there are usually possibilities to define certain areas as write-through (like the video frame buffer). But that's more a chip-set thing than it has anything to do with concurrent programming. I also thought about cache or page attributes (CONST vs. DATA sections), but these IMO don't offer the fine granularity, that would allow to separate synchronized from unsynchronized variables (class/record members!) in code. Even the memory manager would have to deal with two classes of un/synced memory then :-( Apart from that you have to use the appropiate CPU instructions. Seems to be the only solution. Is this a compiler requirement, which has to enforce read/write-through for all volatile variables? No. "volatile" (at least in C) does not mean that. Can you provide a positive answer instead? Ada2005 RM: |C.6(16): For a volatile object all reads and updates of the object as | a whole are performed directly to memory. |C.6(20): The external effect [...] is defined to include each read and | update of a volatile or atomic object. The implementation shall | not generate any memory reads or updates of atomic or volatile | objects other than those specified by the program. That's Ada's definition of "volatile". C's definition is less stronger, but should basically have the same effect. Is that positive enough for you? ;) Much better ;-) But what would this mean to FPC code in general (do we *need* such attributes?), and what will be their speed impact? This obviously depends on the effects of the specific synchronizing instructions, inserted by the compiler. But if so, which variables (class fields...) can ever be treated as non-volatile, when they can be used from threads other than the main thread? Without explicit synchronisation? Actually, none. Do you understand the implication of your answer? I hope so. :) When it's up to every coder, to insert explicit synchronization whenever required, how to determine the places where explicit code is required? By careful analysis. Although there may exist tools which detect potentially un-synchronised accesses to shared variables, there will be no tool that inserts synchronisation code automatically for you. I wouldn't like such tools, except the compiler itself :-( Consider the shareable bi-linked list, where insertion requires code like this: list.Lock; //prevent concurrent access ... //determine affected list elements new.prev := prev; //prev must be guaranteed to be valid new.next := next; prev.next := new; next.prev := new; list.Unlock; What can we expect from the Lock method/instruction - what kind of synchronizaton (memory barrier) can, will or should it provide? My understanding of a *full* cache synchronization would slow down not only the current core and cache, but also all other caches? If so, would it help to enclose above instructions in e.g. Synchronized begin update the links... end; so that the compiler can make all memory references (at least reads) occur read/write-through, inside such a code block? Eventually a global cache sync can be inserted on exit from such a block. After these considerations I'd understand that using Interlocked instructions in the code would ensure such read/write-through, but merely as a side effect - they also lock the bus for every instruction, what's not required when concurrent access has been excluded by other means before. Conclusion: We need a documentation of the FPC specific means of cache synchronization, with their guaranteed effects on every target[1]. Furthermore we need concrete examples[2], how (to what extent) it's required to use these special instructions/procedures, in examples like above. When cache synchronization is a big issue, then the usage of related (thread-unaware) objects should be discussed as well, i.e. how to ensure that their use will cause no trouble, e.g. by invalidating the entire cache before. [1] When the effects of the "primitíves" vary amongst targets, then either more specific documentation is required, or higher level target-insensitive procedures with a guaranteed behaviour. Eventually both, so that the experienced coder can use conditional code for the different handling on various targets. [2] References to e.g. C code samples IMO is inappropriate, because the user cannot know what special handling such a different compiler will apply to its compiled code (see "volatile").
Re: [fpc-devel] volatile variables
On 06/29/2011 05:47 PM, Jonas Maebe wrote: ... Thanks for the multiple pointers. I was just trying to construct an example that (a) is similar to stuff an normal user might think would be sure to work and (b) if the cache-sync problems really exist in the way discussed is likely to fail on an SMP-machine so that it makes sense to do a test. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Wed, 29 Jun 2011 13:28:20 +0200, Hans-Peter Diettrich wrote: Vinzent Höfler schrieb: Question is, what makes one variable use read/write-through, while other variables can be read from the cache, with lazy-write? Synchronisation. Memory barriers. That's what they are for. And this doesn't happen out of thin air. How else? Ok, maybe I misunderstood your question. Normally, these days every memory access is cached (and that's of course independent from compiler optimizations). But there are usually possibilities to define certain areas as write-through (like the video frame buffer). But that's more a chip-set thing than it has anything to do with concurrent programming. Apart from that you have to use the appropiate CPU instructions. Is this a compiler requirement, which has to enforce read/write-through for all volatile variables? No. "volatile" (at least in C) does not mean that. Can you provide a positive answer instead? Ada2005 RM: |C.6(16): For a volatile object all reads and updates of the object as | a whole are performed directly to memory. |C.6(20): The external effect [...] is defined to include each read and | update of a volatile or atomic object. The implementation shall | not generate any memory reads or updates of atomic or volatile | objects other than those specified by the program. That's Ada's definition of "volatile". C's definition is less stronger, but should basically have the same effect. Is that positive enough for you? ;) I meant "volatile" as read/write-through, not related to C. Read as "synchronized", if you ar more comfortable with that term ;-) In that case, there is no such requirement for a compiler. At least not for the ones I know of. But if so, which variables (class fields...) can ever be treated as non-volatile, when they can be used from threads other than the main thread? Without explicit synchronisation? Actually, none. Do you understand the implication of your answer? I hope so. :) When it's up to every coder, to insert explicit synchronization whenever required, how to determine the places where explicit code is required? By careful analysis. Although there may exist tools which detect potentially un-synchronised accesses to shared variables, there will be no tool that inserts synchronisation code automatically for you. If there were, the Linux community wouldn't have such big trouble to get rid of their "BKL" (big kernel lock) from the days, where the Linux kernel was made preemptible. Aren't we then in the unpleasant situation, that *every* expression can be evaluated using unsynchronized values, unless the compiler uses synchronized read instructions to obtain *every* value [except from stack]? If they are accessed by only one thread, I'd assert that each core's view on its own cache is not susceptible to memory ordering issues. So each thread on its own can be treated like the single-CPU case (i.e. nothing special needed). Synchronisation is only required if different threads of execution may need access to the same, shared variable. But in that case you should synchronise anyway, although in the single-core case you could get away with using types which were guaranteed to be atomic. I've done that a couple of times, but I am well aware that this will break any time soon. Vinzent. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Wed, 29 Jun 2011 15:57:15 +0200, Michael Schnell wrote: On 06/29/2011 01:06 AM, Vinzent Höfler wrote: Without explicit synchronisation? Actually, none. How to do such synchronization with normal portable user-program programming (aka Posix means). POSIX: pthread_mutex_(un)lock() & Co. Or, maybe I didn't understand the question... Vinzent. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: *** GMX Spamverdacht *** Re: [fpc-devel] volatile variables
On Wed, 29 Jun 2011 16:31:32 +0200, Michael Schnell wrote: On 06/29/2011 03:17 PM, Nikolai Zhubr wrote: All places where any non-readonly data could be accessed by 2 or more threads should be protected. Thats it. So this is not supposed to work: Precisely, it is not /guaranteed/ to work if that's what you meant. (Please also note that "give up time slice" does not mean very much on a multi-core/CPU system when the threads are running on different cores/CPUs and thus in "real" parallelity. But I suppose you know that.) As assigning a value to myList in one thread is only a very short time before the other thread reads it, it's very likely that the wrong value is still be in the cache of the worker thread's processor and make it crash. But is is just a very extreme example of a behavior that mostly is assumed to work and according to your wording would be bound to fail. Ass-U-Me. You know. ;) - Yes, this is bound to fail. Vinzent. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 29 Jun 2011, at 17:29, Nikolai Zhubr wrote: > 29.06.2011 18:31, Michael Schnell: > [...] >> So this is not supposed to work: >> >> Main thread: >> >> myThread := TmyThread.Create(True); >> while not myThread.Suspended sleep(0); //give up time slice to allow the >> worker thread to start sleep(0) does not give up the current time slice on all operating systems. Use ThreadSwitch() instead. >> myList := TThreadlist.Create; // set the variable in cache 1 >> myThread.Suspended := False; >> sleep(100); // have the worker thread run >> >> >> >> Worker Thread: >> >> procedure TmyTherad.Execute; >> begin >> myList := NIL; // set the variable in the cache 2 >> Suspended := True; In case this supposed to be a tthread descendent: setting its suspended field to true does not suspend the thread. Call >> myList.Add(. //has the variable been synchronized from the other >> cache >> >> Here the variable myList is not protected. > > I think this code will work fine (at least on win32) because your main thread > issues Sleep() and (implicitely) ResumeThread(), and your worker thread > issues Sleep() and (implicitely) SuspendThread(). I somehow doubt that > passing these system calls could let something remain unflushed in the cache, > as the OS will most probably have to do some synchronization inside these > calls for internal bookkeeping, but this is IMHO kind of side-effect. The sleep(100) in the main thread may not happen before the child thread accesses myList. And if it does: the above code is definitely completely thread unsafe and requires memory barriers if the programmer refuses to use a proper synchronization primitive. You cannot use booleans instead of mutexes and expect things to work. Of course, that does not mean that it is "not supposed to work", as the first quoted sentence above states. It's only not *guaranteed* to work. It may very well work 100 out 100 times you try to actually execute it. But there are definitely circumstances under which it will fail. Maybe we should create a new list called "multithreading", because these discussions have absolutely nothing to do with developing FPC. Jonas___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/29/2011 05:29 PM, Nikolai Zhubr wrote: . I somehow doubt that passing these system calls could let something remain unflushed in the cache, as the OS will most probably have to do some synchronization inside these calls for internal bookkeeping, but this is IMHO kind of side-effect. Today the cache is huge and flushing it is very expensive (as it likely will need to be refilled with the same data). Thus I don't suppose the OS will flush the cache unless absolutely necessary. On x86 the cache works on hardware addresses (not on virtual process addresses) and thus reassigning a thread to the same CPU (which with Linux is a preferred strategy) after intermediately running some other process, would in fact at best find the cache filled with much of the old data. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
29.06.2011 19:57, Hans-Peter Diettrich: [...] imply that in detail all application specific objects must be either local to an thread, or must be protected against concurrent access (shareable)? IMHO yes. [...] Possibly the language could be extended to help in the determination of thread-(un)safe procedures. E.g. references to shareable objects could Well yes, but its probably hard to inject such safety into a general purpose language. After all, pointers are not quite safe even in a single-threaded application! Nikolai ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/29/2011 05:57 PM, Hans-Peter Diettrich wrote: This means that a simplified version of TThreadList would be nice, that allows to wrap a single shareable object and make it usable in an thread-safe way. IMHO just TList is OH for this purpose. It (supposedly) is "per-instance thread safe": if an instance is used just by a single thread, the code is safe, if the same instance is used by multiple threads the code is not safe. The necessity of a more complex definition of thread safety for Objects (as a tribute to the hidden self parameter that is not considered as an "input" by the average user) was the starting point of the discussion in the Lazarus list. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/29/2011 05:28 PM, Hans-Peter Diettrich wrote: The code in a called subroutine doesn't know about the CS. [It usually also doesn't care about from which exact thread it was called] This means that possible recursion must be prevented in all related code in a CS, or (safer) that the CS must be "recursive" (spinlock?) on all platforms. I was taking about the CS Enter and Leave procedures themselves, not about calling functions within a CS I feel that calling a subroutine within a CS is a bad idea anyway as the point of CSes is to hold them as short as possible not to increase the latency of the other threads. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
29.06.2011 18:31, Michael Schnell: [...] So this is not supposed to work: Main thread: myThread := TmyThread.Create(True); while not myThread.Suspended sleep(0); //give up time slice to allow the worker thread to start myList := TThreadlist.Create; // set the variable in cache 1 myThread.Suspended := False; sleep(100); // have the worker thread run Worker Thread: procedure TmyTherad.Execute; begin myList := NIL; // set the variable in the cache 2 Suspended := True; myList.Add(. //has the variable been synchronized from the other cache Here the variable myList is not protected. I think this code will work fine (at least on win32) because your main thread issues Sleep() and (implicitely) ResumeThread(), and your worker thread issues Sleep() and (implicitely) SuspendThread(). I somehow doubt that passing these system calls could let something remain unflushed in the cache, as the OS will most probably have to do some synchronization inside these calls for internal bookkeeping, but this is IMHO kind of side-effect. If it was my program I'd use critical section explicitely anyway to be sure. Nikolai As assigning a value to myList in one thread is only a very short time before the other thread reads it, it's very likely that the wrong value is still be in the cache of the worker thread's processor and make it crash. But is is just a very extreme example of a behavior that mostly is assumed to work and according to your wording would be bound to fail. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
Nikolai Zhubr schrieb: 29.06.2011 15:28, Hans-Peter Diettrich: But if so, which variables (class fields...) can ever be treated as non-volatile, when they can be used from threads other than the main thread? Without explicit synchronisation? Actually, none. Do you understand the implication of your answer? When it's up to every coder, to insert explicit synchronization whenever required, how to determine the places where explicit code is required? All places where any non-readonly data could be accessed by 2 or more threads should be protected. Thats it. Consider what this means to the RTL and other libraries. That code typically is not thread-safe, so that it cannot be called safely from threads. Doesn't this imply that in detail all application specific objects must be either local to an thread, or must be protected against concurrent access (shareable)? This means that a simplified version of TThreadList would be nice, that allows to wrap a single shareable object and make it usable in an thread-safe way. Possibly the language could be extended to help in the determination of thread-(un)safe procedures. E.g. references to shareable objects could be allowed only as "const" or "in" parameters, so that the compiler can disallow persistent copies of such references. But like the C "const" modifier, such a strict attribute may be problematic in many cases. DoDi ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
Michael Schnell schrieb: All code executed in between such two calls is absolutely ignorant of the state of the CS, there is no in/outside. The "State" (relevant to this thread) of CS does not change when some code of the thread is between enter and leave. So it is not "ignorant" but it does know that it "owns" the CS and is the only thread that is inside. The code in a called subroutine doesn't know about the CS. [It usually also doesn't care about from which exact thread it was called] This means that possible recursion must be prevented in all related code in a CS, or (safer) that the CS must be "recursive" (spinlock?) on all platforms. DoDi ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/29/2011 04:33 PM, Andrew Brunner wrote: Here is a nice example of one that actually works... http://wiki.lazarus.freepascal.org/Manager_Worker_Threads_System Nice. But actually what we need is an example that does not work and shows a case that the cache incoherency in fact is not handled by the hardware in a way a dummy would assume it would. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
Here is a nice example of one that actually works... http://wiki.lazarus.freepascal.org/Manager_Worker_Threads_System Granted I wrote this sample and Wiki a long time ago, but you may want to read this ;-) ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/29/2011 03:17 PM, Nikolai Zhubr wrote: All places where any non-readonly data could be accessed by 2 or more threads should be protected. Thats it. So this is not supposed to work: Main thread: myThread := TmyThread.Create(True); while not myThread.Suspended sleep(0); //give up time slice to allow the worker thread to start myList := TThreadlist.Create; // set the variable in cache 1 myThread.Suspended := False; sleep(100); // have the worker thread run Worker Thread: procedure TmyTherad.Execute; begin myList := NIL; // set the variable in the cache 2 Suspended := True; myList.Add(. //has the variable been synchronized from the other cache Here the variable myList is not protected. As assigning a value to myList in one thread is only a very short time before the other thread reads it, it's very likely that the wrong value is still be in the cache of the worker thread's processor and make it crash. But is is just a very extreme example of a behavior that mostly is assumed to work and according to your wording would be bound to fail. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 28 Jun 2011, at 22:25, Hans-Peter Diettrich wrote: Andrew Brunner schrieb: Wrong. Sigh... Order of execution is paramount just about everywhere. It can be disastrous if not understood. Remember ***cores!=threads*** people. If your experience is really that chaotic, I think it's worth some deeper investigation. 1) Can one thread be executed on multiple cores, at the same time? Not unless a speculative parallel execution environment is used (either in software or hardware), but because of their speculative nature those are by design transparent to the software (and afaik all of them are still only in research stages). If so, shouldn't there exist means (flags...) to tell the OS, that FPC executables are not (yet) ready for such automatic parallelism? Such flags don't exist because there is no need for them. 2) When a thread wanders around, from one core to another one, shouldn't be the starting conditions (CPU state, caches) exactly in the state when the thread was stopped on the previous core? Yes. That is the job of the operating system (which will do this by inserting memory barriers, cache flushes etc). You seem to assume that the cache of the previous core may contain some updated data, that was not yet written back into RAM when the thread is resumed on a different core, whose cache happens to contain other values? This really would be a very big problem :-( [So big that I cannot believe that it really exists] Indeed, it does not exist, unless there is a bug in the kernel of his machine. 3) When above cache inconsistencies can occur, how can even a single- threaded program work correctly? Indeed. Jonas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/29/2011 01:28 PM, Hans-Peter Diettrich wrote: Do you understand the implication of your answer? Regarding Objects it would mean that it's forbidden to create an object in one thread and use it in another one. This is done very often.I can't believe that the hardware is that bad. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/29/2011 01:06 AM, Vinzent Höfler wrote: Without explicit synchronisation? Actually, none. How to do such synchronization with normal portable user-program programming (aka Posix means). -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 07:05 PM, Vinzent Höfler wrote: On Tue, 28 Jun 2011 15:54:35 +0200, Michael Schnell wrote: No, it can't. "volatile" just ensures that accessing the variable results in actual memory accesses. That does not mean cache-coherence, so another core may still see other (as in "older") values. This is done by the hardware (but not aggressive enough to ensure atomic instructions to work without additional bus-locking) It should not. Right you are. We found that a compiler needs to consider any function call as a "volatile barrier" and is not allowed to cache any memory-value in a register as the called function might somehow know the address and access that variable (even in a single threaded application). As a CS "Enter" and "Leave" is done as a function call this aspect of my original question is solved. Thanks, -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 08:09 PM, Hans-Peter Diettrich wrote: When you have a look at TThreadList.LockList/UnlockList, then you'll see that LockList enters the critical section, and UnlockList leaves it. Yep This is how a CS works. All code executed in between such two calls is absolutely ignorant of the state of the CS, there is no in/outside. The "State" (relevant to this thread) of CS does not change when some code of the thread is between enter and leave. So it is not "ignorant" but it does know that it "owns" the CS and is the only thread that is inside. (You could say, regarding a certain thread the possible CS states are "I'm outside", "I'm inside", and "I'm waiting for entry". The states of the CS regarding other threads is not of interest for this thread, other that they are known not to be inside if this thread is inside.) -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
29.06.2011 15:28, Hans-Peter Diettrich: But if so, which variables (class fields...) can ever be treated as non-volatile, when they can be used from threads other than the main thread? Without explicit synchronisation? Actually, none. Do you understand the implication of your answer? When it's up to every coder, to insert explicit synchronization whenever required, how to determine the places where explicit code is required? All places where any non-readonly data could be accessed by 2 or more threads should be protected. Thats it. Main thread is no special in this regard. In order to reduce potential collisions, different critical section objects (mutexes) can be used to protect different (think unrelated) blocks of data in more fine-grained way. Nikolai Aren't we then in the unpleasant situation, that *every* expression can be evaluated using unsynchronized values, unless the compiler uses synchronized read instructions to obtain *every* value [except from stack]? DoDi ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 06:42 PM, Hans-Peter Diettrich wrote: I could not find a definition of the mutex struct, to determine whether it contains any user-alterable values. When "the value" is declared outside the mutex struct, it will be accessible also *without* locking the mutex first. What do you mean by "Mutex struct". The Data structure a Mutex internally uses is in Kernel space and invisible to the user program. With appropriate archs (such as X86 and modern ARM), in fact pthreadlib uses FUTEX instead of MUTEX, here a data structure in user land memory is allocated by the library, but a user program never should access it. When using a MUTEX or FUTEX as a critical section it protects all the data that only is accessed by instructions issued after doing the "enter" and before doing the "leave" call. So it's entirely up to the user program to define what data is protected. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
Vinzent Höfler schrieb: Question is, what makes one variable use read/write-through, while other variables can be read from the cache, with lazy-write? Synchronisation. Memory barriers. That's what they are for. And this doesn't happen out of thin air. How else? Is this a compiler requirement, which has to enforce read/write-through for all volatile variables? No. "volatile" (at least in C) does not mean that. Can you provide a positive answer instead? I meant "volatile" as read/write-through, not related to C. Read as "synchronized", if you ar more comfortable with that term ;-) But if so, which variables (class fields...) can ever be treated as non-volatile, when they can be used from threads other than the main thread? Without explicit synchronisation? Actually, none. Do you understand the implication of your answer? When it's up to every coder, to insert explicit synchronization whenever required, how to determine the places where explicit code is required? Aren't we then in the unpleasant situation, that *every* expression can be evaluated using unsynchronized values, unless the compiler uses synchronized read instructions to obtain *every* value [except from stack]? DoDi ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 28/06/11 15:15, Andrew Brunner wrote: On Tue, Jun 28, 2011 at 9:00 AM, Henry Vermaak wrote: On 28/06/11 14:23, Andrew Brunner wrote: There is no problem no need for volatile variables. Compare and Swap or Interlocked mechanisms will solve any problems. Nope. You still need to prevent the cpu from reordering instructions with memory barriers. I'm starting to sound like a broken record. If you don't understand this, use the threading primitives provided by your operating system like everyone else. Henry You've got your list particiapants mixed up. It was me who suggested order is important (at least on the lazarus discussion). No, I was talking to you. And I am am 100% correct. Interlocked / CAS happen in one shot. They don't need barriers. They are protected. I think you have my conversations mixed up. The reason for my comment is that I get the idea that you think you can only use atomic operations to implement thread safe code. Please correct me if I'm misunderstanding you. If this is the case, you are mistaken. Your code then probably only works on x86 and amd64 (with some luck), since on those architectures atomic instructions aren't reordered with loads or stores. In fact, x86 and amd64 _only_ reorders stores after loads. Architectures like later ARM/POWER can reorder _anything_ for you, including atomic operations. You will need memory barriers in addition to atomic instructions, even on x86/amd64 in all but the simplest cases. This is basically what pthread_mutex and windows critical sections already do for you (spinlock + barrier). If they're not working for you, you are using them incorrectly. Henry ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 10:25 PM, Hans-Peter Diettrich wrote: Can you run your test again, assuring that only one thread can access the list at the same time, but *without* the Interlocked updates? This would be a very nice move of Andrew's !!! If he uses a single TCriticalSection instance to protect all accesses to the variables (seemingly a set of pointer structures used to create a double linked list) this is bound to work correctly on any hardware with any count of cores under all circumstances. Otherwise there is some bug. And this bug needs to be located. If it is in the user software, Andrew will be able to fix it. If is is in the RTL/LCL we need to issue a patch request here. If it is in the Linux infrastructure (libraries or OS) an appropriate patch request can be generated as well If it is in the Windows infrastructure we are out of luck. If it is in the hardware, same needs to go to the trash bin BTW. The fact that the current code with interlocked instructions works on a higher core-count engine than the code without, does not mean that it in fact is correct or even better, as this drastically changes the timing and might just by chance prevent concurrency from occurring. In fact, IMHO, interlocked instructions are not appropriate here, anyway, as same are constructed to ensure single-Word variable atomic behavior (necessary e.g. to construct a MUTEX or Semaphore). But here, multi-variable atomicity is necessary and same is only possible using a critical section of some kind (and within same - by Posix definition - atomicity and concurrency-protection is granted anyway, thus interlocked instructions do nothing but slow down the code thread-related behavior of the code> ). -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 06:33 PM, Andrew Brunner wrote: Remember ***cores!=threads*** people. Wrong regarding the issue in question (see the message by Jonas). I'm at a loss for words. So you equate threads to cores? A (Posix compliant) user software needs to consider each thread as running on it's own CPU and thus any concurrency to be allowed (e.g. expecting that a higher priority thread is not interrupted by a lower priority thread has to be considered erroneous.) -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 06:07 PM, Andrew Brunner wrote: You can stick your head in the sand all you want, just don't run your code on multi-core cpus and expect valid stability - and come back here complaining on how unstable your multi-threaded application is due to FPC design! If a correctly done Posix compliant program does not run on some system there is a bug in the infrastructure. This discussion is not about which programming paradigm is better, but it is only sensible because an example of a not correctly working Posix compliant program had been offered and thus it's necessary to localize the bug and - if same is not in the user software - request a patch. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, 28 Jun 2011 23:29:52 +0200, Hans-Peter Diettrich wrote: Vinzent Höfler schrieb: No, it can't. "volatile" just ensures that accessing the variable results in actual memory accesses. That does not mean cache-coherence, so another core may still see other (as in "older") values. I dare to disagree. When reading a volatile variable requires a memory (RAM) read in one core, it will require the same read in any other core, and updates have to occur in write-through into the RAM. Sorry, no. Memory access does not mean "RAM" here, it simply means that the compiler is not allowed to keep the value in a register or collapse multiple writes to the same location into a single one. (Ages ago, this happened to me on a memory-mapped i8254, where the counter register requires two 8-bit accesses to the same (memory-mapped) address and the compiler simply removed the first write). So, memory access /might/ be the local cache of the core, unless the actual memory region is write-through (because it's memory-mapped I/O, which was the original intent of "volatile". See above.). A difference could occur only, when the "memory" access may end up in the cache instead of in RAM. But that's precisely what would happen. Question is, what makes one variable use read/write-through, while other variables can be read from the cache, with lazy-write? Synchronisation. Memory barriers. That's what they are for. Is this a compiler requirement, which has to enforce read/write-through for all volatile variables? No. "volatile" (at least in C) does not mean that. It was never intended for synchronisation between threads, cores, or even multiple processors. This is a misconception probably stemming from the fact that it was used to "synchronise" accesses to global variables within interrupt-handlers and the like where this is totally valid as long as there's only one single processor running all the code. The picture immediately changes if such an interrupt-handler (e.g. "another thread") is executed on a different processor/core/whatchamacallit. But if so, which variables (class fields...) can ever be treated as non-volatile, when they can be used from threads other than the main thread? Without explicit synchronisation? Actually, none. Vinzent. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
Andrew Brunner schrieb: On Tue, Jun 28, 2011 at 9:33 AM, Michael Schnell wrote: And this has been discussed in the other message: If the variable in fact is global the compiler needs to avoid caching it, if it is static and the function is in another module it might still decide to cache it, but you are right: it is not likely that it does make this difference. Well, I think one issue is that each core has it's own cache. 1.) How can we get the core to not relent and have the code handed off to another core until we're finished? Never, in a preemptive multi-tasking environment. It's easier to *encourage* such swapping, by inserting Sleep calls. 2.) How can we get the core to have a synchronised copy of a particular variable (aside from CAS)? How can we get *unsynchronized* copies of the same variable, to prove the need for explicit synchronization? And how to prove that the copies *are* different, with means that do not happen to enforce synchronicity themselves? Please note that we'll have to restrict the sample code in a way, that leaves *no* room for *accidental* concurrent access, bypassing the one-thread-only access protection. DoDi ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
Vinzent Höfler schrieb: On Tue, 28 Jun 2011 15:54:35 +0200, Michael Schnell wrote: But if you do the same with volatile static int x; the code will stay and another thread can watch x growing in a time sharing system. No, it can't. "volatile" just ensures that accessing the variable results in actual memory accesses. That does not mean cache-coherence, so another core may still see other (as in "older") values. I dare to disagree. When reading a volatile variable requires a memory (RAM) read in one core, it will require the same read in any other core, and updates have to occur in write-through into the RAM. A difference could occur only, when the "memory" access may end up in the cache instead of in RAM. Question is, what makes one variable use read/write-through, while other variables can be read from the cache, with lazy-write? Is this a compiler requirement, which has to enforce read/write-through for all volatile variables? But if so, which variables (class fields...) can ever be treated as non-volatile, when they can be used from threads other than the main thread? DoDi ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
Andrew Brunner schrieb: On Tue, Jun 28, 2011 at 9:43 AM, Michael Schnell wrote: On 06/28/2011 04:31 PM, Andrew Brunner wrote: how developers can force code execution in order w/o using a third party library? Execution in order only makes sense when there is another thread that relies on this order. Wrong. Sigh... Order of execution is paramount just about everywhere. It can be disastrous if not understood. Remember ***cores!=threads*** people. If your experience is really that chaotic, I think it's worth some deeper investigation. 1) Can one thread be executed on multiple cores, at the same time? If so, shouldn't there exist means (flags...) to tell the OS, that FPC executables are not (yet) ready for such automatic parallelism? 2) When a thread wanders around, from one core to another one, shouldn't be the starting conditions (CPU state, caches) exactly in the state when the thread was stopped on the previous core? Isn't that effect caused by your monitor, that forces the thread into suspended state frequently? You seem to assume that the cache of the previous core may contain some updated data, that was not yet written back into RAM when the thread is resumed on a different core, whose cache happens to contain other values? This really would be a very big problem :-( [So big that I cannot believe that it really exists] 3) When above cache inconsistencies can occur, how can even a single-threaded program work correctly? A little chance exists, that an thread moves so often between two cores, that both caches contain copies of the process-local data. But this never should cause trouble, because single-threaded code was never required to use Interlocked access to its private data. 3.1) Chances are higher for a multi-threaded application, where the caches can contain any number of copies of shared (main thread) memory areas. But what would this mean to threaded code in general? I cannot believe that thread-aware code must use Interlocked access to *all* variables, even in the main thread, because no procedure can know from which thread it is actually called, in which core. That said I have some doubts, regarding your conclusions. Can you run your test again, assuring that only one thread can access the list at the same time, but *without* the Interlocked updates? DoDi ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
28.06.2011 22:38, Vinzent Höfler wrote: involving some mutex. Such proper constructs are not enforced by pascal language automatically (like say in java), so mistakes are quite possible (and sometimes do happen). JFTR, but they aren't /enforced/ in Java, neither. Well, ok, I didn't mean that "synchronize" is enforced, but rather that it is provisioned with such (simple) syntax that enforces some sanity and hides most complications (so that one can not forget to leave the protected block, or try to use some invalid mutex or try to modify the mutex directly etc...) (That said, I'm personally quite happy with pascal though) Nikolai Vinzent. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
At beginning of June I've found the following link on the ReactOS mailing list when they were discussing about memory ordering and volatile as well: http://kernel.org/doc/Documentation/volatile-considered-harmful.txt For those interested the following is the link to the starting discussion: http://www.reactos.org/archives/public/ros-dev/2011-June/014277.html (I hope the mail thread works in the web view as well as in my mail client) Regards, Sven On 28.06.2011 13:14, Michael Schnell wrote: A similar discussion is going on in Lazarus-develop, but this obviously is a compiler question. In C, there is the volatile keyword that ensures that after the code sequence enters the next C instruction after that which modified this variable, another thread sees the correct state of the variable. This is ensured by not caching the value in registers and on SMP systems additionally by low level stuff like memory barriers. Of course this does not protect concurrent read-modify-write accesses (same need to be protected by low level atomic instructions or MUTEX and friend). For variables not defined as volatile, (e.g.) pthread_mutex (and similar stuff on Windows) can be used to protect them. AFAIK, in Pascal all Global (Static) variables are considered to be handled as volatile, so no problem here (other than handling all of them them as volatiles might decrease performance slightly). But what about variables on the heap ? If class instance variables or - say - a liked list done with records created by "new" are accessed by multiple threads, how can said consistency be enforced ? Even if you use a critical section to do the protection, this does not help if the compiler decides to cache the variable in a register while entering or exiting the critical section. But even without dedicated protection, a volatile variable should be able to be be monitored from another thread. Can this be enforced in Pascal for help variables ? -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, 28 Jun 2011 20:34:19 +0200, Nikolai Zhubr wrote: involving some mutex. Such proper constructs are not enforced by pascal language automatically (like say in java), so mistakes are quite possible (and sometimes do happen). JFTR, but they aren't /enforced/ in Java, neither. Vinzent. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, 28 Jun 2011 18:11:29 +0200, Hans-Peter Diettrich wrote: I think that you should give at least an example, where instruction reordering makes a difference. Neither a compiler nor a processor is allowed to reorder instructions in a way, that breaks the def/use (produce/consume...) chain (see SSA - Single Static Assignment). Well, yes. But multiple processors are actually allowed to do that. That's why the double-lock idiom for Singletons is bound to break on multi-cores. Vinzent. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, 28 Jun 2011 20:09:18 +0200, Hans-Peter Diettrich wrote: When you have a look at TThreadList.LockList/UnlockList, then you'll see that LockList enters the critical section, and UnlockList leaves it. All code executed in between such two calls is absolutely ignorant of the state of the CS, there is no in/outside. Of course, why should it bother? The call to "unlock" should ensures whatever memory synchronisation is required. Vinzent. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
28.06.2011 19:42, Hans-Peter Diettrich wrote: Jonas Maebe schrieb: 2.) Blocking access as described in 4.11 does not address execution order. It does guarantee that if T1 locks the mutex, changes the value, unlocks the mutex [...] Can you explain please, to what "changes the value" applies? To some variable, not explicitly named here, but not to the mutex. I could not find a definition of the mutex struct, to determine whether it contains any user-alterable values. When "the value" is declared outside the mutex struct, it will be accessible also *without* locking the mutex first. A mutex is usually treated as opaque. It is only used when entering/leaving critical section, not for storing any user-accessible data. However I can imagine that some mutex derived *class* (TCriticalSection) can have additional fields, that are inaccessible until some code obtains the mutex (similar to TThreadList). Otherwise a mutex cannot protect anything but itself. It is responsibility of a programmer to ensure that all accesses to the variable in question is surrounded by proper enter/leave constructs involving some mutex. Such proper constructs are not enforced by pascal language automatically (like say in java), so mistakes are quite possible (and sometimes do happen). Nikolai DoDi ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
Michael Schnell schrieb: Only the ordering decision "inside" vs "outside" of the critical section is necessary for threaded user application. If both Enter and Leave do a "full fence" barrier, I suppose we are safe. Since the condition is only stored *inside* the CS or mutex, no other code will know about it, unless it *explicitly* queries the state of the object. When you have a look at TThreadList.LockList/UnlockList, then you'll see that LockList enters the critical section, and UnlockList leaves it. All code executed in between such two calls is absolutely ignorant of the state of the CS, there is no in/outside. DoDi ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
Andrew Brunner schrieb: On Tue, Jun 28, 2011 at 9:23 AM, Jonas Maebe wrote: On topic, Jonas can you take a few moments to describe how developers can force code execution in order w/o using a third party library? Is there a compiler directive we can use? I think that you should give at least an example, where instruction reordering makes a difference. Neither a compiler nor a processor is allowed to reorder instructions in a way, that breaks the def/use (produce/consume...) chain (see SSA - Single Static Assignment). No library will prevent you from implementing undetectable side-effects, or to use alias. When in this code snippet list.Add(x); i := list.Count; the statements cannot be executed out-of-sequence, or in parallel, then I assume that every subroutine call will disallow to move instructions from after the call to before it. Everything else would be insane. DoDi ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
Jonas Maebe schrieb: 2.) Blocking access as described in 4.11 does not address execution order. It does guarantee that if T1 locks the mutex, changes the value, unlocks the mutex [...] Can you explain please, to what "changes the value" applies? I could not find a definition of the mutex struct, to determine whether it contains any user-alterable values. When "the value" is declared outside the mutex struct, it will be accessible also *without* locking the mutex first. However I can imagine that some mutex derived *class* (TCriticalSection) can have additional fields, that are inaccessible until some code obtains the mutex (similar to TThreadList). Otherwise a mutex cannot protect anything but itself. DoDi ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, 28 Jun 2011 15:20:22 +0200, Andrew Brunner wrote: On Tue, Jun 28, 2011 at 8:11 AM, Jonas Maebe wrote: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html (point 4.11) Nope. Nothing about order - just access - and that is entirely on the application level - not system. |synchronize thread execution and also synchronize memory with respect to other threads. How do you interpret "synchronise memory with respect to other threads" then? Vinzent. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, 28 Jun 2011 15:54:35 +0200, Michael Schnell wrote: But if you do the same with volatile static int x; the code will stay and another thread can watch x growing in a time sharing system. No, it can't. "volatile" just ensures that accessing the variable results in actual memory accesses. That does not mean cache-coherence, so another core may still see other (as in "older") values. I believe that inserting some ptherad_mutex... calls will not force the compiler to bother about some intermediate values of a non volatile variable. Well, then it's probably overly aggressive or buggy. I believe that with FPC global variables are assumed to be volatile and not optimized away or cashed in registers. But what about heap-variables ? They are not volatile, I'd guess. And I don't see the need to assume they are. You would always need proper synchronisation constructs here. Thus true for global variables, not necessary true for static variables as they can't be accessed by a function defined in another module (I don't know whether the C compiler makes a difference) It should not. It can't possibly assume that a call to pthread_...() wouldn't result in a recursive call back to the caller... ;) Vinzent. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, Jun 28, 2011 at 10:17 AM, Michael Schnell wrote: > You still did not give an example Don't take my word. Just look at the wikipedia link I already posted which indicates otherwise. >> Remember ***cores!=threads*** people. > > Wrong regarding the issue in question (see the message by Jonas). I'm at a loss for words. So you equate threads to cores? You know what forget it. Don't bother. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
You can stick your head in the sand all you want, just don't run your code on multi-core cpus and expect valid stability - and come back here complaining on how unstable your multi-threaded application is due to FPC design! > User programs are not supposed to bother about anything beyond threads that > are a well defined arch independent paradigm. Wrong again... Sigh... Think interlocked variables in your code and you will be fine. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 05:02 PM, Andrew Brunner wrote: Wrong. Sigh... Order of execution is paramount just about everywhere. It can be disastrous if not understood. You still did not give an example Remember ***cores!=threads*** people. Wrong regarding the issue in question (see the message by Jonas). User programs are not supposed to bother about anything beyond threads that are a well defined arch independent paradigm. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 04:38 PM, Andrew Brunner wrote: 1.) How can we get the core to not relent and have the code handed off to another core until we're finished? 2.) How can we get the core to have a synchronised copy of a particular variable (aside from CAS)? I suppose you need to ask these questions the hardware designers at Intel or AMD (or read the appropriate docs). If cache synchronization would not be done (even without forcing it by atomic interlocked instructions or memory barriers) regarding the huge cache provide with modern CPUs a thread would _never_ see what another thread writes into memory. But (unless some kind of atomicness or ordering is required) there are no issues on that behalf. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, Jun 28, 2011 at 9:43 AM, Michael Schnell wrote: > On 06/28/2011 04:31 PM, Andrew Brunner wrote: >> >> how developers >> can force code execution in order w/o using a third party library? > > Execution in order only makes sense when there is another thread that relies > on this order. Wrong. Sigh... Order of execution is paramount just about everywhere. It can be disastrous if not understood. Remember ***cores!=threads*** people. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 28 Jun 2011, at 16:28, Andrew Brunner wrote: Jonas already pointed you to it: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_11 "Applications shall ensure that access to any memory location by more than one thread of control (threads or processes) is restricted such that no thread of control can read or modify a memory location while another thread of control may be modifying it." Please note the "read or modify". If you fail to understand this, you can read the source of a posix threads implementation, e.g. nptl (which is part of libc). I honestly don't believe that by the above statement has anything to do with what we're talking about here. And I'm thinking it's because of the two issues. One is threads. One is cores. I think we need to focus to get to the bottom of what we're all trying to say. The Posix specification (and the Win32 api documentation referred to in this thread) doesn't care whether all threads are executed by the same or by different cores, and/or whether separate threads are rescheduled to different cores at different time slices. The specified behaviour is guaranteed to be the same under all circumstances exactly because it is defined at the level of "threads" rather than "cores". That's the whole point of having abstractions such as threads and specifying their behaviour. Even if you would create a libpthread implementation that works on top of MPI and which distributes threads over an entire cluster of different machines, then still the same behaviour would have to be guaranteed (because the *threads* have to comply to the specified behaviour, not specifically pipelines, cores, processors, machines, accelerator cards, ...). Jonas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, Jun 28, 2011 at 9:33 AM, Michael Schnell wrote: > And this has been discussed in the other message: If the variable in fact is > global the compiler needs to avoid caching it, if it is static and the > function is in another module it might still decide to cache it, but you are > right: it is not likely that it does make this difference. Well, I think one issue is that each core has it's own cache. 1.) How can we get the core to not relent and have the code handed off to another core until we're finished? 2.) How can we get the core to have a synchronised copy of a particular variable (aside from CAS)? ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 04:31 PM, Andrew Brunner wrote: how developers can force code execution in order w/o using a third party library? Execution in order only makes sense when there is another thread that relies on this order. So if both threads use the same critical section for accessing all variables that an ordering is necessary with, the actual ordering used completely within the critical section in fact is irrelevant as no other thread can get in the way at that point. So the high level Posix interface that is provided as TCriticalSection in the RTL/LCL should be workable (but not high performance). -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, Jun 28, 2011 at 9:23 AM, Jonas Maebe wrote: On topic, Jonas can you take a few moments to describe how developers can force code execution in order w/o using a third party library? Is there a compiler directive we can use? ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 04:23 PM, Jonas Maebe wrote: On 28 Jun 2011, at 15:54, Michael Schnell wrote: I believe that inserting some ptherad_mutex... calls will not force the compiler to bother about some intermediate values of a non volatile variable. You believe wrongly. As the compiler does not know anything about what pthread_mutex does just the existence of a function call at that location can trigger that it behaves different from the case that no function call is done. And this has been discussed in the other message: If the variable in fact is global the compiler needs to avoid caching it, if it is static and the function is in another module it might still decide to cache it, but you are right: it is not likely that it does make this difference. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
> Jonas already pointed you to it: > > http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_11 > > "Applications shall ensure that access to any memory location by more than > one thread of control (threads or processes) is restricted such that no > thread of control can read or modify a memory location while another thread > of control may be modifying it." > > Please note the "read or modify". If you fail to understand this, you can > read the source of a posix threads implementation, e.g. nptl (which is part > of libc). I honestly don't believe that by the above statement has anything to do with what we're talking about here. And I'm thinking it's because of the two issues. One is threads. One is cores. I think we need to focus to get to the bottom of what we're all trying to say. I have been following and it is completely agreed that thread locks are NOT what we are trying to discuss. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 28 Jun 2011, at 15:54, Michael Schnell wrote: static int x; void play_with_x(void) { for (i=1; i>0; i--) { x += 1; }; x = 0; }; the compiler will see that x is just defined to be 0 in the end and optimize out thge complete loop. But if you do the same with volatile static int x; the code will stay and another thread can watch x growing in a time sharing system. I believe that inserting some ptherad_mutex... calls will not force the compiler to bother about some intermediate values of a non volatile variable. You believe wrongly. Jonas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 28/06/11 15:09, Andrew Brunner wrote: Of course it is. They issue a hardware memory barrier. This stops the cpu from reordering operations. How do you think anything using pthreads will work if they didn't? Documentation please? If what you are saying is accurate just point me to the documentation? Jonas already pointed you to it: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_11 "Applications shall ensure that access to any memory location by more than one thread of control (threads or processes) is restricted such that no thread of control can read or modify a memory location while another thread of control may be modifying it." Please note the "read or modify". If you fail to understand this, you can read the source of a posix threads implementation, e.g. nptl (which is part of libc). Henry ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, Jun 28, 2011 at 9:00 AM, Henry Vermaak wrote: > On 28/06/11 14:23, Andrew Brunner wrote: >> >> There is no problem no need for volatile variables. Compare and Swap >> or Interlocked mechanisms will solve any problems. > > Nope. You still need to prevent the cpu from reordering instructions with > memory barriers. I'm starting to sound like a broken record. If you don't > understand this, use the threading primitives provided by your operating > system like everyone else. > > Henry You've got your list particiapants mixed up. It was me who suggested order is important (at least on the lazarus discussion). And I am am 100% correct. Interlocked / CAS happen in one shot. They don't need barriers. They are protected. I think you have my conversations mixed up. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re[2]: [fpc-devel] volatile variables
Hello FPC, Tuesday, June 28, 2011, 3:39:29 PM, you wrote: AB> Sort of right. 6 core system. Core 1 locks code block. Code block AB> should still use interlocked statements to make memory assignments so AB> that when Core 1 releases lock - Core 2 can have a real-time image of AB> variable. Otherwise Core 2 may see a stale copy of the variable. Core 2 should only access those variables using the same lock (critical section) as core 1 or data integrity is not garanteed. Critical sections garantee a full fence, pipe lines as invalidated. The only possible problem is the variable caching in a register, but as stated here the call to the function that perform the critical section forces fpc to store the variables in a register to its memory address and the critical section activity forces the fence ensuring all cores see the same data at the same time. You can not protect a code with a critical section and access the data without using the same critical section, so you can not protect code with a critical section and operate over the data in other thread with interlock operations. This is not threading 101, do not ? -- Best regards, José ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
> Of course it is. They issue a hardware memory barrier. This stops the cpu > from reordering operations. How do you think anything using pthreads will > work if they didn't? Documentation please? If what you are saying is accurate just point me to the documentation? ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
> No, that is impossible. That's the whole point of using libraries such as > libpthread. They abstract such issues away. Using atomic operations inside > mutex sections only slows down your program unnecessarily (unless you also > access the target memory location from code not guarded by that mutex, and > also use atomic operations in those alternate cases -- or if you are using a > synchronization primitive from a library that does not observe the same > semantics as libpthread, but that would be a really strange design > decision). Two issues with what you are suggesting Jonas. Issue 1.) libpthread is just a posix implementation. it does not AUTOMATICALLY resolve issues inherent with present day multi-core memory access with respect to cores. It is by definition a thread implementation that includes atomic locks. Issue 2.) Telling people that it is poor design to exclude posix threads implementation is ignorant. FPC is cross platform. Posix threads specification is mainly to offer windows like threadding to unix/linux flavors. > If what you write above would be true, almost no program using libpthread > for synchronization would consistently work on multi-core systems. How many > programs do you know that exclusively use atomic operations to access shared > memory locations inside code regions guarded by a pthread_mutex? Access vs. Order. This is what makes a variable volatile across cores (not threads). ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 28/06/11 14:23, Andrew Brunner wrote: There is no problem no need for volatile variables. Compare and Swap or Interlocked mechanisms will solve any problems. Nope. You still need to prevent the cpu from reordering instructions with memory barriers. I'm starting to sound like a broken record. If you don't understand this, use the threading primitives provided by your operating system like everyone else. Henry ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 28/06/11 14:20, Andrew Brunner wrote: On Tue, Jun 28, 2011 at 8:11 AM, Jonas Maebe wrote: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html (point 4.11) Nope. Nothing about order - just access - and that is entirely on the application level - not system. 1.) Code execution on die is not controlled by pthreads implemention - as it is unaware at that level. Of course it is. They issue a hardware memory barrier. This stops the cpu from reordering operations. How do you think anything using pthreads will work if they didn't? Henry ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 03:23 PM, Andrew Brunner wrote: There is no problem no need for volatile variables. Compare and Swap or Interlocked mechanisms will solve any problems. "volatile" is a directive to the compiler on how to handle a variable. Variables that are not handled by the compiler but handled by non portable low level assembler functions of course are volatile on their own account. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 03:23 PM, Andrew Brunner wrote: Getting developers to chose the right tool for the job is the key here. Regarding "normal" user application there is only one option: Posix. Ans same happily is encapsulated in the RTL/LCL for FPC/Lazarus programmers. "Advanced" (non-portable) programming of course can be necessary in certain projects. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 03:16 PM, Jonas Maebe wrote: The C (or Pascal) compiler has no idea whether or not the global variable will be accessed by the pthread_mutex_lock()/unlock() function. As a result, it will never cache it in a register across function calls, and the call to the mutex function by itself guarantees that the variable's value will be written back. If in C you do static int x; void play_with_x(void) { for (i=1; i>0; i--) { x += 1; }; x = 0; }; the compiler will see that x is just defined to be 0 in the end and optimize out thge complete loop. But if you do the same with volatile static int x; the code will stay and another thread can watch x growing in a time sharing system. I believe that inserting some ptherad_mutex... calls will not force the compiler to bother about some intermediate values of a non volatile variable. I believe that with FPC global variables are assumed to be volatile and not optimized away or cashed in registers. But what about heap-variables ? Even if it's a local variable you don't need it, Of course not as they can't be accessed by anybody but the running thread anyway. the compiler again has to assume that any called function may modify it via an indirect access. ... if same gets the address (which of course is possible with a global variable) Thus true for global variables, not necessary true for static variables as they can't be accessed by a function defined in another module (I don't know whether the C compiler makes a difference) -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 28 Jun 2011, at 15:39, Andrew Brunner wrote: On Tue, Jun 28, 2011 at 8:28 AM, Jonas Maebe > wrote: 1.) Code execution on die is not controlled by pthreads implemention - as it is unaware at that level. I have no idea what you mean by this. What would "code execution off die" be as opposed to "code execution on die"? "on die" image was meant to take you to the code on the actual core being executed. That is to say the core itself is ignorant of what just executed before and will just take the code and execute it. That's why libpthread includes memory barriers. It does guarantee that if T1 locks the mutex, changes the value, unlocks the mutex and then T2 acquires the mutex (either on another cpu or not is irrelevant), then T2 will observe strict memory ordering with respect to T1 as far as this memory location is concerned (i.e., it will see any changes to that memory location performed by T1 that were protected by the mutex). Sort of right. 6 core system. Core 1 locks code block. Code block should still use interlocked statements to make memory assignments so that when Core 1 releases lock - Core 2 can have a real-time image of variable. Otherwise Core 2 may see a stale copy of the variable. No, that is impossible. That's the whole point of using libraries such as libpthread. They abstract such issues away. Using atomic operations inside mutex sections only slows down your program unnecessarily (unless you also access the target memory location from code not guarded by that mutex, and also use atomic operations in those alternate cases -- or if you are using a synchronization primitive from a library that does not observe the same semantics as libpthread, but that would be a really strange design decision). If what you write above would be true, almost no program using libpthread for synchronization would consistently work on multi-core systems. How many programs do you know that exclusively use atomic operations to access shared memory locations inside code regions guarded by a pthread_mutex? Jonas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, Jun 28, 2011 at 8:28 AM, Jonas Maebe wrote: >> 1.) Code execution on die is not controlled by pthreads implemention - >> as it is unaware at that level. > I have no idea what you mean by this. What would "code execution off die" be > as opposed to "code execution on die"? "on die" image was meant to take you to the code on the actual core being executed. That is to say the core itself is ignorant of what just executed before and will just take the code and execute it. >> 2.) Blocking access as described in 4.11 does not address execution order. > > It does guarantee that if T1 locks the mutex, changes the value, unlocks the > mutex and then T2 acquires the mutex (either on another cpu or not is > irrelevant), then T2 will observe strict memory ordering with respect to T1 > as far as this memory location is concerned (i.e., it will see any changes > to that memory location performed by T1 that were protected by the mutex). Sort of right. 6 core system. Core 1 locks code block. Code block should still use interlocked statements to make memory assignments so that when Core 1 releases lock - Core 2 can have a real-time image of variable. Otherwise Core 2 may see a stale copy of the variable. > If by "execution ordering" you mean that there is no guarantee regarding > which thread will acquire the mutex first, then that's true, but > synchonrization races are unrelated to memory ordering issues. Don't bother looking that deep. The topic the poster raised is about variable volatility with respect to thread safe code. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 03:20 PM, Andrew Brunner wrote: Nothing about order - just access - As only on thread can be inside one of the code sequences protected by the CriticalSection, we only need the correct ordering outside vs. inside of the Critical section. so I suppose access management (Full Fence memory barrier) is sufficient. and that is entirely on the application level - not system. We are just talking about normal user applications. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 28 Jun 2011, at 15:20, Andrew Brunner wrote: On Tue, Jun 28, 2011 at 8:11 AM, Jonas Maebe > wrote: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html (point 4.11) Nope. Nothing about order - just access - and that is entirely on the application level - not system. 1.) Code execution on die is not controlled by pthreads implemention - as it is unaware at that level. I have no idea what you mean by this. What would "code execution off die" be as opposed to "code execution on die"? 2.) Blocking access as described in 4.11 does not address execution order. It does guarantee that if T1 locks the mutex, changes the value, unlocks the mutex and then T2 acquires the mutex (either on another cpu or not is irrelevant), then T2 will observe strict memory ordering with respect to T1 as far as this memory location is concerned (i.e., it will see any changes to that memory location performed by T1 that were protected by the mutex). If by "execution ordering" you mean that there is no guarantee regarding which thread will acquire the mutex first, then that's true, but synchonrization races are unrelated to memory ordering issues. Jonas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 03:00 PM, Jonas Maebe wrote: . I don't know about the Windows equivalents. see http://msdn.microsoft.com/en-us/library/ms686355%28v=VS.85%29.aspx ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, Jun 28, 2011 at 8:16 AM, Jonas Maebe wrote: > The C (or Pascal) compiler has no idea whether or not the global variable > will be accessed by the pthread_mutex_lock()/unlock() function. As a result, > it will never cache it in a register across function calls, and the call to > the mutex function by itself guarantees that the variable's value will be > written back. Agreed. And you can make such access atomic. Getting developers to chose the right tool for the job is the key here. But understanding the core issues (pun intented ;-) is the key. > So you don't need volatile. Even if it's a local variable you don't need it, > because as soon as you take the address of a local variable and it can > escape the current function (and hence the current thread), the compiler > again has to assume that any called function may modify it via an indirect > access. > There is no problem no need for volatile variables. Compare and Swap or Interlocked mechanisms will solve any problems. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, Jun 28, 2011 at 8:11 AM, Jonas Maebe wrote: > http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html > (point 4.11) Nope. Nothing about order - just access - and that is entirely on the application level - not system. 1.) Code execution on die is not controlled by pthreads implemention - as it is unaware at that level. 2.) Blocking access as described in 4.11 does not address execution order. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 02:58 PM, Andrew Brunner wrote: A mutex may be able to atomically block access because of its own memory barrier, but I would suggest that employing such a technique on multi-core systems will not ensure an accurate value. If this is true, how can any multithreaded be done ? Only the ordering decision "inside" vs "outside" of the critical section is necessary for threaded user application. If both Enter and Leave do a "full fence" barrier, I suppose we are safe. -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 28 Jun 2011, at 14:32, Michael Schnell wrote: So, regarding C, I understand that (even in a single CPU environment): If all accesses to a variable are protected by a MUTEX, multiple threads will use the variable as expected, only if it is defined as volatile. Otherwise is might be cached in registers and one thread's writing to (i C code but not compiled that way) it might be unnoticed by the other thread. The C (or Pascal) compiler has no idea whether or not the global variable will be accessed by the pthread_mutex_lock()/unlock() function. As a result, it will never cache it in a register across function calls, and the call to the mutex function by itself guarantees that the variable's value will be written back. So you don't need volatile. Even if it's a local variable you don't need it, because as soon as you take the address of a local variable and it can escape the current function (and hence the current thread), the compiler again has to assume that any called function may modify it via an indirect access. Jonas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 28/06/11 14:00, Jonas Maebe wrote: On 28 Jun 2011, at 14:58, Andrew Brunner wrote: On Tue, Jun 28, 2011 at 6:14 AM, Michael Schnell wrote: For variables not defined as volatile, (e.g.) pthread_mutex (and similar stuff on Windows) can be used to protect them. A mutex may be able to atomically block access because of its own memory barrier, but I would suggest that employing such a technique on multi-core systems will not ensure an accurate value. pthread_mutex() does guarantee that. I don't know about the Windows equivalents. I've found this earlier: http://msdn.microsoft.com/en-us/library/ms686355%28v=VS.85%29.aspx Henry ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 28 Jun 2011, at 15:05, Andrew Brunner wrote: On Tue, Jun 28, 2011 at 8:00 AM, Jonas Maebe > wrote: On 28 Jun 2011, at 14:58, Andrew Brunner wrote: A mutex may be able to atomically block access because of its own memory barrier, but I would suggest that employing such a technique on multi-core systems will not ensure an accurate value. pthread_mutex() does guarantee that. I don't know about the Windows equivalents. Specification just describes standard mutex. What makes pthreads specification different to include ordering? http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/ V1_chap04.html (point 4.11) Jonas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, Jun 28, 2011 at 8:00 AM, Jonas Maebe wrote: > > On 28 Jun 2011, at 14:58, Andrew Brunner wrote: > >> On Tue, Jun 28, 2011 at 6:14 AM, Michael Schnell >> wrote: >> >>> For variables not defined as volatile, (e.g.) pthread_mutex (and similar >>> stuff on Windows) can be used to protect them. >>> >> A mutex may be able to atomically block access because of its own >> memory barrier, but I would suggest that employing such a technique on >> multi-core systems will not ensure an accurate value. > > pthread_mutex() does guarantee that. I don't know about the Windows > equivalents. > Specification just describes standard mutex. What makes pthreads specification different to include ordering? ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 28 Jun 2011, at 14:58, Andrew Brunner wrote: On Tue, Jun 28, 2011 at 6:14 AM, Michael Schnell wrote: For variables not defined as volatile, (e.g.) pthread_mutex (and similar stuff on Windows) can be used to protect them. A mutex may be able to atomically block access because of its own memory barrier, but I would suggest that employing such a technique on multi-core systems will not ensure an accurate value. pthread_mutex() does guarantee that. I don't know about the Windows equivalents. Jonas ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On Tue, Jun 28, 2011 at 6:14 AM, Michael Schnell wrote: > For variables not defined as volatile, (e.g.) pthread_mutex (and similar > stuff on Windows) can be used to protect them. > A mutex may be able to atomically block access because of its own memory barrier, but I would suggest that employing such a technique on multi-core systems will not ensure an accurate value. ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 06/28/2011 01:20 PM, Henry Vermaak wrote: "Operations on volatile variables are not atomic, That is of course known. nor do they establish a proper happens-before relationship for threading. I see. So maybe part of my question is invalid. But as pthread_mutex (and the appropriate Windows stuff) contains a memory barrier, same does enforce memory ordering even in an SMP environment, regarding cache operations and with CPUs that do on-the fly reordering. So, regarding C, I understand that (even in a single CPU environment): If all accesses to a variable are protected by a MUTEX, multiple threads will use the variable as expected, only if it is defined as volatile. Otherwise is might be cached in registers and one thread's writing to (i C code but not compiled that way) it might be unnoticed by the other thread. Now how is the volatile state defined in Pascal and how can a heap variable be defined to be handled as volatile ? -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
Re: [fpc-devel] volatile variables
On 28/06/11 12:14, Michael Schnell wrote: A similar discussion is going on in Lazarus-develop, but this obviously is a compiler question. In C, there is the volatile keyword that ensures that after the code sequence enters the next C instruction after that which modified this variable, another thread sees the correct state of the variable. This is completely incorrect. Read this: http://en.wikipedia.org/wiki/Volatile_variable Note this: "Operations on volatile variables are not atomic, nor do they establish a proper happens-before relationship for threading. This is according to the relevant standards (C, C++, POSIX, WIN32), and this is the matter of fact for the vast majority of current implementations. The volatile keyword is basically worthless as a portable threading construct." Henry ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel
[fpc-devel] volatile variables
A similar discussion is going on in Lazarus-develop, but this obviously is a compiler question. In C, there is the volatile keyword that ensures that after the code sequence enters the next C instruction after that which modified this variable, another thread sees the correct state of the variable. This is ensured by not caching the value in registers and on SMP systems additionally by low level stuff like memory barriers. Of course this does not protect concurrent read-modify-write accesses (same need to be protected by low level atomic instructions or MUTEX and friend). For variables not defined as volatile, (e.g.) pthread_mutex (and similar stuff on Windows) can be used to protect them. AFAIK, in Pascal all Global (Static) variables are considered to be handled as volatile, so no problem here (other than handling all of them them as volatiles might decrease performance slightly). But what about variables on the heap ? If class instance variables or - say - a liked list done with records created by "new" are accessed by multiple threads, how can said consistency be enforced ? Even if you use a critical section to do the protection, this does not help if the compiler decides to cache the variable in a register while entering or exiting the critical section. But even without dedicated protection, a volatile variable should be able to be be monitored from another thread. Can this be enforced in Pascal for help variables ? -Michael ___ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/mailman/listinfo/fpc-devel