KEJR Posted September 7, 2011 Share Posted September 7, 2011 Hello, I need to be able to read P variables from a "Background C application" with guaranteed Atomicity in the event that a higher priority thread (like a motion program) preempts me and writes to the same P variable halfway through the read. The C application is listed as a 32 bit Elf executable so it will read the 64 bit words as two 32 bit words and herein lies the problem. Right now I'm using the shared memory pointer (pshm->) to access the P variables from my C application. Any thoughts? KEJR Link to comment Share on other sites More sharing options...
curtwilson Posted September 8, 2011 Share Posted September 8, 2011 In the Power PMAC, any access to a "double" (64-bit floating-point) variable is guaranteed to be atomic, a feature of the hardware floating-point engine in the processor. Link to comment Share on other sites More sharing options...
KEJR Posted September 8, 2011 Author Share Posted September 8, 2011 In the Power PMAC, any access to a "double" (64-bit floating-point) variable is guaranteed to be atomic, a feature of the hardware floating-point engine in the processor. I was pretty sure there *had* to be something like this, but it is good to make sure. Thank you, KEJR Link to comment Share on other sites More sharing options...
KEJR Posted September 9, 2011 Author Share Posted September 9, 2011 I definitely know what *not* to do now. I had used the memcpy() routine in my program to do a P var backup, so I wanted to test that it was not behaving differently than, say, a "for" loop copy of "double" datatypes (I suspected it might). Well, to sum it up, it seems that the memcpy() function reads in 16 bit words based off of a quick experiment. See the complete code here: Background C program, capp1.c: //-------------------------------------------------------------------------------- #include #include // Global Rt/Gp Shared memory pointers //------------------------------------------------------------- // The following is a projpp created file from the User defines //------------------------------------------------------------- #include "../../Include/pp_proj.h" int main(void) { char buf[255]; double SaveDouble; InitLibrary(); Send(1,"Capp Starting to monitor...."); while(1) { //SaveDouble=pshm->P[0]; //Capture value for later processing, keeping it synchronous. memcpy(&SaveDouble, &pshm->P[0], sizeof(double)); //Now try it with memcpy which may acess the vars differently. if(!((SaveDouble == 8888.0) || (SaveDouble == 9999.0))) { snprintf(buf, sizeof(buf), "Caught You. SaveDouble: %0.0f", SaveDouble); Send(1, buf); } } //Put your code here CloseLibrary(); return 0; } Background "c" PLC: #include #include #include void user_plcc() { struct timespec SleepTime={0}; // Initialize time structure SleepTime.tv_nsec=1000000; // 1000000 nanoseconds, which equals 1 msec pshm->P[0]=9999.0; nanosleep(&SleepTime,NULL); pshm->P[0]=8888.0; nanosleep(&SleepTime,NULL); } Note that when I use the commented out line: SaveDouble=pshm->P[0] the code produces no output at the Send() buffer. When using memcpy() it continuously barfs out the wrong values: Port 1: Caught You. SaveDouble: 9998 Port 1: Caught You. SaveDouble: 8889 Port 1: Caught You. SaveDouble: 9912 Looking at the Hex values for the numbers you can see why: 40C15C0000000000 Decimal 8888.000000 40C3878000000000 Decimal 9999.000000 40C1878000000000 Decimal 8975.000000 40C35C0000000000 Decimal 9912.000000 40C3870000000000 Decimal 9998.000000 It would appear that they are being overwritten in 16 bit chunks. To make a long story short[er] I will be writing a function to do memcpy64bit() or insert a for() loop into my code. I just wanted others to be aware of this so that proper care is taken in handling shared memory. I hope gcc continues to behave this way, although I have no reason to expect it to change. Thank you, KEJR Link to comment Share on other sites More sharing options...
Recommended Posts