# HG changeset patch # User edouard # Date 1260317508 -3600 # Node ID bc26c42d2eecf6133c9aa616fa5180a75db8c430 # Parent 7c83eb6a55bd081c7b2a912567a917000c88f592# Parent 28d47c1df46f46840964b94e8949298df4a7c3e8 fixed greg's crap in win32, enhanced debug stability, implemented preliminary retain diff -r 7c83eb6a55bd -r bc26c42d2eec plugger.py --- a/plugger.py Wed Dec 09 00:56:18 2009 +0100 +++ b/plugger.py Wed Dec 09 01:11:48 2009 +0100 @@ -681,12 +681,8 @@ from plcopen.structures import IEC_KEYWORDS, TypeHierarchy_list # Construct debugger natively supported types -DebugTypes = [t for t in zip(*TypeHierarchy_list)[0] if not t.startswith("ANY")] + \ - ["STEP","TRANSITION","ACTION"] +DebugTypes = [t for t in zip(*TypeHierarchy_list)[0] if not t.startswith("ANY")] DebugTypesSize = {"BOOL" : 1, - "STEP" : 1, - "TRANSITION" : 1, - "ACTION" : 1, "SINT" : 1, "USINT" : 1, "BYTE" : 1, @@ -1712,7 +1708,7 @@ #print weakcallable, value, args, kwargs function = getattr(weakcallable, function_name, None) if function is not None: - if status == "Forced": + if status == "Forced" and cargs[1] == fvalue: function(*(cargs + (True,) + args), **kwargs) else: function(*(cargs + args), **kwargs) @@ -1803,12 +1799,13 @@ """ Stop PLC """ + if self._connector is not None and not self._connector.StopPLC(): + self.logger.write_error(_("Couldn't stop PLC !\n")) + if self.DebugThread is not None: self.logger.write(_("Stopping debug\n")) self.KillDebugThread() - if self._connector is not None and not self._connector.StopPLC(): - self.logger.write_error(_("Couldn't stop PLC !\n")) self.UpdateMethodsFromPLCStatus() def _Connect(self): diff -r 7c83eb6a55bd -r bc26c42d2eec plugins/python/plc_python.c --- a/plugins/python/plc_python.c Wed Dec 09 00:56:18 2009 +0100 +++ b/plugins/python/plc_python.c Wed Dec 09 01:11:48 2009 +0100 @@ -157,6 +157,8 @@ char* next_command; PYTHON_EVAL* data__; //printf("PythonIterator result %%s\n", result); + /*emergency exit*/ + if(PythonState & PYTHON_FINISHED) return NULL; /* take python mutex to prevent changing PLC data while PLC running */ LockPython(); /* Get current FB */ diff -r 7c83eb6a55bd -r bc26c42d2eec runtime/PLCObject.py --- a/runtime/PLCObject.py Wed Dec 09 00:56:18 2009 +0100 +++ b/runtime/PLCObject.py Wed Dec 09 01:11:48 2009 +0100 @@ -86,7 +86,6 @@ Load PLC library Declare all functions, arguments and return values """ - PLCprint("Load PLC") try: self._PLClibraryHandle = dlopen(self._GetLibFileName()) self.PLClibraryHandle = ctypes.CDLL(self.CurrentPLCFilename, handle=self._PLClibraryHandle) @@ -103,11 +102,7 @@ self._PythonIterator.restype = ctypes.c_char_p self._PythonIterator.argtypes = [ctypes.c_char_p] - def StopPLCLock(): - self.PLClibraryLock.acquire() - self._stopPLC_real() - self.PLClibraryLock.release() - + self._stopPLC = self._stopPLC_real else: # If python plugin is not enabled, we reuse _PythonIterator # as a call that block pythonthread until StopPLC @@ -119,13 +114,11 @@ return None self._PythonIterator = PythonIterator - def StopPLCLock(): - self.PLClibraryLock.acquire() + def __StopPLC(): self._stopPLC_real() self.PythonIteratorLock.release() - self.PLClibraryLock.release() - - self._stopPLC = StopPLCLock + self._stopPLC = __StopPLC + self._ResetDebugVariables = self.PLClibraryHandle.ResetDebugVariables self._ResetDebugVariables.restype = None @@ -163,7 +156,7 @@ self._startPLC = lambda:None self._stopPLC = lambda:None self._ResetDebugVariables = lambda:None - self._RegisterDebugVariable = lambda x:None + self._RegisterDebugVariable = lambda x, y:None self._IterDebugData = lambda x,y:None self._FreeDebugData = lambda:None self._GetDebugData = lambda:-1 @@ -217,7 +210,6 @@ self.python_threads_vars = None def PythonThreadProc(self): - PLCprint("PythonThreadProc started") c_argv = ctypes.c_char_p * len(self.argv) error = None if self._LoadNewPLC(): @@ -248,7 +240,6 @@ PLCprint("Problem %s PLC"%error) self.PLCStatus = "Broken" self._FreePLC() - PLCprint("PythonThreadProc interrupted") def StartPLC(self): PLCprint("StartPLC") @@ -260,6 +251,7 @@ def StopPLC(self): PLCprint("StopPLC") if self.PLCStatus == "Started": + self.PLCStatus = "Stopped" self._stopPLC() return True return False @@ -384,30 +376,31 @@ """ if self.PLCStatus == "Started": res=[] - self.PLClibraryLock.acquire() tick = ctypes.c_uint32() size = ctypes.c_uint32() buffer = ctypes.c_void_p() offset = 0 - if self._GetDebugData(ctypes.byref(tick),ctypes.byref(size),ctypes.byref(buffer)) == 0 : - for idx, iectype, forced in self._Idxs: - cursor = ctypes.c_void_p(buffer.value + offset) - c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None)) - if c_type is not None and offset < size: - res.append(unpack_func(ctypes.cast(cursor, - ctypes.POINTER(c_type)).contents)) - offset += ctypes.sizeof(c_type) - else: - if c_type is None: - PLCprint("Debug error - " + iectype + " not supported !") - if offset >= size: - PLCprint("Debug error - buffer too small !") - break - self._FreeDebugData() - self.PLClibraryLock.release() + if self.PLClibraryLock.acquire(False) and \ + self._GetDebugData(ctypes.byref(tick),ctypes.byref(size),ctypes.byref(buffer)) == 0 : + if size.value: + for idx, iectype, forced in self._Idxs: + cursor = ctypes.c_void_p(buffer.value + offset) + c_type,unpack_func, pack_func = self.TypeTranslator.get(iectype, (None,None,None)) + if c_type is not None and offset < size: + res.append(unpack_func(ctypes.cast(cursor, + ctypes.POINTER(c_type)).contents)) + offset += ctypes.sizeof(c_type) + else: + if c_type is None: + PLCprint("Debug error - " + iectype + " not supported !") + if offset >= size: + PLCprint("Debug error - buffer too small !") + break + self._FreeDebugData() + self.PLClibraryLock.release() if offset and offset == size.value: return self.PLCStatus, tick.value, res - else: - PLCprint("Debug error - bad buffer unpack !") + elif size.value: + PLCprint("Debug error - wrong buffer unpack !") return self.PLCStatus, None, None diff -r 7c83eb6a55bd -r bc26c42d2eec targets/LPC/plc_LPC_main.c --- a/targets/LPC/plc_LPC_main.c Wed Dec 09 00:56:18 2009 +0100 +++ b/targets/LPC/plc_LPC_main.c Wed Dec 09 01:11:48 2009 +0100 @@ -92,3 +92,11 @@ void LockPython(void) { } + +void Retain(unsigned int offset, unsigned int count, void *p) +{t +} + +void Remind(unsigned int offset, unsigned int count, void *p) +{ +} diff -r 7c83eb6a55bd -r bc26c42d2eec targets/Linux/plc_Linux_main.c --- a/targets/Linux/plc_Linux_main.c Wed Dec 09 00:56:18 2009 +0100 +++ b/targets/Linux/plc_Linux_main.c Wed Dec 09 01:11:48 2009 +0100 @@ -111,8 +111,8 @@ if(__DEBUG){ return 1; } + pthread_mutex_unlock(&debug_mutex); } - pthread_mutex_unlock(&debug_mutex); return 0; } @@ -127,12 +127,10 @@ PLC_SetTimer(0,0); timer_delete (PLC_timer); __cleanup(); - __debug_tick = -1; - pthread_mutex_unlock(&debug_mutex); - pthread_mutex_unlock(&debug_wait_mutex); pthread_mutex_destroy(&debug_wait_mutex); - pthread_mutex_unlock(&python_wait_mutex); + pthread_mutex_destroy(&debug_mutex); pthread_mutex_destroy(&python_wait_mutex); + pthread_mutex_destroy(&python_mutex); return 0; } @@ -198,3 +196,11 @@ { pthread_mutex_lock(&python_mutex); } + +void Retain(unsigned int offset, unsigned int count, void *p) +{ +} + +void Remind(unsigned int offset, unsigned int count, void *p) +{ +} diff -r 7c83eb6a55bd -r bc26c42d2eec targets/Win32/plc_Win32_main.c --- a/targets/Win32/plc_Win32_main.c Wed Dec 09 00:56:18 2009 +0100 +++ b/targets/Win32/plc_Win32_main.c Wed Dec 09 01:11:48 2009 +0100 @@ -37,31 +37,19 @@ /* 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)) + if (!SetWaitableTimer(PLC_timer, &liDueTime, period/1000000, NULL, NULL, 0)) { printf("SetWaitableTimer failed (%d)\n", GetLastError()); } } /* Variable used to stop plcloop thread */ -int runplcloop; void PlcLoop() { - runplcloop = 1; - while(runplcloop) - { - // Set a timer - PLC_SetTimer(Ttick,Ttick); - if (WaitForSingleObject(PLC_timer, INFINITE) != WAIT_OBJECT_0) - { - printf("WaitForSingleObject failed (%d)\n", GetLastError()); - } - PLC_timer_notify(); - } + while(WaitForSingleObject(PLC_timer, INFINITE) == WAIT_OBJECT_0) + { + PLC_timer_notify(); + } } HANDLE PLC_thread; @@ -77,22 +65,22 @@ /* Define Ttick to 1ms if common_ticktime not defined */ Ttick = common_ticktime__?common_ticktime__:1000000; - debug_sem = CreateSemaphore( - NULL, // default security attributes - 1, // initial count - 1, // maximum count - NULL); // unnamed semaphore + debug_sem = CreateSemaphore( + NULL, // default security attributes + 1, // initial count + 1, // maximum count + NULL); // unnamed semaphore if (debug_sem == NULL) { printf("startPLC CreateSemaphore debug_sem error: %d\n", GetLastError()); return; } - debug_wait_sem = CreateSemaphore( - NULL, // default security attributes - 0, // initial count - 1, // maximum count - NULL); // unnamed semaphore + debug_wait_sem = CreateSemaphore( + NULL, // default security attributes + 0, // initial count + 1, // maximum count + NULL); // unnamed semaphore if (debug_wait_sem == NULL) { @@ -100,22 +88,22 @@ return; } - python_sem = CreateSemaphore( - NULL, // default security attributes - 1, // initial count - 1, // maximum count - NULL); // unnamed semaphore + python_sem = CreateSemaphore( + NULL, // default security attributes + 1, // initial count + 1, // maximum count + NULL); // unnamed semaphore if (python_sem == NULL) { printf("startPLC CreateSemaphore python_sem error: %d\n", GetLastError()); return; } - python_wait_sem = CreateSemaphore( - NULL, // default security attributes - 0, // initial count - 1, // maximum count - NULL); // unnamed semaphore + python_wait_sem = CreateSemaphore( + NULL, // default security attributes + 0, // initial count + 1, // maximum count + NULL); // unnamed semaphore if (python_wait_sem == NULL) @@ -125,7 +113,7 @@ } - /* Create a waitable timer */ + /* Create a waitable timer */ PLC_timer = CreateWaitableTimer(NULL, FALSE, "WaitableTimer"); if(NULL == PLC_timer) { @@ -134,11 +122,11 @@ } if( __init(argc,argv) == 0 ) { - printf("Tick Time : %d ms\n", common_ticktime__); - PLC_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlcLoop, NULL, 0, &thread_id); + PLC_SetTimer(Ttick,Ttick); + PLC_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlcLoop, NULL, 0, &thread_id); } else{ - return 1; + return 1; } return 0; } @@ -152,9 +140,9 @@ if(__DEBUG){ return 1; } - ReleaseSemaphore(debug_sem, 1, NULL); + ReleaseSemaphore(debug_sem, 1, NULL); + } return 0; - } } void LeaveDebugSection(void) @@ -165,15 +153,14 @@ int stopPLC() { - runplcloop = 0; - WaitForSingleObject(PLC_thread, INFINITE); - __cleanup(); - __debug_tick = -1; - ReleaseSemaphore(debug_wait_sem, 1, NULL); - CloseHandle(debug_sem); - CloseHandle(debug_wait_sem); - CloseHandle(PLC_timer); - CloseHandle(PLC_thread); + CloseHandle(PLC_timer); + WaitForSingleObject(PLC_thread, INFINITE); + __cleanup(); + CloseHandle(debug_wait_sem); + CloseHandle(debug_sem); + CloseHandle(python_wait_sem); + CloseHandle(python_sem); + CloseHandle(PLC_thread); } /* from plc_debugger.c */ @@ -197,7 +184,7 @@ void suspendDebug(int disable) { /* Prevent PLC to enter debug code */ - WaitForSingleObject(debug_sem, INFINITE); + WaitForSingleObject(debug_sem, INFINITE); /*__DEBUG is protected by this mutex */ __DEBUG = !disable; } @@ -238,3 +225,15 @@ WaitForSingleObject(python_sem, INFINITE); } +void Retain(unsigned int offset, unsigned int count, void * p) +{ + unsigned int position; + for(position=0; positionflags;\ - ptrvalue = &((__IEC_##TYPENAME##_t *)varp)->value;\ + *flags = ((__IEC_##TYPENAME##_t *)varp)->flags;\ + *ptrvalue = &((__IEC_##TYPENAME##_t *)varp)->value;\ break; #define __BufferDebugDataIterator_case_p(TYPENAME)\ case TYPENAME##_P_ENUM :\ - flags = ((__IEC_##TYPENAME##_p *)varp)->flags;\ - ptrvalue = ((__IEC_##TYPENAME##_p *)varp)->value;\ - break; - -void BufferDebugDataIterator(void* varp, __IEC_types_enum vartype) -{ - void *ptrvalue = NULL; - char flags = 0; + *flags = ((__IEC_##TYPENAME##_p *)varp)->flags;\ + *ptrvalue = ((__IEC_##TYPENAME##_p *)varp)->value;\ + break; + +void UnpackVar(void* varp, __IEC_types_enum vartype, void **ptrvalue, char *flags) +{ /* find data to copy*/ switch(vartype){ ANY(__BufferDebugDataIterator_case_t) @@ -99,26 +77,114 @@ default: break; } - if(flags && __IEC_DEBUG_FLAG){ +} + +void Remind(unsigned int offset, unsigned int count, void * p); + +void RemindIterator(void* varp, __IEC_types_enum vartype) +{ + void *ptrvalue = NULL; + char flags = 0; + UnpackVar(varp, vartype, &ptrvalue, &flags); + + if(flags && __IEC_RETAIN_FLAG){ USINT size = __get_type_enum_size(vartype); /* compute next cursor positon*/ - char* next_cursor = buffer_cursor + size; + unsigned int next_retain_offset = retain_offset + size; /* if buffer not full */ - if(next_cursor <= debug_buffer + BUFFER_SIZE) - { - /* copy data to the buffer */ - memcpy(buffer_cursor, ptrvalue, size); - /* increment cursor according size*/ - buffer_cursor = next_cursor; - }else{ - /*TODO : signal overflow*/ + Remind(retain_offset, size, ptrvalue); + /* increment cursor according size*/ + retain_offset = next_retain_offset; + } +} + +void __init_debug(void) +{ + /* init local static vars */ + buffer_cursor = debug_buffer; + retain_offset = 0; + buffer_state = BUFFER_FREE; + /* Iterate over all variables to fill debug buffer */ + __for_each_variable_do(RemindIterator); + retain_offset = 0; +} + +extern void InitiateDebugTransfer(void); + +extern unsigned long __tick; + +void __cleanup_debug(void) +{ + buffer_cursor = debug_buffer; + InitiateDebugTransfer(); +} + +void __retrieve_debug(void) +{ +} + +void DoDebug(void *ptrvalue, char flags, USINT size) +{ + /* compute next cursor positon*/ + char* next_cursor = buffer_cursor + size; + /* if buffer not full */ + if(next_cursor <= debug_buffer + BUFFER_SIZE) + { + /* copy data to the buffer */ + memcpy(buffer_cursor, ptrvalue, size); + /* increment cursor according size*/ + buffer_cursor = next_cursor; + }else{ + /*TODO : signal overflow*/ + } +} + +void Retain(unsigned int offset, unsigned int count, void * p); +void DoRetain(void *ptrvalue, char flags, USINT size){ + /* compute next cursor positon*/ + unsigned int next_retain_offset = retain_offset + size; + /* if buffer not full */ + Retain(retain_offset, size, ptrvalue); + /* increment cursor according size*/ + retain_offset = next_retain_offset; +} + +void BufferDebugDataIterator(void* varp, __IEC_types_enum vartype) +{ + void *ptrvalue = NULL; + char flags = 0; + UnpackVar(varp, vartype, &ptrvalue, &flags); + /* For optimization purpose we do retain and debug in the same pass */ + if(flags & (__IEC_DEBUG_FLAG | __IEC_RETAIN_FLAG)){ + USINT size = __get_type_enum_size(vartype); + if(flags & __IEC_DEBUG_FLAG){ + DoDebug(ptrvalue, flags, size); } - } -} - + if(flags & __IEC_RETAIN_FLAG){ + DoRetain(ptrvalue, flags, size); + } + } +} + +void RetainIterator(void* varp, __IEC_types_enum vartype) +{ + void *ptrvalue = NULL; + char flags = 0; + UnpackVar(varp, vartype, &ptrvalue, &flags); + + if(flags & __IEC_RETAIN_FLAG){ + USINT size = __get_type_enum_size(vartype); + DoRetain(ptrvalue, flags, size); + } +} + +extern int TryEnterDebugSection(void); +extern long AtomicCompareExchange(long*, long, long); +extern void LeaveDebugSection(void); void __publish_debug(void) { + retain_offset = 0; /* Check there is no running debugger re-configuration */ if(TryEnterDebugSection()){ /* Lock buffer */ @@ -141,6 +207,9 @@ InitiateDebugTransfer(); /* size */ } LeaveDebugSection(); + }else{ + /* when not debugging, do only retain */ + __for_each_variable_do(RetainIterator); } }