targets/OSX/plc_OSX_main.c
branchpython3
changeset 3778 296e459efdfb
child 3781 25195da82745
equal deleted inserted replaced
3777:a26453d1c54d 3778:296e459efdfb
       
     1 /**
       
     2  * Mac OSX specific code
       
     3  **/
       
     4 
       
     5 #include <stdio.h>
       
     6 #include <string.h>
       
     7 #include <time.h>
       
     8 #include <signal.h>
       
     9 #include <stdlib.h>
       
    10 #include <pthread.h>
       
    11 #include <locale.h>
       
    12 #include <semaphore.h>
       
    13 #include <dispatch/dispatch.h>
       
    14 
       
    15 static sem_t Run_PLC;
       
    16 
       
    17 long AtomicCompareExchange(long *atomicvar, long compared, long exchange)
       
    18 {
       
    19     return __sync_val_compare_and_swap(atomicvar, compared, exchange);
       
    20 }
       
    21 
       
    22 long long AtomicCompareExchange64(long long *atomicvar, long long compared,
       
    23                                   long long exchange)
       
    24 {
       
    25     return __sync_val_compare_and_swap(atomicvar, compared, exchange);
       
    26 }
       
    27 
       
    28 void PLC_GetTime(IEC_TIME * CURRENT_TIME)
       
    29 {
       
    30     struct timespec tmp;
       
    31     clock_gettime(CLOCK_REALTIME, &tmp);
       
    32     CURRENT_TIME->tv_sec = tmp.tv_sec;
       
    33     CURRENT_TIME->tv_nsec = tmp.tv_nsec;
       
    34 }
       
    35 
       
    36 dispatch_queue_t queue;
       
    37 dispatch_source_t PLC_timer;
       
    38 
       
    39 static inline void PLC_timer_cancel(void *arg)
       
    40 {
       
    41     dispatch_release(PLC_timer);
       
    42     dispatch_release(queue);
       
    43     exit(0);
       
    44 }
       
    45 
       
    46 static inline void PLC_timer_notify(void *arg)
       
    47 {
       
    48     PLC_GetTime(&__CURRENT_TIME);
       
    49     sem_post(&Run_PLC);
       
    50 }
       
    51 
       
    52 void PLC_SetTimer(unsigned long long next, unsigned long long period)
       
    53 {
       
    54     if (next == period && next == 0) {
       
    55         dispatch_suspend(PLC_timer);
       
    56     } else {
       
    57         dispatch_time_t start;
       
    58         start = dispatch_time(DISPATCH_TIME_NOW, next);
       
    59         dispatch_source_set_timer(PLC_timer, start, period, 0);
       
    60         dispatch_resume(PLC_timer);
       
    61     }
       
    62 }
       
    63 
       
    64 void catch_signal(int sig)
       
    65 {
       
    66     signal(SIGINT, catch_signal);
       
    67     printf("Got Signal %d\n", sig);
       
    68     dispatch_source_cancel(PLC_timer);
       
    69     exit(0);
       
    70 }
       
    71 
       
    72 static unsigned long __debug_tick;
       
    73 
       
    74 pthread_t PLC_thread;
       
    75 static pthread_mutex_t python_wait_mutex = PTHREAD_MUTEX_INITIALIZER;
       
    76 static pthread_mutex_t python_mutex = PTHREAD_MUTEX_INITIALIZER;
       
    77 static pthread_mutex_t debug_wait_mutex = PTHREAD_MUTEX_INITIALIZER;
       
    78 static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
       
    79 
       
    80 int PLC_shutdown = 0;
       
    81 
       
    82 int ForceSaveRetainReq(void)
       
    83 {
       
    84     return PLC_shutdown;
       
    85 }
       
    86 
       
    87 void PLC_thread_proc(void *arg)
       
    88 {
       
    89     while (!PLC_shutdown) {
       
    90         sem_wait(&Run_PLC);
       
    91         __run();
       
    92     }
       
    93     pthread_exit(0);
       
    94 }
       
    95 
       
    96 #define maxval(a,b) ((a>b)?a:b)
       
    97 int startPLC(int argc, char **argv)
       
    98 {
       
    99     setlocale(LC_NUMERIC, "C");
       
   100 
       
   101     PLC_shutdown = 0;
       
   102 
       
   103     sem_init(&Run_PLC, 0, 0);
       
   104 
       
   105     pthread_create(&PLC_thread, NULL, (void *)&PLC_thread_proc, NULL);
       
   106 
       
   107     pthread_mutex_init(&debug_wait_mutex, NULL);
       
   108     pthread_mutex_init(&debug_mutex, NULL);
       
   109     pthread_mutex_init(&python_wait_mutex, NULL);
       
   110     pthread_mutex_init(&python_mutex, NULL);
       
   111 
       
   112     pthread_mutex_lock(&debug_wait_mutex);
       
   113     pthread_mutex_lock(&python_wait_mutex);
       
   114 
       
   115     queue = dispatch_queue_create("timerQueue", 0);
       
   116     PLC_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
       
   117 
       
   118     dispatch_set_context(PLC_timer, &PLC_timer);
       
   119     dispatch_source_set_event_handler_f(PLC_timer, PLC_timer_notify);
       
   120     dispatch_source_set_cancel_handler_f(PLC_timer, PLC_timer_cancel);
       
   121 
       
   122     if (__init(argc, argv) == 0) {
       
   123         PLC_SetTimer(common_ticktime__, common_ticktime__);
       
   124 
       
   125         /* install signal handler for manual break */
       
   126         signal(SIGINT, catch_signal);
       
   127     } else {
       
   128         return 1;
       
   129     }
       
   130     return 0;
       
   131 }
       
   132 
       
   133 int TryEnterDebugSection(void)
       
   134 {
       
   135     if (pthread_mutex_trylock(&debug_mutex) == 0) {
       
   136         /* Only enter if debug active */
       
   137         if (__DEBUG) {
       
   138             return 1;
       
   139         }
       
   140         pthread_mutex_unlock(&debug_mutex);
       
   141     }
       
   142     return 0;
       
   143 }
       
   144 
       
   145 void LeaveDebugSection(void)
       
   146 {
       
   147     pthread_mutex_unlock(&debug_mutex);
       
   148 }
       
   149 
       
   150 int stopPLC()
       
   151 {
       
   152     /* Stop the PLC */
       
   153     PLC_shutdown = 1;
       
   154     sem_post(&Run_PLC);
       
   155     PLC_SetTimer(0, 0);
       
   156     pthread_join(PLC_thread, NULL);
       
   157     sem_destroy(&Run_PLC);
       
   158     dispatch_source_cancel(PLC_timer);
       
   159     __cleanup();
       
   160     pthread_mutex_destroy(&debug_wait_mutex);
       
   161     pthread_mutex_destroy(&debug_mutex);
       
   162     pthread_mutex_destroy(&python_wait_mutex);
       
   163     pthread_mutex_destroy(&python_mutex);
       
   164     return 0;
       
   165 }
       
   166 
       
   167 extern unsigned long __tick;
       
   168 
       
   169 int WaitDebugData(unsigned long *tick)
       
   170 {
       
   171     int res;
       
   172     if (PLC_shutdown)
       
   173         return 1;
       
   174     /* Wait signal from PLC thread */
       
   175     res = pthread_mutex_lock(&debug_wait_mutex);
       
   176     *tick = __debug_tick;
       
   177     return res;
       
   178 }
       
   179 
       
   180 /* Called by PLC thread when debug_publish finished
       
   181  * This is supposed to unlock debugger thread in WaitDebugData*/
       
   182 void InitiateDebugTransfer()
       
   183 {
       
   184     /* remember tick */
       
   185     __debug_tick = __tick;
       
   186     /* signal debugger thread it can read data */
       
   187     pthread_mutex_unlock(&debug_wait_mutex);
       
   188 }
       
   189 
       
   190 int suspendDebug(int disable)
       
   191 {
       
   192     /* Prevent PLC to enter debug code */
       
   193     pthread_mutex_lock(&debug_mutex);
       
   194     /*__DEBUG is protected by this mutex */
       
   195     __DEBUG = !disable;
       
   196     if (disable)
       
   197         pthread_mutex_unlock(&debug_mutex);
       
   198     return 0;
       
   199 }
       
   200 
       
   201 void resumeDebug(void)
       
   202 {
       
   203     __DEBUG = 1;
       
   204     /* Let PLC enter debug code */
       
   205     pthread_mutex_unlock(&debug_mutex);
       
   206 }
       
   207 
       
   208 /* from plc_python.c */
       
   209 int WaitPythonCommands(void)
       
   210 {
       
   211     /* Wait signal from PLC thread */
       
   212     return pthread_mutex_lock(&python_wait_mutex);
       
   213 }
       
   214 
       
   215 /* Called by PLC thread on each new python command*/
       
   216 void UnBlockPythonCommands(void)
       
   217 {
       
   218     /* signal python thread it can read data */
       
   219     pthread_mutex_unlock(&python_wait_mutex);
       
   220 }
       
   221 
       
   222 int TryLockPython(void)
       
   223 {
       
   224     return pthread_mutex_trylock(&python_mutex) == 0;
       
   225 }
       
   226 
       
   227 void UnLockPython(void)
       
   228 {
       
   229     pthread_mutex_unlock(&python_mutex);
       
   230 }
       
   231 
       
   232 void LockPython(void)
       
   233 {
       
   234     pthread_mutex_lock(&python_mutex);
       
   235 }
       
   236 
       
   237 struct RT_to_nRT_signal_s {
       
   238     pthread_cond_t WakeCond;
       
   239     pthread_mutex_t WakeCondLock;
       
   240 };
       
   241 
       
   242 typedef struct RT_to_nRT_signal_s RT_to_nRT_signal_t;
       
   243 
       
   244 #define _LogAndReturnNull(text) \
       
   245     {\
       
   246     	char mstr[256] = text " for ";\
       
   247         strncat(mstr, name, 255);\
       
   248         LogMessage(LOG_CRITICAL, mstr, strlen(mstr));\
       
   249         return NULL;\
       
   250     }
       
   251 
       
   252 void *create_RT_to_nRT_signal(char *name)
       
   253 {
       
   254     RT_to_nRT_signal_t *sig =
       
   255         (RT_to_nRT_signal_t *) malloc(sizeof(RT_to_nRT_signal_t));
       
   256 
       
   257     if (!sig)
       
   258         _LogAndReturnNull("Failed allocating memory for RT_to_nRT signal");
       
   259 
       
   260     pthread_cond_init(&sig->WakeCond, NULL);
       
   261     pthread_mutex_init(&sig->WakeCondLock, NULL);
       
   262 
       
   263     return (void *)sig;
       
   264 }
       
   265 
       
   266 void delete_RT_to_nRT_signal(void *handle)
       
   267 {
       
   268     RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t *) handle;
       
   269 
       
   270     pthread_cond_destroy(&sig->WakeCond);
       
   271     pthread_mutex_destroy(&sig->WakeCondLock);
       
   272 
       
   273     free(sig);
       
   274 }
       
   275 
       
   276 int wait_RT_to_nRT_signal(void *handle)
       
   277 {
       
   278     int ret;
       
   279     RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t *) handle;
       
   280     pthread_mutex_lock(&sig->WakeCondLock);
       
   281     ret = pthread_cond_wait(&sig->WakeCond, &sig->WakeCondLock);
       
   282     pthread_mutex_unlock(&sig->WakeCondLock);
       
   283     return ret;
       
   284 }
       
   285 
       
   286 int unblock_RT_to_nRT_signal(void *handle)
       
   287 {
       
   288     RT_to_nRT_signal_t *sig = (RT_to_nRT_signal_t *) handle;
       
   289     return pthread_cond_signal(&sig->WakeCond);
       
   290 }
       
   291 
       
   292 void nRT_reschedule(void)
       
   293 {
       
   294     sched_yield();
       
   295 }