question on semantics
I'm not sure who I should address this to...I hope this is correct. If I share memory between two processes, and protect access to the memory using standard locking (fcntl(), for instance), do I need to specify that the memory is volatile? Or is the fact that I'm using fcntl() enough to force the compiler to not optimise away memory accesses? As an example, consider the following code, with / replaced with the appropriate fcntl() code: int *b; int test() { b=; while(1) { if (*b) { break; } } return *b; } Without the locks, the compiler is free to only load *b once (and in fact gcc does so). Is the addition of the locks sufficient to force *b to be re-read each time, or do I need to declare it as volatile int *b; Thanks, Chris
Re: question on semantics
Mike Stump wrote: On May 4, 2005, at 10:59 AM, Chris Friesen wrote: If I share memory between two processes, and protect access to the memory using standard locking (fcntl(), for instance), do I need to specify that the memory is volatile? It is safer to. People might compile your whole app at once for better optimization, and the compiler might be just smart enough to optimize it away. One problem with using volatile is that it can destroy performance. I only need to really read it in from memory the first time after I take a lock, and flush it out to memory at the time I give up the lock. If I specify it as volatile, I force the compiler to read/write memory on *every* access, even when it's not necessary. Also, what about threads and pthread locking? Do I need to use volatile there? If not, then what about using pthread locking between processes? So far I've gotten answers all over the map from people who all claim to know what's going on. It's a pain. Chris
Re: question on semantics
Diego Novillo wrote: On Wed, May 04, 2005 at 01:47:20PM -0600, Chris Friesen wrote: Also, what about threads and pthread locking? Do I need to use volatile there? If not, then what about using pthread locking between processes? Things will only break for you when GCC pulls in function bodies at link time. At that point, yes, you will need to declare your pointed-to area as volatile. Dave Butenhof (author of "Programming with POSIX Threads") seems to disagree with that position: "In general, use of "volatile" for variables that are simply shared between threads is unnecessary and wasteful. Proper synchronization is necessary and sufficient; there is no substitute short of coding carefully with specific knowledge of the memory architecture of a specific platform." In multiple messages to comp.programming.threads he has stated that volatile is not necessary between threads if you use the posix locking functions, and in fact that one of the main purposes of the posix locks is to ensure correct memory visibility between threads. Chris
Re: question on semantics
Diego Novillo wrote: On Wed, May 04, 2005 at 02:47:14PM -0600, Chris Friesen wrote: In multiple messages to comp.programming.threads he has stated that volatile is not necessary between threads if you use the posix locking functions, and in fact that one of the main purposes of the posix locks is to ensure correct memory visibility between threads. That still assumes that the compiler isn't pulling the body of pthread_mutex_lock, deciding that it doesn't really clobber any globals and proceeding to consider it a read-only function. At this point in time, and for the foreseeable future this will remain to be true. Right. I suspect that he would consider such behaviour as rendering that version of GCC as non POSIX compliant. The real future-proof fix is to mark them as such and have the compiler recognize that attribute. This means adding concurrency semantics to the compiler. Something that we are in the process of doing. Cool. Thanks for all the explanations. I'm going to be giving an internal talk on programming for concurrency, and I've learned way more doing the research for the talk than most of the attendees will currently be able to appreciate. Chris
Re: question on semantics
Mike Stump wrote: On May 4, 2005, at 12:47 PM, Chris Friesen wrote: One problem with using volatile is that it can destroy performance. Gosh, I was going to elaborate and give the more complete answer, but decided against it, I was wrong. Heh...sorry. I've been trying to figure out who's responsible for what guarantees. It's a bit confusing. I was going to say, you can insert memory barriers inside the, near the lock/unlock (or even, inside the lock/unlock code. If your lock/ unlock author has put them in there for you, then, trivially, you don't even need them. Since this list doesn't cover pthreads, we are the wrong people to answer that question. Okay, that makes sense. Thanks for your comments. Chris