etisserant@280: /**
etisserant@280:  * Win32 specific code
greg@329:  **/
etisserant@280: 
greg@205: #include <stdio.h>
greg@205: #include <sys/timeb.h>
greg@205: #include <time.h>
greg@205: #include <windows.h>
edouard@568: #include <locale.h>
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: 
greg@205: struct _timeb timetmp;
greg@205: void PLC_GetTime(IEC_TIME *CURRENT_TIME)
greg@205: {
greg@205: 	_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: void PLC_timer_notify()
greg@205: {
greg@205:     PLC_GetTime(&__CURRENT_TIME);
greg@205:     __run();
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: 
greg@229: /* Variable used to stop plcloop thread */
greg@229: void PlcLoop()
greg@229: {
edouard@483:     while(WaitForSingleObject(PLC_timer, INFINITE) == WAIT_OBJECT_0)
edouard@483:     {
edouard@483:         PLC_timer_notify();
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;
edouard@568:     setlocale(LC_NUMERIC, "C");
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: }
laurent@397: static unsigned long __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@483:     CloseHandle(PLC_timer);
edouard@483:     WaitForSingleObject(PLC_thread, INFINITE);
edouard@483:     __cleanup();
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 */
ed@446: int WaitDebugData(unsigned long *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@1903: #ifndef HAVE_RETAIN
Edouard@1457: void InitRetain(void)
Edouard@1457: {
Edouard@1457: }
Edouard@1457: 
Edouard@1457: void CleanupRetain(void)
Edouard@1457: {
Edouard@1457: }
Edouard@1457: 
edouard@521: int CheckRetainBuffer(void)
edouard@521: {
edouard@521: 	return 1;
edouard@521: }
edouard@521: 
edouard@580: void ValidateRetainBuffer(void)
edouard@580: {
edouard@580: }
edouard@580: 
edouard@580: void InValidateRetainBuffer(void)
edouard@580: {
edouard@580: }
edouard@580: 
edouard@483: void Retain(unsigned int offset, unsigned int count, void * p)
edouard@483: {
Edouard@681:     /*
edouard@483:     unsigned int position;
edouard@483:     for(position=0; position<count; position++ ){
edouard@483:         printf("%d : 0x%2.2x\n", offset+position, ((char*)p)[position]);
edouard@483:     }
Edouard@681:     */
edouard@483: }
edouard@483: 
edouard@483: void Remind(unsigned int offset, unsigned int count, void *p)
edouard@483: {
edouard@483: }
Edouard@1903: #endif // !HAVE_RETAIN
edouard@483: 
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: