--- 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):
_Idxs = []
- 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._FreePLC()
self.daemon = daemon
self.statuschange = statuschange
- self.python_threads_vars = None
self.hmi_frame = None
# Get the last transfered PLC if connector must be restart
@@ -220,23 +219,21 @@
break
except:
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)
+ 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)
+ 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.BeginRuntimePy()
+ self.evaluator(self.PrepareRuntimePy)
res,cmd = "None","None"
while self.PLCStatus == "Started":
#print "_PythonIterator(", res, ")",
@@ -249,6 +246,7 @@
except Exception,e:
res = "#EXCEPTION : "+str(e)
PLCprint(res)
+ self.evaluator(self.FinishRuntimePy)
PLCprint("PythonThreadProc interrupted")
def StartPLC(self, debug=False):
@@ -262,7 +260,6 @@
self._resumeDebug()
self.PLCStatus = "Started"
self.StatusChange()
- self.evaluator(self.PrepareRuntimePy)
self.PythonThread = Thread(target=self.PythonThreadProc)
self.PythonThread.start()
return True
@@ -272,12 +269,8 @@
return False
def _DoStopPLC(self):
+ self.PLCStatus = "Stopped"
self._stopPLC()
- self.PLCStatus = "Stopped"
- self.PythonThread.join(timeout=1)
- if self.PythonThread.isAlive():
- PLCprint("Python thread couldn't be killed")
- self.FinishRuntimePy()
if self._FreePLC():
self.PLCStatus = "Dirty"
self.StatusChange()
--- 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 @@
/**
* Linux specific code
- **/
+ **/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <stdlib.h>
-#include <pthread.h>
+#include <pthread.h>
/* provided by POUS.C */
extern int common_ticktime__;
@@ -51,7 +51,7 @@
timerValues.it_interval.tv_sec = period / 1000000000;
timerValues.it_interval.tv_nsec = period % 1000000000;
#endif
- }
+ }
timer_settime (PLC_timer, 0, &timerValues, NULL);
}
//
@@ -77,20 +77,23 @@
struct sigevent sigev;
/* 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 @@
__cleanup();
__debug_tick = -1;
pthread_mutex_unlock(&debug_wait_mutex);
+ pthread_mutex_destroy(&debug_wait_mutex);
+ pthread_mutex_unlock(&python_wait_mutex);
+ pthread_mutex_destroy(&python_wait_mutex);
}
extern int __tick;
@@ -125,10 +131,10 @@
int WaitDebugData()
{
/* Wait signal from PLC thread */
- pthread_mutex_lock(&debug_wait_mutex);
+ if(pthread_mutex_lock(&debug_wait_mutex)) return -1;
return __debug_tick;
}
-
+
/* 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 @@
/**
* Win32 specific code
- **/
+ **/
#include <stdio.h>
#include <sys/timeb.h>
@@ -19,7 +19,7 @@
void PLC_GetTime(IEC_TIME *CURRENT_TIME)
{
_ftime(&timetmp);
-
+
(*CURRENT_TIME).tv_sec = timetmp.time;
(*CURRENT_TIME).tv_nsec = timetmp.millitm * 1000000;
}
@@ -36,11 +36,11 @@
LARGE_INTEGER liDueTime;
/* 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 @@
HANDLE PLC_thread;
HANDLE debug_sem;
-HANDLE debug_wait_sem;
+HANDLE debug_wait_sem;
HANDLE python_sem;
-HANDLE python_wait_sem;
+HANDLE python_wait_sem;
#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
1, // initial count
1, // maximum count
NULL); // unnamed semaphore
- if (debug_sem == NULL)
+ if (debug_sem == NULL)
{
printf("startPLC CreateSemaphore debug_sem error: %d\n", GetLastError());
return;
}
-
- debug_wait_sem = CreateSemaphore(
+
+ debug_wait_sem = CreateSemaphore(
NULL, // default security attributes
0, // initial count
1, // maximum count
NULL); // unnamed semaphore
- if (debug_wait_sem == NULL)
+ if (debug_wait_sem == NULL)
{
printf("startPLC CreateSemaphore debug_wait_sem error: %d\n", GetLastError());
return;
}
- python_sem = CreateSemaphore(
+ python_sem = CreateSemaphore(
NULL, // default security attributes
1, // initial count
1, // maximum count
NULL); // unnamed semaphore
- if (python_sem == NULL)
+ if (python_sem == NULL)
{
printf("startPLC CreateSemaphore python_sem error: %d\n", GetLastError());
return;
}
- python_wait_sem = CreateSemaphore(
+ python_wait_sem = CreateSemaphore(
NULL, // default security attributes
0, // initial count
1, // maximum count
NULL); // unnamed semaphore
- if (python_wait_sem == NULL)
+ if (python_wait_sem == NULL)
{
printf("startPLC CreateSemaphore python_wait_sem error: %d\n", GetLastError());
return;
}
-
+
/* Create a waitable timer */
PLC_timer = CreateWaitableTimer(NULL, FALSE, "WaitableTimer");
if(NULL == PLC_timer)
@@ -172,10 +172,10 @@
/* from plc_debugger.c */
int WaitDebugData()
{
- WaitForSingleObject(debug_wait_sem, INFINITE);
+ if(WaitForSingleObject(debug_wait_sem, INFINITE) != WAIT_OBJECT_0) return -1;
return __debug_tick;
}
-
+
/* Called by PLC thread when debug_publish finished
* This is supposed to unlock debugger thread in WaitDebugData*/
void InitiateDebugTransfer()
@@ -190,7 +190,7 @@
{
__DEBUG = 0;
/* Prevent PLC to enter debug code */
- WaitForSingleObject(debug_sem, INFINITE);
+ WaitForSingleObject(debug_sem, INFINITE);
}
void resumeDebug()
@@ -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 @@
extension = ".so"
def getXenoConfig(self):
""" 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
* flags.
- *
+ *
* */
#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_FREE 0
#define PYTHON_FB_REQUESTED 1
@@ -62,12 +62,12 @@
void __retrieve_python()
{
- /* Check Python thread is not being
+ /* Check Python thread is not being
* modifying internal python_eval data */
- PythonState = TryLockPython() ?
- PYTHON_LOCKED_BY_PLC :
+ PythonState = TryLockPython() ?
+ PYTHON_LOCKED_BY_PLC :
PYTHON_LOCKED_BY_PYTHON;
- /* 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
* be requested twice */
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)
{
UnLockPython();
/* wait next FB to eval */
//printf("PythonIterator wait\n");
- WaitPythonCommands();
+ if(WaitPythonCommands()) return NULL;
/*emergency exit*/
if(PythonState & PYTHON_FINISHED) return NULL;
LockPython();