They seem most related to I/O access, like gbe.h.bob wrote: Other questions?
I suggest to (at least slightly) understand what you are doing before doing it...also after it would suffice.
Moderator: Ras
They seem most related to I/O access, like gbe.h.bob wrote: Other questions?
No, I am not surprised at all. Nothing wrong with Crafty. The problem is only that you, as always, butt into threads without knowing what it is about and start blabbering "all wrong". So then I think:bob wrote:Fact is, MOST shared data in Crafty is not volatile. Big surprise? Volatile has a specific purpose.syzygy wrote:Ok, I will not check whether they all fall under one of the exceptions listed in https://www.kernel.org/doc/Documentatio ... armful.txt (prima facie most seem to do). And your "offer" related so spinlocks (and spinlock_types_up.h smells like uniprocessor), but never mind.
Fact is, most shared data in the kernel is not volatile.
Your use of volatile in Crafty falls under:syzygy wrote:Oh boy, there we go again...
In C11 you can do this in a standard-compliant way using atomics.syzygy wrote:If you don't want to be restricted by a thread library, but (in addition) want to rely on how the compiler will map your code to the machine, then volatile is useful. Your program will be full of undefined behavior, but if that is a conscious choice that is not necessarily bad. It will just not be "standard C/C++ plus pthreads" or "standard C11/C++11".
Senpai properly uses C++11 locking primitives, so does not need volatile (nor atomic) for its shared variables. (I'm ignoring the tt table.)syzygy wrote:For multithreaded programs using volatile is not necessary if you are properly using the synchronisation primitives of a thread library, e.g. pthreads or C++11 threads.
I referred to those you fabricated by copying and pasting from the pthreads source.bob wrote:Your ignorance is showing. My lock was NOT "amateurishly written by me.syzygy wrote:Those locks were not amateuristically written by Mr Hyatt, but include the necessary compiler and hardware memory barriers.
They include a compiler barrier... Otherwise memory accesses would be moved across lock operations by the compiler.Since X86 is always in-order store architecture, barriers are not needed.
Can you read this? It is only the fourth or maybe fifth time I repeat, it's from the start of this thread:bob wrote:Just because someone doesn't like the volatile approach does NOT mean it does not work correctly AND efficiently.
I have nothing against an educated use of volatile for multithreaded programming (when C11 is not available and the consequences are well-understood).syzygy wrote:If you don't want to be restricted by a thread library, but (in addition) want to rely on how the compiler will map your code to the machine, then volatile is useful. Your program will be full of undefined behavior, but if that is a conscious choice that is not necessarily bad. It will just not be "standard C/C++ plus pthreads" or "standard C11/C++11".
syzygy wrote:For multithreaded programs using volatile is not necessary if you are properly using the synchronisation primitives of a thread library, e.g. pthreads or C++11 threads.
Most of the kernel is related to doing I/O. I only included a few of the 1000+ that I found...mcostalba wrote:They seem most related to I/O access, like gbe.h.bob wrote: Other questions?
I suggest to (at least slightly) understand what you are doing before doing it...also after it would suffice.
as "it is always wrong to use volatile in a multithreaded program".syzygy wrote:For multithreaded programs using volatile is not necessary if you are properly using the synchronisation primitives of a thread library, e.g. pthreads or C++11 threads.
Let me get this straight. You REALLY want to claim that the ONLY way one can use the pthread library is to use it in its pre-compiled form? Can you cite a source? (hint: such a source does NOT exist, because that is NOT a requirement for using the pthreads library. In fact, if it were a requirement, it would break way too much because library behavior is defined, specifically, to behave IDENTICALLY with behavior produced when the library source code AND the application are compiled together. That is the very DEFINITION of a library, it eliminates the NEED to compile the library source each time it is used. It does NOT preclude doing so.syzygy wrote:No, I am not surprised at all. Nothing wrong with Crafty. The problem is only that you, as always, butt into threads without knowing what it is about and start blabbering "all wrong". So then I think:bob wrote:Fact is, MOST shared data in Crafty is not volatile. Big surprise? Volatile has a specific purpose.syzygy wrote:Ok, I will not check whether they all fall under one of the exceptions listed in https://www.kernel.org/doc/Documentatio ... armful.txt (prima facie most seem to do). And your "offer" related so spinlocks (and spinlock_types_up.h smells like uniprocessor), but never mind.
Fact is, most shared data in the kernel is not volatile.Your use of volatile in Crafty falls under:syzygy wrote:Oh boy, there we go again...In C11 you can do this in a standard-compliant way using atomics.syzygy wrote:If you don't want to be restricted by a thread library, but (in addition) want to rely on how the compiler will map your code to the machine, then volatile is useful. Your program will be full of undefined behavior, but if that is a conscious choice that is not necessarily bad. It will just not be "standard C/C++ plus pthreads" or "standard C11/C++11".
Senpai's use falls under:Senpai properly uses C++11 locking primitives, so does not need volatile (nor atomic) for its shared variables. (I'm ignoring the tt table.)syzygy wrote:For multithreaded programs using volatile is not necessary if you are properly using the synchronisation primitives of a thread library, e.g. pthreads or C++11 threads.
I referred to those you fabricated by copying and pasting from the pthreads source.bob wrote:Your ignorance is showing. My lock was NOT "amateurishly written by me.syzygy wrote:Those locks were not amateuristically written by Mr Hyatt, but include the necessary compiler and hardware memory barriers.
For "some places" volatile is necessary, because max performance is an absolute requirement. Using locks to avoid volatile takes a big performance hit. And I am not talking about pthreads locks which take a MUCH bigger performance hit over a standard xchg() type x86 lock. But that xchg() lock is a big hit itself.They include a compiler barrier... Otherwise memory accesses would be moved across lock operations by the compiler.Since X86 is always in-order store architecture, barriers are not needed.
Can you read this? It is only the fourth or maybe fifth time I repeat, it's from the start of this thread:bob wrote:Just because someone doesn't like the volatile approach does NOT mean it does not work correctly AND efficiently.I have nothing against an educated use of volatile for multithreaded programming (when C11 is not available and the consequences are well-understood).syzygy wrote:If you don't want to be restricted by a thread library, but (in addition) want to rely on how the compiler will map your code to the machine, then volatile is useful. Your program will be full of undefined behavior, but if that is a conscious choice that is not necessarily bad. It will just not be "standard C/C++ plus pthreads" or "standard C11/C++11".
But you blabbered "all wrong" against something which is simply "all right":syzygy wrote:For multithreaded programs using volatile is not necessary if you are properly using the synchronisation primitives of a thread library, e.g. pthreads or C++11 threads.
Did you not cite a blog post where that was THE TOPIC?syzygy wrote:It seems you amazingly completely misread my simple:as "it is always wrong to use volatile in a multithreaded program".syzygy wrote:For multithreaded programs using volatile is not necessary if you are properly using the synchronisation primitives of a thread library, e.g. pthreads or C++11 threads.
English comprehension...
Duh? This is precisely your example from the very beginning that was supposed to show why volatile was needed to avoid the reordering.bob wrote:You DO realize this program runs on other than X86? The alpha compiler from DEC had a software lock function that did what mine does above, but in C, using the interlocked exchange() mechanism their compiler used. Remove the volatile and the alpha would hang there.syzygy wrote:You can safely remove the "volatile" from "volatile int *lock" in this code:bob wrote:The lock used in Crafty came from older kernel sources. Still works flawlessly.The __volatile__ in "asm __volatile__" is important, though.Code: Select all
static void __inline__ LockX86(volatile int *lock) { int dummy; asm __volatile__( "1: movl $1, %0" "\n\t" " xchgl (%1), %0" "\n\t" " testl %0, %0" "\n\t" " jz 3f" "\n\t" "2: pause" "\n\t" " movl (%1), %0" "\n\t" " testl %0, %0" "\n\t" " jnz 2b" "\n\t" " jmp 1b" "\n\t" "3:" "\n\t" :"=&q"(dummy) :"q"(lock) :"cc", "memory"); } static void __inline__ UnlockX86(volatile int *lock) { int dummy; asm __volatile__( "movl $0, (%1)" :"=&q"(dummy) :"q"(lock)); }
Can you explain why the shared variable gets reloaded:
Wrong! Properly written locks include memory barriers! Get it now?!bob wrote:The above will fail because variable was not changed in this code between the first reference and the second. Another thread COULD have acquired the lock, modified variable, and then released the lock. When you access variable a second time, the compiler is free to use the original value (now stored in i) rather than re-loading it again, even though the other thread might have modified it inside the locks.
Yeah! That IS what I was talking about. All... the... <explicit>... time... Wow, we.. have... gotten.. somewhere... finally...bob wrote:I didn't feel up to looking at what you are doing. But first things first. The volatile declaration on the inline asm is important. The compiler can't reorder across that, ever, nor can it change the location of the inline assembler by moving it up or down, before or after existing code.
If that is what you are talking about, that's the reason. Done quite intentionally, obviously.
You raised the issue about volatile int lockxx; in Crafty and the volatile not being needed.syzygy wrote:Duh? This is precisely your example from the very beginning that was supposed to show why volatile was needed to avoid the reordering.bob wrote:You DO realize this program runs on other than X86? The alpha compiler from DEC had a software lock function that did what mine does above, but in C, using the interlocked exchange() mechanism their compiler used. Remove the volatile and the alpha would hang there.syzygy wrote:You can safely remove the "volatile" from "volatile int *lock" in this code:bob wrote:The lock used in Crafty came from older kernel sources. Still works flawlessly.The __volatile__ in "asm __volatile__" is important, though.Code: Select all
static void __inline__ LockX86(volatile int *lock) { int dummy; asm __volatile__( "1: movl $1, %0" "\n\t" " xchgl (%1), %0" "\n\t" " testl %0, %0" "\n\t" " jz 3f" "\n\t" "2: pause" "\n\t" " movl (%1), %0" "\n\t" " testl %0, %0" "\n\t" " jnz 2b" "\n\t" " jmp 1b" "\n\t" "3:" "\n\t" :"=&q"(dummy) :"q"(lock) :"cc", "memory"); } static void __inline__ UnlockX86(volatile int *lock) { int dummy; asm __volatile__( "movl $0, (%1)" :"=&q"(dummy) :"q"(lock)); }
Can you explain why the shared variable gets reloaded:
And the required volatile lock type declaration (lock_t includes that on the alpha C compiler I last used). Otherwise the compiler will produce a lock that you never get through once you reach it and the lock is already set.
On alpha one would need to include an appropriate memory fence in the LOCK() macro, obviously.
OK, volatile is required there. Didn't I say that already?
YOUR point was that the compiler could reorder around the LOCK(). But this lock includes a compiler barrier, as it should, so there won't be any reordering.
No need to make "variable" volatile.Wrong! Properly written locks include memory barriers! Get it now?!bob wrote:The above will fail because variable was not changed in this code between the first reference and the second. Another thread COULD have acquired the lock, modified variable, and then released the lock. When you access variable a second time, the compiler is free to use the original value (now stored in i) rather than re-loading it again, even though the other thread might have modified it inside the locks.
Yeah! That IS what I was talking about. All... the... <explicit>... time... Wow, we.. have... gotten.. somewhere... finally...bob wrote:I didn't feel up to looking at what you are doing. But first things first. The volatile declaration on the inline asm is important. The compiler can't reorder across that, ever, nor can it change the location of the inline assembler by moving it up or down, before or after existing code.
If that is what you are talking about, that's the reason. Done quite intentionally, obviously.
Well, the above quote of mine is what made you start whining. Not something else.bob wrote:Did you not cite a blog post where that was THE TOPIC?syzygy wrote:It seems you amazingly completely misread my simple:as "it is always wrong to use volatile in a multithreaded program".syzygy wrote:For multithreaded programs using volatile is not necessary if you are properly using the synchronisation primitives of a thread library, e.g. pthreads or C++11 threads.
English comprehension...
Or do you cite references but really don't mean that they be looked at?
I am saying that POSIX does not guarantee that if you randomly copy and paste stuff into your program you end up with something that works.bob wrote:Let me get this straight. You REALLY want to claim that the ONLY way one can use the pthread library is to use it in its pre-compiled form?syzygy wrote:I referred to those you fabricated by copying and pasting from the pthreads source.bob wrote:Your ignorance is showing. My lock was NOT "amateurishly written by me.syzygy wrote:Those locks were not amateuristically written by Mr Hyatt, but include the necessary compiler and hardware memory barriers.
OK, why don't you file a bug report to the pthreads maintainers so that they can have as big a laugh at you as we are having.Can you cite a source? (hint: such a source does NOT exist, because that is NOT a requirement for using the pthreads library. In fact, if it were a requirement, it would break way too much because library behavior is defined, specifically, to behave IDENTICALLY with behavior produced when the library source code AND the application are compiled together. That is the very DEFINITION of a library, it eliminates the NEED to compile the library source each time it is used. It does NOT preclude doing so.
If your POSIX system doesn't do this, it is buggy. You believe you found a bug, so report it. Woohoo.The following functions synchronize memory with respect to other threads:
...
pthread_mutex_lock()
...