>>>>> "Robert" == Robert Dewar <[EMAIL PROTECTED]> writes:
Robert> Paul Koning wrote: >>>>>>> "Robert" == Robert Dewar <[EMAIL PROTECTED]> writes: >> Robert> Ken Raeburn wrote: >> >> That's what I thought. So, unless the compiler (or language >> spec) >> is going to become thread-aware, any data to be shared >> across >> threads needs to be declared volatile, even if some >> other >> mechanism (like a mutex) is in use to do some >> synchronization. >> Which means performance would be poor for any >> such data. >> Robert> The use of shared variables without synchronization is rare Robert> in any case in most code. >> You mean "without explicit synchronization" via mutexes or the >> like? >> >> It seems that the classic circular buffer communication mechanisms >> have been forgotten by many, but they still work quite well and >> require no mutexes or the like. All that is required is >> sufficiently ordered memory accesses. Robert> Sure such alogorithms are interesting on mono processors, ... They work fine on multi-processors too, of course. That's where they first showed up, in CDC 6000 series machines for communication between CPU and PPU. Robert> Nevertheless such usage is relatively rare, and volatile is Robert> good enough, I see no basis for any changes to the compiler. Maybe they are rare because people no longer learn them, even though they are the most efficient answer in a lot of cases where they end up using heavier solutions instead. I remember being amazed that RTLinux (some years ago) was using interrupt enable/disable to synchronize control variables in an RTLinux to Linux communication mechanism, when circular buffers would provide the same service without any need of interrupt lockout or other explicit synchronization at all. Also: circular buffers are a VERY common communication mechanism in DMA devices. For example, many Ethernet NICs use them. They may not be exactly CDC 6000 "CIO" ring buffers, but the basic idea is similar and the memory access properties needed are analogous. >> I'm using circular buffers to communicate between threads. I drop >> data into the buffer and move the "in" pointer; the consumer >> compares the pointers, reads data from the buffer, and advances >> the "out" pointer. The current code has the pointers declared as >> volatile, buf the buffer data area is not (and I wouldn't want it >> to be -- that seems to be a performance issue). Robert> Of course the buffer data area must be declared as volatile, Robert> otherwise the compiler is free to make and hold private Robert> copies of elements in separate threads. It probably won't in Robert> practice, but to rely on this is non-portable. Ok. I think that may be the issue that people are talking about with the comments about volatile being a costly solution. I'm using memcpy() to load/unload buffer data. Is memcpy defined for volatile variables? If yes, and I declare the buffer as a char array (logical, since the threads can pass arbitrary quantities of bytes), would the generated code be required by the semantics of "volatile" to do individual loads and stores for every byte? That is the problem. What's needed is (a) no code movement across the pointer operations, (b) the data copy can be fully optimized, as is typically done with memcpy, (c) no old data hangs around in registers. I guess GCC lets us do this with asm ("":::"memory") but of course that isn't portable either... paul