digitalmars.D - volatile variables in D....
- Forest Ray (7/7) Apr 11 2007 What is the correct way to impliment a volatile variable ala C++ in D? ...
- David B. Held (26/32) Apr 11 2007 In fact, C++'s 'volatile' isn't guaranteed to do the right thing because...
- Forest Ray (3/28) Apr 12 2007 I am NOT asking for an atomic increment or access. What volatile guaran...
- Frank Benoit (keinfarbton) (2/2) Apr 12 2007 is it this you are looking for?
- Sean Kelly (11/13) Apr 12 2007 Technically no, but it should achieve the same thing. Given the
- Sean Kelly (9/25) Apr 12 2007 Oh, if you're so inclined, tango.core.Atomic in Tango should achieve the...
- Derek Parnell (15/17) Apr 12 2007 I'm sure now that the people trying to help the OP just are not
- Sean Kelly (5/19) Apr 12 2007 Yup. But given that no such feature exists in D right now, I was
- Sean Kelly (14/17) Apr 12 2007 For what it's worth, I don't think the C++ implementation of 'volatile'
- Davidl (3/16) Apr 12 2007 worth consideration!!
- Sean Kelly (6/9) Apr 12 2007 If you mean for the actual purpose of volatile in C++ (reading from IO
- Forest Ray (9/28) Apr 12 2007 Here is a more concrete example which should not get confused with atomi...
- Rory McGuire (16/16) Mar 19 2008 Wouldn't it be better to have an object which represents the actual devi...
What is the correct way to impliment a volatile variable ala C++ in D? For example an ISR which triggers every 1 ms does some work and increments a heartbeat variable. How does one define this? In C++ you would define it as "volatile unsigned int timer_1ms;" and all referance would aways read from/write to the memory location. In D do you have to use the volatile key word on every statement that access this variable? That would be rather klunky and error prone, not to mention gdc does not always do the correct thing. Now that D is getting proper 'const', maybe it should get proper 'volatile'. Mark
Apr 11 2007
Forest Ray wrote:What is the correct way to impliment a volatile variable ala C++ in D? For example an ISR which triggers every 1 ms does some work and increments a heartbeat variable. How does one define this? In C++ you would define it as "volatile unsigned int timer_1ms;" and all referance would aways read from/write to the memory location. In D do you have to use the volatile key word on every statement that access this variable? That would be rather klunky and error prone, not to mention gdc does not always do the correct thing. Now that D is getting proper 'const', maybe it should get proper 'volatile'.In fact, C++'s 'volatile' isn't guaranteed to do the right thing because C++ doesn't define a memory model which would be necessary to define what The Right Thing even is. Java made the same mistake at first, but later fixed the standard to properly define 'volatile'. While setting up memory barriers etc. to make volatile work properly might seem like a quick and easy solution, I think we need to think carefully about what multithreading primitives really give the most benefit. In this case, you basically want volatile to give you a cheap form of atomic increment. However, I would suggest that if you really need the accuracy of atomic increment, then you should consider a primitive like CAS instead: int count = 0; asm { MOV EBX, &count; MOV EAX, [EBX]; Retry: MOV EDX, EAX; INC EDX; CMPXCHG [EBX], EDX; JNZ Retry; } My x86 asm is pretty rusty, so this might be completely bogus code, but it should give you an idea of what I mean. Dave
Apr 11 2007
I am NOT asking for an atomic increment or access. What volatile guarantees is that the variable is always read from memory or written to memory for each access. The ISR routine increments the timer variable every 1 ms. The user space application (which will be getting interrupted every 1 ms) checks the variable to schedule events...this is not relying on atomic access. == Quote from David B. Held (dheld codelogicconsulting.com)'s articleIn fact, C++'s 'volatile' isn't guaranteed to do the right thing because C++ doesn't define a memory model which would be necessary to define what The Right Thing even is. Java made the same mistake at first, but later fixed the standard to properly define 'volatile'. While setting up memory barriers etc. to make volatile work properly might seem like a quick and easy solution, I think we need to think carefully about what multithreading primitives really give the most benefit. In this case, you basically want volatile to give you a cheap form of atomic increment. However, I would suggest that if you really need the accuracy of atomic increment, then you should consider a primitive like CAS instead: int count = 0; asm { MOV EBX, &count; MOV EAX, [EBX]; Retry: MOV EDX, EAX; INC EDX; CMPXCHG [EBX], EDX; JNZ Retry; } My x86 asm is pretty rusty, so this might be completely bogus code, but it should give you an idea of what I mean. Dave
Apr 12 2007
is it this you are looking for? http://www.digitalmars.com/d/statement.html#VolatileStatement
Apr 12 2007
Frank Benoit (keinfarbton) wrote:is it this you are looking for? http://www.digitalmars.com/d/statement.html#VolatileStatementTechnically no, but it should achieve the same thing. Given the functionality of the volatile statement in D: int* io = 0x1234; int x; volatile x = *io; implicitly guarantees that the load from *io will always occur from memory rather than from a cached register value. I know it's not as convenient as labeling a variable as volatile as per C/C++, but it should do. Sean
Apr 12 2007
Sean Kelly wrote:Frank Benoit (keinfarbton) wrote:Oh, if you're so inclined, tango.core.Atomic in Tango should achieve the same result, even though it's intended for multithreading as well. Use "atomicLoad!(msync.raw)(val)" and it will always load 'val' from memory. This module currently only supports x86 however. If you (or anyone else) needs support for other platforms, please let me know. And if you're really inclined, perhaps supply a .c or .S file with the stuff I'd need to call for that platform. Seanis it this you are looking for? http://www.digitalmars.com/d/statement.html#VolatileStatementTechnically no, but it should achieve the same thing. Given the functionality of the volatile statement in D: int* io = 0x1234; int x; volatile x = *io; implicitly guarantees that the load from *io will always occur from memory rather than from a cached register value. I know it's not as convenient as labeling a variable as volatile as per C/C++, but it should do.
Apr 12 2007
On Thu, 12 Apr 2007 08:18:48 -0700, Sean Kelly wrote:Oh, if you're so inclined, tango.core.Atomic in Tango should achieve the same result ...I'm sure now that the people trying to help the OP just are not understanding the problem. The problem is that in D, one must code the 'volatile' keyword on *EVERY* access of the variable if one wants to force the compiler to do real memory fetch and store operations, otherwise the compiler /might/ cache a fetch or store value when it optimizes the machine code. The OP was asking for a shorthand way to do this ... namely apply the 'volatile' keyword to a variable so that the compiler will behave as if the coder had used 'volatile' on each and every access to that variable. -- Derek Parnell Melbourne, Australia "Justice for David Hicks!" skype: derek.j.parnell
Apr 12 2007
Derek Parnell wrote:On Thu, 12 Apr 2007 08:18:48 -0700, Sean Kelly wrote:Perhaps in other cases, that's true.Oh, if you're so inclined, tango.core.Atomic in Tango should achieve the same result ...I'm sure now that the people trying to help the OP just are not understanding the problem.The problem is that in D, one must code the 'volatile' keyword on *EVERY* access of the variable if one wants to force the compiler to do real memory fetch and store operations, otherwise the compiler /might/ cache a fetch or store value when it optimizes the machine code. The OP was asking for a shorthand way to do this ... namely apply the 'volatile' keyword to a variable so that the compiler will behave as if the coder had used 'volatile' on each and every access to that variable.Yup. But given that no such feature exists in D right now, I was suggesting alternatives. Sean
Apr 12 2007
Sean Kelly wrote:Yup. But given that no such feature exists in D right now, I was suggesting alternatives.For what it's worth, I don't think the C++ implementation of 'volatile' is really ideal. Qualifying something as 'volatile' has a viral effect on code, and overloading and such can become fairly complicated. Also, the requirements for memory mapped io are a subset of the requirements for multithreaded programming, so by properly addressing multithreading I think memory mapped io will be supported "for free." The C++ 0x discussions seem pretty promising here, so perhaps something similar will be done in D once the dust settles a bit in the C++ arena. In short, I agree that something more than the 'volatile' statement we have in D now would be useful, and suspect we'll get something before too terribly long. In the interim, I would probably implement a value "proxy" struct to simplify things. Sean
Apr 12 2007
worth consideration!! And the volatile statement we have now is completely not usable compare to C++'s volatile prefix varsWhat is the correct way to impliment a volatile variable ala C++ in D? For example an ISR which triggers every 1 ms does some work and increments a heartbeat variable. How does one define this? In C++ you would define it as "volatile unsigned int timer_1ms;" and all referance would aways read from/write to the memory location. In D do you have to use the volatile key word on every statement that access this variable? That would be rather klunky and error prone, not to mention gdc does not always do the correct thing. Now that D is getting proper 'const', maybe it should get proper 'volatile'. Mark
Apr 12 2007
Davidl wrote:worth consideration!! And the volatile statement we have now is completely not usable compare to C++'s volatile prefix varsIf you mean for the actual purpose of volatile in C++ (reading from IO memory and such) then that's debatable. But C++ volatile is currently useless for multithreading, though Microsoft has extended the guarantees so it will work in some circumstances. Sean
Apr 12 2007
Here is a more concrete example which should not get confused with atomic access. I am an embedded/OS programmer. I have to use memory mapped devices all of the time. In C/C++ I must declare references to these address as volatile pointers otherwise the compiler may NOT actually access that address. An optomizing compiler will cache the value from the first reference and not read/write the other accesses. For example, I have a serial port device mapped into my address space: volatile unsigned char* serial_base = 0x00000020; then I need to read 3 character from the serial port: x = *serial_base; y = *serial_base; z = *serial_base; If serial_base is NOT volatile and I have a modern optimizing compiler x, y, and z will all have the same value as serial_base was only accessed once. The first memory load from serial_base is stored in x then copied to y and z. volatile tells the compiler not to optimize the serial_base variable and always read from/write to it. If D is to be considered in the embedded enviroment this has to be addressed. D's volatile statement is error prone, I would have to declare each STATEMENT that used serial_base as volatile, that is horrible. Davidl Wrote:worth consideration!! And the volatile statement we have now is completely not usable compare to C++'s volatile prefix varsWhat is the correct way to impliment a volatile variable ala C++ in D? For example an ISR which triggers every 1 ms does some work and increments a heartbeat variable. How does one define this? In C++ you would define it as "volatile unsigned int timer_1ms;" and all referance would aways read from/write to the memory location. In D do you have to use the volatile key word on every statement that access this variable? That would be rather klunky and error prone, not to mention gdc does not always do the correct thing. Now that D is getting proper 'const', maybe it should get proper 'volatile'. Mark
Apr 12 2007
Wouldn't it be better to have an object which represents the actual device/port that you are reading/writing? This would also make the code's actions more obvious. class Port { // (Could also be a struct) size_t port; // this is a pointer to the memory mapped io port this(size_t port) { this.port = port; } byte read() { volatile return *port; } void write(byte value) { volatile *port = value; } } Anyone still reading this thread?
Mar 19 2008