Jump to content
OMRON Forums

Mutexs between scripts and C programs


windell747

Recommended Posts

Aloha,

 

I have a C program that writes to a set of P-variables and a motion program reads from those same variables. Since the Power PMAC I have is a 32-bit machine, it will take 2 processor cycles to write to a 64-bit memory location. Therefore, with multiple threads running, it is possible to read only half of an updated 64-bit floating point number. You can imagine that this can give crazy behavior if this variable is a commanded position. To be responsible, I am using mutexs to ensure that I cannot read a variable while I'm writing to it.

 

1) Does DT have any existing mutex schemes for writing and reading shared global memory P-variables?

 

I can do my own per Dekker's algorithm for example, but depending on how the C optimization occurs, the mutex may not work as intended. I wanted to make sure I check what comes out of the box before doing my own mutex.

 

Thanks,

windell

Link to comment
Share on other sites

  • Replies 9
  • Created
  • Last Reply

Top Posters In This Topic

Hi Charles,

 

That will be a bit difficult since on the C side, I'm writing to a set of P-variables and on the script side, I am reading from the same set. So I'm not sharing any critical areas between C and script, but I am read and writing to P-variables between the two.

 

1) When writing to P-variables is this an atomic operation such that on the script side I won't be able to read a half modified 64-bit double?

2) How about when reading a P-variable on the script side is this an atomic operation too?

3) I'm fine with C always taking priority. However, if I set Sys.Lock[1] == 1 when I'm doing a read of the P-variables on the script side, I want to make sure that the C program will wait until the lock is released rather than overriding the lock and doing a write anyway. Can you send me an example of what you're trying? I want to compare apples to apples here.

4) How would you propose to implement a mutex for our application without using the Sys.Lock element? Please refer to below.

 

Here is an example of what I'm doing so that were on the same page. Please note that this is greatly simplified from what were doing on our C side, I haven't checked it lately, but I'm guessing we have at least 10k lines of code. The position commands on the C side come from a host computer that is communicating with the Power PMAC.

 

C side:
Process 0:

main(){
...
while(1){
pshm->P[400] = a
pshm->P[401] = b
pshm->P[402] = c
pshm->P[403]= d

usleep(1000);
}
...
}

Process 1:
Motion program side:

while(1){
var1 = P400;
var2 = P401;
var3 = P402;
var4 = P403;

pvt(10);
X(var1):(DEC_MOTION_VEL)
X(var2):(DEC_MOTION_VEL)
X(var3):(DEC_MOTION_VEL)
X(var4):(DEC_MOTION_VEL)
X(var5):(DEC_MOTION_VEL)
}

 

 

Sys.Lock is not really designed to be used between a C program and Script. I suggest you put all of your critical areas that need to be shared either in Script or in C, not both.

 

Basically C always takes the Lock priority, so it will ignore what your Script program is doing. I just tested it.

Link to comment
Share on other sites

1. No.

2. No.

3. C will always overwrite Sys.Lock and take control. Note that no process can write Sys.Lock=1; the act of reading Sys.Lock when it is available will cause PMAC to set it =1 internally.

 

I suggest you do not use Sys.Lock, but instead use a "poor man's semaphore" with some global flags that you can use to lock processes. Use a Sys.Cdata on the script side and map it with a char* pointer on the C side. Poll the flag on either end. On the C end you will have to nanosleep() while polling.

 

In a .pmh file you can make something like:

 

#define PosDataSemaphore Sys.Cdata[1]

 

In C this would be

 

#define PosDataSemaphore Cdata[1]

 

You need this in your program for the above #define to work:

 

char* Cdata = (char*)pushm;

 

Then in Script you can do

 

while(PosDataSemaphore==1){} // A1

if(PosDataSemaphore == 0)

{

PosDataSemaphore = 1;

// read values

PosDataSemaphore = 0;

}

In C:

 

struct timespec Timer = {0, 10000000}; // 10 msec

while(PosDataSemaphore){nanosleep(&Timer,NULL)} // A2

if(!PosDataSemaphore)

{

PosDataSemaphore = 1;

// write values

PosDataSemaphore = 0;

}

 

Of course this is not as robust as a REAL mutex or semaphore, but it may work for you.

Link to comment
Share on other sites

Thank you Charles.

 

As I was referring to in the OP, I'm assuming that by you suggesting the "poor man's semaphore" method that you're certain that the compile optimizer will not detect that the semaphore isn't updated from within the while loop and use Loop-invariant Code Motion resulting in a potential infinite loop. Is that correct? I just wanted to make sure because this is one caveat of someone doing their own mutex.

 

This was my primary motivation to post here and ask before doing my own semaphore.

 

Look at the notes under Dekker's Algorithm here and the :

https://en.m.wikipedia.org/wiki/Dekker%27s_algorithm

 

thanks,

windell

Link to comment
Share on other sites

Thanks Charles.

 

Is it possible to do the same thing using global p-variables? I know its inefficient use of memory, but I like being able to view these variables in the scope.

 

thanks,

windell

 

Windell,

 

On the Script side, no such optimization is performed because it is all interpreted in the first place and evaluated at run time.

 

In C, I am not completely sure if the compiler will try to optimize, but you can force it not to by making your semaphore variable a volatile:

 

volatile char* Cdata = (char*)pushm;

Link to comment
Share on other sites

You can of course use P-Variables, but be aware you cannot do integer logic checks unless you cast to integer in C:

 

For example:

 

while((unsigned int)pshm->P[MyMutex] == 1){}

 

Please note that Sys.Cdata in Script maps the same memory as

 

volatile char* Cdata = (char*)pushm;

 

Cdata

 

maps in C and can be observed globally.

Link to comment
Share on other sites

Mahalo Charles I'll see if this works. thank you for the reminder about the P-variables.

 

You can of course use P-Variables, but be aware you cannot do integer logic checks unless you cast to integer in C:

 

For example:

 

while((unsigned int)pshm->P[MyMutex] == 1){}

 

Please note that Sys.Cdata in Script maps the same memory as

 

volatile char* Cdata = (char*)pushm;

 

Cdata

 

maps in C and can be observed globally.

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.

×
×
  • Create New...