Jump to content
OMRON Forums

P Variable Atomic read in C?


KEJR

Recommended Posts

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

  • Replies 3
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

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

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

Guest
This topic is now closed to further replies.

×
×
  • Create New...