kinsamanka@3778: /** kinsamanka@3778: * Mac OSX specific code kinsamanka@3778: **/ kinsamanka@3778: kinsamanka@3778: #include kinsamanka@3778: #include kinsamanka@3778: #include kinsamanka@3778: #include kinsamanka@3778: #include kinsamanka@3778: #include kinsamanka@3778: #include kinsamanka@3778: #include kinsamanka@3778: #include kinsamanka@3778: kinsamanka@3778: static sem_t Run_PLC; kinsamanka@3778: kinsamanka@3778: long AtomicCompareExchange(long *atomicvar, long compared, long exchange) kinsamanka@3778: { kinsamanka@3778: return __sync_val_compare_and_swap(atomicvar, compared, exchange); kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: long long AtomicCompareExchange64(long long *atomicvar, long long compared, kinsamanka@3778: long long exchange) kinsamanka@3778: { kinsamanka@3778: return __sync_val_compare_and_swap(atomicvar, compared, exchange); kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: void PLC_GetTime(IEC_TIME * CURRENT_TIME) kinsamanka@3778: { kinsamanka@3778: struct timespec tmp; kinsamanka@3778: clock_gettime(CLOCK_REALTIME, &tmp); kinsamanka@3778: CURRENT_TIME->tv_sec = tmp.tv_sec; kinsamanka@3778: CURRENT_TIME->tv_nsec = tmp.tv_nsec; kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: dispatch_queue_t queue; kinsamanka@3778: dispatch_source_t PLC_timer; kinsamanka@3778: kinsamanka@3778: static inline void PLC_timer_cancel(void *arg) kinsamanka@3778: { kinsamanka@3778: dispatch_release(PLC_timer); kinsamanka@3778: dispatch_release(queue); kinsamanka@3778: exit(0); kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: static inline void PLC_timer_notify(void *arg) kinsamanka@3778: { kinsamanka@3778: PLC_GetTime(&__CURRENT_TIME); kinsamanka@3778: sem_post(&Run_PLC); kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: void PLC_SetTimer(unsigned long long next, unsigned long long period) kinsamanka@3778: { kinsamanka@3778: if (next == period && next == 0) { kinsamanka@3778: dispatch_suspend(PLC_timer); kinsamanka@3778: } else { kinsamanka@3778: dispatch_time_t start; kinsamanka@3778: start = dispatch_time(DISPATCH_TIME_NOW, next); kinsamanka@3778: dispatch_source_set_timer(PLC_timer, start, period, 0); kinsamanka@3778: dispatch_resume(PLC_timer); kinsamanka@3778: } kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: void catch_signal(int sig) kinsamanka@3778: { kinsamanka@3778: signal(SIGINT, catch_signal); kinsamanka@3778: printf("Got Signal %d\n", sig); kinsamanka@3778: dispatch_source_cancel(PLC_timer); kinsamanka@3778: exit(0); kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: static unsigned long __debug_tick; kinsamanka@3778: kinsamanka@3778: pthread_t PLC_thread; kinsamanka@3778: static pthread_mutex_t python_wait_mutex = PTHREAD_MUTEX_INITIALIZER; kinsamanka@3778: static pthread_mutex_t python_mutex = PTHREAD_MUTEX_INITIALIZER; kinsamanka@3778: static pthread_mutex_t debug_wait_mutex = PTHREAD_MUTEX_INITIALIZER; kinsamanka@3778: static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER; kinsamanka@3778: kinsamanka@3778: int PLC_shutdown = 0; kinsamanka@3778: kinsamanka@3778: int ForceSaveRetainReq(void) kinsamanka@3778: { kinsamanka@3778: return PLC_shutdown; kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: void PLC_thread_proc(void *arg) kinsamanka@3778: { kinsamanka@3778: while (!PLC_shutdown) { kinsamanka@3778: sem_wait(&Run_PLC); kinsamanka@3778: __run(); kinsamanka@3778: } kinsamanka@3778: pthread_exit(0); kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: #define maxval(a,b) ((a>b)?a:b) kinsamanka@3778: int startPLC(int argc, char **argv) kinsamanka@3778: { kinsamanka@3778: setlocale(LC_NUMERIC, "C"); kinsamanka@3778: kinsamanka@3778: PLC_shutdown = 0; kinsamanka@3778: kinsamanka@3778: sem_init(&Run_PLC, 0, 0); kinsamanka@3778: kinsamanka@3778: pthread_create(&PLC_thread, NULL, (void *)&PLC_thread_proc, NULL); kinsamanka@3778: kinsamanka@3778: pthread_mutex_init(&debug_wait_mutex, NULL); kinsamanka@3778: pthread_mutex_init(&debug_mutex, NULL); kinsamanka@3778: pthread_mutex_init(&python_wait_mutex, NULL); kinsamanka@3778: pthread_mutex_init(&python_mutex, NULL); kinsamanka@3778: kinsamanka@3778: pthread_mutex_lock(&debug_wait_mutex); kinsamanka@3778: pthread_mutex_lock(&python_wait_mutex); kinsamanka@3778: kinsamanka@3778: queue = dispatch_queue_create("timerQueue", 0); kinsamanka@3778: PLC_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue); kinsamanka@3778: kinsamanka@3778: dispatch_set_context(PLC_timer, &PLC_timer); kinsamanka@3778: dispatch_source_set_event_handler_f(PLC_timer, PLC_timer_notify); kinsamanka@3778: dispatch_source_set_cancel_handler_f(PLC_timer, PLC_timer_cancel); kinsamanka@3778: kinsamanka@3778: if (__init(argc, argv) == 0) { kinsamanka@3778: PLC_SetTimer(common_ticktime__, common_ticktime__); kinsamanka@3778: kinsamanka@3778: /* install signal handler for manual break */ kinsamanka@3778: signal(SIGINT, catch_signal); kinsamanka@3778: } else { kinsamanka@3778: return 1; kinsamanka@3778: } kinsamanka@3778: return 0; kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: int TryEnterDebugSection(void) kinsamanka@3778: { kinsamanka@3778: if (pthread_mutex_trylock(&debug_mutex) == 0) { kinsamanka@3778: /* Only enter if debug active */ kinsamanka@3778: if (__DEBUG) { kinsamanka@3778: return 1; kinsamanka@3778: } kinsamanka@3778: pthread_mutex_unlock(&debug_mutex); kinsamanka@3778: } kinsamanka@3778: return 0; kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: void LeaveDebugSection(void) kinsamanka@3778: { kinsamanka@3778: pthread_mutex_unlock(&debug_mutex); kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: int stopPLC() kinsamanka@3778: { kinsamanka@3778: /* Stop the PLC */ kinsamanka@3778: PLC_shutdown = 1; kinsamanka@3778: sem_post(&Run_PLC); kinsamanka@3778: PLC_SetTimer(0, 0); kinsamanka@3778: pthread_join(PLC_thread, NULL); kinsamanka@3778: sem_destroy(&Run_PLC); kinsamanka@3778: dispatch_source_cancel(PLC_timer); kinsamanka@3778: __cleanup(); kinsamanka@3778: pthread_mutex_destroy(&debug_wait_mutex); kinsamanka@3778: pthread_mutex_destroy(&debug_mutex); kinsamanka@3778: pthread_mutex_destroy(&python_wait_mutex); kinsamanka@3778: pthread_mutex_destroy(&python_mutex); kinsamanka@3778: return 0; kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: extern unsigned long __tick; kinsamanka@3778: kinsamanka@3778: int WaitDebugData(unsigned long *tick) kinsamanka@3778: { kinsamanka@3778: int res; kinsamanka@3778: if (PLC_shutdown) kinsamanka@3778: return 1; kinsamanka@3778: /* Wait signal from PLC thread */ kinsamanka@3778: res = pthread_mutex_lock(&debug_wait_mutex); kinsamanka@3778: *tick = __debug_tick; kinsamanka@3778: return res; kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: /* Called by PLC thread when debug_publish finished kinsamanka@3778: * This is supposed to unlock debugger thread in WaitDebugData*/ kinsamanka@3778: void InitiateDebugTransfer() kinsamanka@3778: { kinsamanka@3778: /* remember tick */ kinsamanka@3778: __debug_tick = __tick; kinsamanka@3778: /* signal debugger thread it can read data */ kinsamanka@3778: pthread_mutex_unlock(&debug_wait_mutex); kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: int suspendDebug(int disable) kinsamanka@3778: { kinsamanka@3778: /* Prevent PLC to enter debug code */ kinsamanka@3778: pthread_mutex_lock(&debug_mutex); kinsamanka@3778: /*__DEBUG is protected by this mutex */ kinsamanka@3778: __DEBUG = !disable; kinsamanka@3778: if (disable) kinsamanka@3778: pthread_mutex_unlock(&debug_mutex); kinsamanka@3778: return 0; kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: void resumeDebug(void) kinsamanka@3778: { kinsamanka@3778: __DEBUG = 1; kinsamanka@3778: /* Let PLC enter debug code */ kinsamanka@3778: pthread_mutex_unlock(&debug_mutex); kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: /* from plc_python.c */ kinsamanka@3778: int WaitPythonCommands(void) kinsamanka@3778: { kinsamanka@3778: /* Wait signal from PLC thread */ kinsamanka@3778: return pthread_mutex_lock(&python_wait_mutex); kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: /* Called by PLC thread on each new python command*/ kinsamanka@3778: void UnBlockPythonCommands(void) kinsamanka@3778: { kinsamanka@3778: /* signal python thread it can read data */ kinsamanka@3778: pthread_mutex_unlock(&python_wait_mutex); kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: int TryLockPython(void) kinsamanka@3778: { kinsamanka@3778: return pthread_mutex_trylock(&python_mutex) == 0; kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: void UnLockPython(void) kinsamanka@3778: { kinsamanka@3778: pthread_mutex_unlock(&python_mutex); kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: void LockPython(void) kinsamanka@3778: { kinsamanka@3778: pthread_mutex_lock(&python_mutex); kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: struct RT_to_nRT_signal_s { kinsamanka@3778: pthread_cond_t WakeCond; kinsamanka@3778: pthread_mutex_t WakeCondLock; kinsamanka@3778: }; kinsamanka@3778: kinsamanka@3778: typedef struct RT_to_nRT_signal_s RT_to_nRT_signal_t; kinsamanka@3778: kinsamanka@3778: #define _LogAndReturnNull(text) \ kinsamanka@3778: {\ kinsamanka@3778: char mstr[256] = text " for ";\ kinsamanka@3778: strncat(mstr, name, 255);\ kinsamanka@3778: LogMessage(LOG_CRITICAL, mstr, strlen(mstr));\ kinsamanka@3778: return NULL;\ kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: void *create_RT_to_nRT_signal(char *name) kinsamanka@3778: { kinsamanka@3778: RT_to_nRT_signal_t *sig = kinsamanka@3778: (RT_to_nRT_signal_t *) malloc(sizeof(RT_to_nRT_signal_t)); kinsamanka@3778: kinsamanka@3778: if (!sig) kinsamanka@3778: _LogAndReturnNull("Failed allocating memory for RT_to_nRT signal"); kinsamanka@3778: kinsamanka@3778: pthread_cond_init(&sig->WakeCond, NULL); kinsamanka@3778: pthread_mutex_init(&sig->WakeCondLock, NULL); kinsamanka@3778: kinsamanka@3778: return (void *)sig; kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: void delete_RT_to_nRT_signal(void *handle) kinsamanka@3778: { kinsamanka@3778: RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t *) handle; kinsamanka@3778: kinsamanka@3778: pthread_cond_destroy(&sig->WakeCond); kinsamanka@3778: pthread_mutex_destroy(&sig->WakeCondLock); kinsamanka@3778: kinsamanka@3778: free(sig); kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: int wait_RT_to_nRT_signal(void *handle) kinsamanka@3778: { kinsamanka@3778: int ret; kinsamanka@3778: RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t *) handle; kinsamanka@3778: pthread_mutex_lock(&sig->WakeCondLock); kinsamanka@3778: ret = pthread_cond_wait(&sig->WakeCond, &sig->WakeCondLock); kinsamanka@3778: pthread_mutex_unlock(&sig->WakeCondLock); kinsamanka@3778: return ret; kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: int unblock_RT_to_nRT_signal(void *handle) kinsamanka@3778: { kinsamanka@3778: RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t *) handle; kinsamanka@3778: return pthread_cond_signal(&sig->WakeCond); kinsamanka@3778: } kinsamanka@3778: kinsamanka@3778: void nRT_reschedule(void) kinsamanka@3778: { kinsamanka@3778: sched_yield(); kinsamanka@3778: }