--- a/runtime/PLCObject.py Tue Mar 24 17:33:46 2009 +0100
+++ b/runtime/PLCObject.py Mon Mar 30 17:04:30 2009 +0200
@@ -46,7 +46,7 @@
class PLCObject(pyro.ObjBase):
- def __init__(self, workingdir, daemon, argv, statuschange=None, evaluator=eval):
+ def __init__(self, workingdir, daemon, argv, statuschange, evaluator): pyro.ObjBase.__init__(self)
self.evaluator = evaluator
self.argv = [workingdir] + argv # force argv[0] to be "path" to exec...
@@ -57,7 +57,6 @@
self.statuschange = statuschange
- self.python_threads_vars = None
# Get the last transfered PLC if connector must be restart
@@ -220,23 +219,21 @@
PLCprint(traceback.format_exc())
- def BeginRuntimePy(self):
runtime_begin = self.python_threads_vars.get("_runtime_begin",None)
if runtime_begin is not None:
- self.evaluator(runtime_begin)
def FinishRuntimePy(self):
runtime_cleanup = self.python_threads_vars.get("_runtime_cleanup",None)
if runtime_cleanup is not None:
- self.evaluator(runtime_cleanup)
if self.hmi_frame is not None:
- self.evaluator(self.hmi_frame.Destroy)
+ self.hmi_frame.Destroy() self.python_threads_vars = None
def PythonThreadProc(self):
PLCprint("PythonThreadProc started")
+ self.evaluator(self.PrepareRuntimePy) while self.PLCStatus == "Started":
#print "_PythonIterator(", res, ")",
@@ -249,6 +246,7 @@
res = "#EXCEPTION : "+str(e)
+ self.evaluator(self.FinishRuntimePy) PLCprint("PythonThreadProc interrupted")
def StartPLC(self, debug=False):
@@ -262,7 +260,6 @@
self.PLCStatus = "Started"
- self.evaluator(self.PrepareRuntimePy)
self.PythonThread = Thread(target=self.PythonThreadProc)
self.PythonThread.start()
@@ -272,12 +269,8 @@
+ self.PLCStatus = "Stopped" - self.PLCStatus = "Stopped"
- self.PythonThread.join(timeout=1)
- if self.PythonThread.isAlive():
- PLCprint("Python thread couldn't be killed")
--- a/targets/Linux/plc_Linux_main.c Tue Mar 24 17:33:46 2009 +0100
+++ b/targets/Linux/plc_Linux_main.c Mon Mar 30 17:04:30 2009 +0200
@@ -1,13 +1,13 @@
extern int common_ticktime__;
@@ -51,7 +51,7 @@
timerValues.it_interval.tv_sec = period / 1000000000;
timerValues.it_interval.tv_nsec = period % 1000000000;
timer_settime (PLC_timer, 0, &timerValues, NULL);
@@ -77,20 +77,23 @@
/* Translate PLC's microseconds to Ttick nanoseconds */
Ttick = 1000000 * maxval(common_ticktime__,1);
memset (&sigev, 0, sizeof (struct sigevent));
sigev.sigev_value.sival_int = 0;
sigev.sigev_notify = SIGEV_THREAD;
sigev.sigev_notify_attributes = NULL;
sigev.sigev_notify_function = PLC_timer_notify;
+ pthread_mutex_init(&debug_wait_mutex); + pthread_mutex_init(&python_wait_mutex); pthread_mutex_lock(&debug_wait_mutex);
pthread_mutex_lock(&python_wait_mutex);
timer_create (CLOCK_REALTIME, &sigev, &PLC_timer);
if( __init(argc,argv) == 0 ){
PLC_SetTimer(Ttick,Ttick);
/* install signal handler for manual break */
// signal(SIGTERM, catch_signal);
signal(SIGINT, catch_signal);
@@ -118,6 +121,9 @@
pthread_mutex_unlock(&debug_wait_mutex);
+ pthread_mutex_destroy(&debug_wait_mutex); + pthread_mutex_unlock(&python_wait_mutex); + pthread_mutex_destroy(&python_wait_mutex); @@ -125,10 +131,10 @@
/* Wait signal from PLC thread */
- pthread_mutex_lock(&debug_wait_mutex);
+ if(pthread_mutex_lock(&debug_wait_mutex)) return -1;
/* Called by PLC thread when debug_publish finished
* This is supposed to unlock debugger thread in WaitDebugData*/
void InitiateDebugTransfer()
@@ -157,9 +163,9 @@
int WaitPythonCommands(void)
/* Wait signal from PLC thread */
- pthread_mutex_lock(&python_wait_mutex);
+ return pthread_mutex_lock(&python_wait_mutex);
/* Called by PLC thread on each new python command*/
void UnBlockPythonCommands(void)
--- a/targets/Win32/plc_Win32_main.c Tue Mar 24 17:33:46 2009 +0100
+++ b/targets/Win32/plc_Win32_main.c Mon Mar 30 17:04:30 2009 +0200
@@ -1,6 +1,6 @@
@@ -19,7 +19,7 @@
void PLC_GetTime(IEC_TIME *CURRENT_TIME)
(*CURRENT_TIME).tv_sec = timetmp.time;
(*CURRENT_TIME).tv_nsec = timetmp.millitm * 1000000;
@@ -36,11 +36,11 @@
/* arg 2 of SetWaitableTimer take 100 ns interval*/
liDueTime.QuadPart = next / (-100);
printf("SetTimer(%lld,%lld)\n",next, period);
if (!SetWaitableTimer(PLC_timer, &liDueTime, common_ticktime__, NULL, NULL, 0))
printf("SetWaitableTimer failed (%d)\n", GetLastError());
@@ -66,9 +66,9 @@
#define maxval(a,b) ((a>b)?a:b)
int startPLC(int argc,char **argv)
@@ -77,54 +77,54 @@
/* Translate PLC's microseconds to Ttick nanoseconds */
Ttick = 1000000 * maxval(common_ticktime__,1);
- debug_sem = CreateSemaphore(
+ debug_sem = CreateSemaphore( NULL, // default security attributes
NULL); // unnamed semaphore
printf("startPLC CreateSemaphore debug_sem error: %d\n", GetLastError());
- debug_wait_sem = CreateSemaphore(
+ debug_wait_sem = CreateSemaphore( NULL, // default security attributes
NULL); // unnamed semaphore
- if (debug_wait_sem == NULL)
+ if (debug_wait_sem == NULL) printf("startPLC CreateSemaphore debug_wait_sem error: %d\n", GetLastError());
- python_sem = CreateSemaphore(
+ python_sem = CreateSemaphore( NULL, // default security attributes
NULL); // unnamed semaphore
- if (python_sem == NULL)
+ if (python_sem == NULL) printf("startPLC CreateSemaphore python_sem error: %d\n", GetLastError());
- python_wait_sem = CreateSemaphore(
+ python_wait_sem = CreateSemaphore( NULL, // default security attributes
NULL); // unnamed semaphore
- if (python_wait_sem == NULL)
+ if (python_wait_sem == NULL) printf("startPLC CreateSemaphore python_wait_sem error: %d\n", GetLastError());
/* Create a waitable timer */
PLC_timer = CreateWaitableTimer(NULL, FALSE, "WaitableTimer");
@@ -172,10 +172,10 @@
/* from plc_debugger.c */
- WaitForSingleObject(debug_wait_sem, INFINITE);
+ if(WaitForSingleObject(debug_wait_sem, INFINITE) != WAIT_OBJECT_0) return -1;
/* Called by PLC thread when debug_publish finished
* This is supposed to unlock debugger thread in WaitDebugData*/
void InitiateDebugTransfer()
@@ -190,7 +190,7 @@
/* Prevent PLC to enter debug code */
- WaitForSingleObject(debug_sem, INFINITE);
+ WaitForSingleObject(debug_sem, INFINITE); @@ -204,9 +204,9 @@
int WaitPythonCommands(void)
/* Wait signal from PLC thread */
- WaitForSingleObject(python_wait_sem, INFINITE);
+ return WaitForSingleObject(python_wait_sem, INFINITE);
/* Called by PLC thread on each new python command*/
void UnBlockPythonCommands(void)
--- a/targets/Xenomai/__init__.py Tue Mar 24 17:33:46 2009 +0100
+++ b/targets/Xenomai/__init__.py Mon Mar 30 17:04:30 2009 +0200
@@ -5,7 +5,7 @@
""" Get xeno-config from target parameters """
- return self.PuginsRootInstance.BeremizRoot.getTargetType().getcontent()["value"].getXenoConfig()
+ return self.PluginsRootInstance.BeremizRoot.getTargetType().getcontent()["value"].getXenoConfig() def getBuilderLDFLAGS(self):
# get xeno-config from target parameters
--- a/targets/plc_python.c Tue Mar 24 17:33:46 2009 +0100
+++ b/targets/plc_python.c Mon Mar 30 17:04:30 2009 +0200
@@ -1,17 +1,17 @@
* Python Asynchronous execution code
* PLC put python commands in a fifo, respecting execution order
- * with the help of C pragmas inserted in python_eval FB code
- * Buffer content is read asynchronously, (from non real time part),
+ * with the help of C pragmas inserted in python_eval FB code + * Buffer content is read asynchronously, (from non real time part), * commands are executed and result stored for later use by PLC.
* In this implementation, fifo is a list of pointer to python_eval
* function blocks structures. Some local variables have been added in
* python_eval interface. We use those local variables as buffer and state
#include "iec_types_all.h"
@@ -30,7 +30,7 @@
#define PYTHON_LOCKED_BY_PLC 1
#define PYTHON_MUSTWAKEUP 2
#define PYTHON_FINISHED 4
/* Each python_eval FunctionBlock have it own state */
#define PYTHON_FB_REQUESTED 1
@@ -62,12 +62,12 @@
- /* Check Python thread is not being
+ /* Check Python thread is not being * modifying internal python_eval data */
- PythonState = TryLockPython() ?
+ PythonState = TryLockPython() ? - /* If python thread _is_ in, then PythonState remains PYTHON_LOCKED_BY_PYTHON
+ /* If python thread _is_ in, then PythonState remains PYTHON_LOCKED_BY_PYTHON * and python_eval will no do anything */
@@ -83,13 +83,13 @@
- * Called by the PLC, each time a python_eval
+ * Called by the PLC, each time a python_eval * FB instance is executed
void __PythonEvalFB(int poll, PYTHON_EVAL* data__)
- /* detect rising edge on TRIG to trigger evaluation */
- if(((data__->TRIG && !data__->TRIGM1) ||
+ /* detect rising edge on TRIG to trigger evaluation */ + if(((data__->TRIG && !data__->TRIGM1) || /* polling is equivalent to trig on value rather than on rising edge*/
(poll && data__->TRIG )) &&
/* trig only if not already trigged */
@@ -122,12 +122,12 @@
/* got the order to act ?*/
if(data__->TRIGGED == 1 &&
- /* and not already being processed */
- data__->STATE == PYTHON_FB_FREE)
+ /* and not already being processed */ + data__->STATE == PYTHON_FB_FREE) /* Enter the block in the fifo
/* Don't have to check if fifo cell is free
- * as fifo size == FB count, and a FB cannot
+ * as fifo size == FB count, and a FB cannot EvalFBs[Current_PLC_EvalFB] = data__;
/* copy into BUFFER local*/
@@ -186,14 +186,14 @@
//printf("PythonIterator ++ Current_Python_EvalFB %%d\n", Current_Python_EvalFB);
/* while next slot is empty */
- while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) ||
- /* or doesn't contain command */
+ while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) || + /* or doesn't contain command */ data__->STATE != PYTHON_FB_REQUESTED)
/* wait next FB to eval */
//printf("PythonIterator wait\n");
+ if(WaitPythonCommands()) return NULL; if(PythonState & PYTHON_FINISHED) return NULL;