etisserant@280: /** etisserant@280: * Win32 specific code greg@329: **/ etisserant@280: greg@205: #include greg@205: #include greg@205: #include greg@205: #include edouard@568: #include greg@205: etisserant@280: greg@244: long AtomicCompareExchange(long* atomicvar, long compared, long exchange) greg@205: { greg@205: return InterlockedCompareExchange(atomicvar, exchange, compared); greg@205: } Edouard@954: CRITICAL_SECTION Atomic64CS; Edouard@954: long long AtomicCompareExchange64(long long* atomicvar, long long compared, long long exchange) Edouard@954: { Edouard@954: long long res; Edouard@954: EnterCriticalSection(&Atomic64CS); Edouard@954: res=*atomicvar; Edouard@954: if(*atomicvar == compared){ Edouard@954: *atomicvar = exchange; Edouard@954: } Edouard@954: LeaveCriticalSection(&Atomic64CS); Edouard@954: return res; Edouard@954: } greg@205: edouard@3296: struct timeb timetmp; greg@205: void PLC_GetTime(IEC_TIME *CURRENT_TIME) greg@205: { edouard@3296: ftime(&timetmp); greg@329: greg@205: (*CURRENT_TIME).tv_sec = timetmp.time; greg@205: (*CURRENT_TIME).tv_nsec = timetmp.millitm * 1000000; greg@205: } greg@205: greg@205: HANDLE PLC_timer = NULL; edouard@518: void PLC_SetTimer(unsigned long long next, unsigned long long period) greg@205: { greg@229: LARGE_INTEGER liDueTime; greg@205: /* arg 2 of SetWaitableTimer take 100 ns interval*/ greg@205: liDueTime.QuadPart = next / (-100); greg@329: Edouard@685: if (!SetWaitableTimer(PLC_timer, &liDueTime, period<1000000?1:period/1000000, NULL, NULL, 0)) greg@205: { greg@205: printf("SetWaitableTimer failed (%d)\n", GetLastError()); greg@205: } greg@229: } greg@229: andrej@2174: int PLC_shutdown; andrej@2174: andrej@2174: int ForceSaveRetainReq(void) { andrej@2174: return PLC_shutdown; andrej@2174: } andrej@2174: greg@229: /* Variable used to stop plcloop thread */ greg@229: void PlcLoop() greg@229: { andrej@2174: PLC_shutdown = 0; andrej@2174: while(!PLC_shutdown) { edouard@3850: if (WaitForSingleObject(PLC_timer, INFINITE) != WAIT_OBJECT_0){ andrej@2174: PLC_shutdown = 1; edouard@3850: break; edouard@3850: } edouard@3850: PLC_GetTime(&__CURRENT_TIME); edouard@3850: __run(); edouard@483: } greg@205: } greg@205: greg@229: HANDLE PLC_thread; greg@244: HANDLE debug_sem; greg@329: HANDLE debug_wait_sem; etisserant@280: HANDLE python_sem; greg@329: HANDLE python_wait_sem; etisserant@280: etisserant@280: #define maxval(a,b) ((a>b)?a:b) greg@229: int startPLC(int argc,char **argv) greg@205: { greg@229: unsigned long thread_id = 0; Edouard@954: BOOL tmp; greg@205: edouard@483: debug_sem = CreateSemaphore( edouard@483: NULL, // default security attributes edouard@483: 1, // initial count edouard@483: 1, // maximum count edouard@483: NULL); // unnamed semaphore greg@329: if (debug_sem == NULL) greg@244: { etisserant@280: printf("startPLC CreateSemaphore debug_sem error: %d\n", GetLastError()); ewald@1573: return 1; greg@244: } greg@329: edouard@483: debug_wait_sem = CreateSemaphore( edouard@483: NULL, // default security attributes edouard@483: 0, // initial count edouard@483: 1, // maximum count edouard@483: NULL); // unnamed semaphore etisserant@280: greg@329: if (debug_wait_sem == NULL) etisserant@280: { etisserant@280: printf("startPLC CreateSemaphore debug_wait_sem error: %d\n", GetLastError()); ewald@1573: return 1; etisserant@280: } etisserant@280: edouard@483: python_sem = CreateSemaphore( edouard@483: NULL, // default security attributes edouard@483: 1, // initial count edouard@483: 1, // maximum count edouard@483: NULL); // unnamed semaphore etisserant@280: greg@329: if (python_sem == NULL) etisserant@280: { etisserant@280: printf("startPLC CreateSemaphore python_sem error: %d\n", GetLastError()); ewald@1573: return 1; etisserant@280: } edouard@483: python_wait_sem = CreateSemaphore( edouard@483: NULL, // default security attributes edouard@483: 0, // initial count edouard@483: 1, // maximum count edouard@483: NULL); // unnamed semaphore etisserant@280: etisserant@280: greg@329: if (python_wait_sem == NULL) etisserant@280: { etisserant@280: printf("startPLC CreateSemaphore python_wait_sem error: %d\n", GetLastError()); ewald@1573: return 1; etisserant@280: } etisserant@280: greg@329: edouard@483: /* Create a waitable timer */ Edouard@685: timeBeginPeriod(1); greg@205: PLC_timer = CreateWaitableTimer(NULL, FALSE, "WaitableTimer"); greg@205: if(NULL == PLC_timer) greg@205: { greg@205: printf("CreateWaitableTimer failed (%d)\n", GetLastError()); greg@205: return 1; greg@205: } greg@205: if( __init(argc,argv) == 0 ) greg@205: { Edouard@1428: PLC_SetTimer(common_ticktime__,common_ticktime__); edouard@483: PLC_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlcLoop, NULL, 0, &thread_id); greg@205: } greg@229: else{ edouard@483: return 1; greg@229: } greg@205: return 0; greg@205: } edouard@3947: static unsigned int __debug_tick; greg@244: greg@244: int TryEnterDebugSection(void) greg@244: { greg@244: //printf("TryEnterDebugSection\n"); edouard@469: if(WaitForSingleObject(debug_sem, 0) == WAIT_OBJECT_0){ edouard@469: /* Only enter if debug active */ edouard@469: if(__DEBUG){ edouard@469: return 1; edouard@469: } edouard@483: ReleaseSemaphore(debug_sem, 1, NULL); edouard@483: } edouard@469: return 0; greg@244: } greg@244: greg@244: void LeaveDebugSection(void) greg@244: { greg@244: ReleaseSemaphore(debug_sem, 1, NULL); greg@244: //printf("LeaveDebugSection\n"); greg@244: } greg@229: greg@229: int stopPLC() greg@229: { edouard@3850: edouard@3850: PLC_shutdown = 1; edouard@3850: // force last wakeup of PLC thread edouard@3850: SetWaitableTimer(PLC_timer, 0, 0, NULL, NULL, 0); edouard@3850: // wait end of PLC thread edouard@3850: WaitForSingleObject(PLC_thread, INFINITE); edouard@3850: edouard@3850: __cleanup(); edouard@3850: edouard@483: CloseHandle(PLC_timer); edouard@483: CloseHandle(debug_wait_sem); edouard@483: CloseHandle(debug_sem); edouard@483: CloseHandle(python_wait_sem); edouard@483: CloseHandle(python_sem); edouard@483: CloseHandle(PLC_thread); greg@229: } greg@229: greg@229: /* from plc_debugger.c */ edouard@3947: int WaitDebugData(unsigned int *tick) greg@229: { laurent@709: DWORD res; laurent@709: res = WaitForSingleObject(debug_wait_sem, INFINITE); ed@446: *tick = __debug_tick; ed@446: /* Wait signal from PLC thread */ laurent@709: return res != WAIT_OBJECT_0; greg@229: } greg@329: etisserant@280: /* Called by PLC thread when debug_publish finished greg@229: * This is supposed to unlock debugger thread in WaitDebugData*/ greg@229: void InitiateDebugTransfer() greg@229: { greg@244: /* remember tick */ greg@244: __debug_tick = __tick; greg@244: /* signal debugger thread it can read data */ etisserant@280: ReleaseSemaphore(debug_wait_sem, 1, NULL); greg@229: } greg@244: Edouard@614: int suspendDebug(int disable) edouard@469: { greg@244: /* Prevent PLC to enter debug code */ edouard@483: WaitForSingleObject(debug_sem, INFINITE); edouard@469: __DEBUG = !disable; Lolitech@484: if(disable) Lolitech@484: ReleaseSemaphore(debug_sem, 1, NULL); Edouard@614: return 0; greg@244: } greg@244: greg@244: void resumeDebug() greg@244: { etisserant@290: __DEBUG = 1; greg@244: /* Let PLC enter debug code */ greg@244: ReleaseSemaphore(debug_sem, 1, NULL); greg@244: } etisserant@280: etisserant@280: /* from plc_python.c */ etisserant@280: int WaitPythonCommands(void) etisserant@280: { etisserant@280: /* Wait signal from PLC thread */ greg@329: return WaitForSingleObject(python_wait_sem, INFINITE); greg@329: } greg@329: etisserant@280: /* Called by PLC thread on each new python command*/ etisserant@280: void UnBlockPythonCommands(void) etisserant@280: { etisserant@280: /* signal debugger thread it can read data */ etisserant@280: ReleaseSemaphore(python_wait_sem, 1, NULL); etisserant@280: } etisserant@280: etisserant@280: int TryLockPython(void) etisserant@280: { etisserant@280: return WaitForSingleObject(python_sem, 0) == WAIT_OBJECT_0; etisserant@280: } etisserant@280: etisserant@280: void UnLockPython(void) etisserant@280: { etisserant@280: ReleaseSemaphore(python_sem, 1, NULL); etisserant@280: } etisserant@280: etisserant@280: void LockPython(void) etisserant@280: { etisserant@280: WaitForSingleObject(python_sem, INFINITE); etisserant@280: } etisserant@280: Edouard@1465: static void __attribute__((constructor)) Edouard@1465: beremiz_dll_init(void) Edouard@1465: { Edouard@1465: InitializeCriticalSection(&Atomic64CS); Edouard@1465: Edouard@1465: } Edouard@1465: Edouard@1465: static void __attribute__((destructor)) Edouard@1465: beremiz_dll_destroy(void) Edouard@1465: { Edouard@1465: DeleteCriticalSection(&Atomic64CS); Edouard@1465: } Edouard@1465: edouard@3295: struct RT_to_nRT_signal_s { edouard@3295: HANDLE sem; edouard@3295: }; edouard@3295: edouard@3295: typedef struct RT_to_nRT_signal_s RT_to_nRT_signal_t; edouard@3295: edouard@3295: #define _LogAndReturnNull(text) \ edouard@3295: {\ edouard@3295: char mstr[256] = text " for ";\ edouard@3295: strncat(mstr, name, 255);\ edouard@3295: LogMessage(LOG_CRITICAL, mstr, strlen(mstr));\ edouard@3295: return NULL;\ edouard@3295: } edouard@3295: edouard@3295: void *create_RT_to_nRT_signal(char* name){ edouard@3295: RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t*)malloc(sizeof(RT_to_nRT_signal_t)); edouard@3295: edouard@3295: if(!sig) edouard@3295: _LogAndReturnNull("Failed allocating memory for RT_to_nRT signal"); edouard@3295: edouard@3295: sig->sem = CreateSemaphore( edouard@3295: NULL, // default security attributes edouard@3295: 1, // initial count edouard@3295: 1, // maximum count edouard@3295: NULL); // unnamed semaphore edouard@3295: edouard@3295: if(sig->sem == NULL) edouard@3295: { edouard@3295: char mstr[256]; edouard@3295: snprintf(mstr, 255, "startPLC CreateSemaphore %s error: %d\n", name, GetLastError()); edouard@3295: LogMessage(LOG_CRITICAL, mstr, strlen(mstr)); edouard@3295: return NULL; edouard@3295: } edouard@3295: edouard@3295: return (void*)sig; edouard@3295: } edouard@3295: edouard@3295: void delete_RT_to_nRT_signal(void* handle){ edouard@3295: RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t*)handle; edouard@3295: edouard@3295: CloseHandle(python_sem); edouard@3295: edouard@3295: free(sig); edouard@3295: } edouard@3295: edouard@3295: int wait_RT_to_nRT_signal(void* handle){ edouard@3295: int ret; edouard@3295: RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t*)handle; edouard@3295: return WaitForSingleObject(sig->sem, INFINITE); edouard@3295: } edouard@3295: edouard@3295: int unblock_RT_to_nRT_signal(void* handle){ edouard@3295: RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t*)handle; edouard@3295: return ReleaseSemaphore(sig->sem, 1, NULL); edouard@3295: } edouard@3295: edouard@3295: void nRT_reschedule(void){ edouard@3295: SwitchToThread(); edouard@3295: } edouard@3295: