modbus/mb_runtime.c
changeset 2684 da8de4ef0449
parent 2683 5d8a4deacfe1
child 2685 f71c22b2ca25
equal deleted inserted replaced
2683:5d8a4deacfe1 2684:da8de4ef0449
   293 }
   293 }
   294 
   294 
   295 
   295 
   296 static void *__mb_client_thread(void *_index)  {
   296 static void *__mb_client_thread(void *_index)  {
   297 	int client_node_id = (char *)_index - (char *)NULL; // Use pointer arithmetic (more portable than cast)
   297 	int client_node_id = (char *)_index - (char *)NULL; // Use pointer arithmetic (more portable than cast)
   298 	struct timespec next_cycle;
       
   299 	int period_sec  =  client_nodes[client_node_id].comm_period / 1000;          /* comm_period is in ms */
       
   300 	int period_nsec = (client_nodes[client_node_id].comm_period %%1000)*1000000; /* comm_period is in ms */
       
   301 
   298 
   302 	// Enable thread cancelation. Enabled is default, but set it anyway to be safe.
   299 	// Enable thread cancelation. Enabled is default, but set it anyway to be safe.
   303 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
   300 	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
   304 	
   301 	
   305 	// configure the timer for periodic activation
       
   306     {
       
   307       struct itimerspec timerspec;
       
   308       timerspec.it_interval.tv_sec  = period_sec;
       
   309       timerspec.it_interval.tv_nsec = period_nsec;
       
   310       timerspec.it_value            = timerspec.it_interval;
       
   311       
       
   312       if (timer_settime(client_nodes[client_node_id].timer_id, 0 /* flags */, &timerspec, NULL) < 0)
       
   313         fprintf(stderr, "Modbus plugin: Error configuring periodic activation timer for Modbus client %%s.\n", client_nodes[client_node_id].location);          
       
   314     }
       
   315 
       
   316     /* loop the communication with the client
   302     /* loop the communication with the client
   317      * 
   303      * 
   318          * When the client thread has difficulty communicating with remote client and/or server (network issues, for example),
   304          * When the client thread has difficulty communicating with remote client and/or server (network issues, for example),
   319          * then the communications get delayed and we will fall behind in the period. 
   305          * then the communications get delayed and we will fall behind in the period. 
   320          * 
   306          * 
   490 
   476 
   491 
   477 
   492 static int stop_mb_client_timer_thread;
   478 static int stop_mb_client_timer_thread;
   493 static void *__mb_client_timer_thread(void *_index) {
   479 static void *__mb_client_timer_thread(void *_index) {
   494     sigset_t set;
   480     sigset_t set;
   495     int signum = SIGALRM;
   481     int signum;
       
   482     sigemptyset(&set);
       
   483     sigaddset(&set, SIGALRM);
       
   484 
   496 	int client_node_id = (char *)_index - (char *)NULL; // Use pointer arithmetic (more portable than cast)
   485 	int client_node_id = (char *)_index - (char *)NULL; // Use pointer arithmetic (more portable than cast)
   497     printf("%%d\n", client_node_id);
   486     printf("%%d\n", client_node_id);
   498     /* initialize the timer that will be used to periodically activate the client node */
   487     /* initialize the timer that will be used to periodically activate the client node */
   499     {
   488     {
   500         // start off by reseting the flag that will be set whenever the timer expires
   489         // start off by reseting the flag that will be set whenever the timer expires
   501         client_nodes[client_node_id].periodic_act = 0;
   490         client_nodes[client_node_id].periodic_act = 0;
   502 
   491 
   503         struct sigevent evp = {0};
   492         if (timer_create(CLOCK_REALTIME, NULL, &(client_nodes[client_node_id].timer_id)) < 0) {
   504         evp.sigev_notify            = SIGEV_THREAD_ID; /* Notification method - call a function in a new thread context */
       
   505         evp.sigev_signo             = SIGALRM;
       
   506         evp.sigev_value.sival_int   = client_node_id;        /* Data passed to function upon notification - used to indentify which client node to activate */
       
   507        
       
   508         if (timer_create(CLOCK_MONOTONIC, &evp, &(client_nodes[client_node_id].timer_id)) < 0) {
       
   509             fprintf(stderr, "Modbus plugin: Error (%%s) creating timer for modbus client node %%s\n", strerror(errno), client_nodes[client_node_id].location);
   493             fprintf(stderr, "Modbus plugin: Error (%%s) creating timer for modbus client node %%s\n", strerror(errno), client_nodes[client_node_id].location);
   510             return NULL;
   494             return NULL;
   511         }
   495         }
   512     }
   496     }
   513 
   497 
       
   498 	int period_sec  =  client_nodes[client_node_id].comm_period / 1000;          /* comm_period is in ms */
       
   499 	int period_nsec = (client_nodes[client_node_id].comm_period %%1000)*1000000; /* comm_period is in ms */
       
   500 
       
   501 	// configure the timer for periodic activation
       
   502     {
       
   503       struct itimerspec timerspec;
       
   504       timerspec.it_interval.tv_sec  = period_sec;
       
   505       timerspec.it_interval.tv_nsec = period_nsec;
       
   506       timerspec.it_value            = timerspec.it_interval;
       
   507       
       
   508       if (timer_settime(client_nodes[client_node_id].timer_id, 0 /* flags */, &timerspec, NULL) < 0)
       
   509         fprintf(stderr, "Modbus plugin: Error configuring periodic activation timer for Modbus client %%s.\n", client_nodes[client_node_id].location);          
       
   510     }
       
   511 
   514     stop_mb_client_timer_thread = 0;
   512     stop_mb_client_timer_thread = 0;
   515     while(!stop_mb_client_timer_thread) {
   513     while(!stop_mb_client_timer_thread) {
   516         if(sigwait (&set, &signum) == -1)
   514         if(sigwait (&set, &signum) == -1)
   517             perror ("sigwait");
   515             perror ("sigwait");
       
   516 
   518         if(stop_mb_client_timer_thread)
   517         if(stop_mb_client_timer_thread)
   519             break;
   518             break;
   520         __client_node_timer_callback_function(client_node_id);
   519 
       
   520         if(signum == SIGALRM)
       
   521             __client_node_timer_callback_function(client_node_id);
       
   522         else
       
   523             fprintf(stderr, "Modbus plugin: spurious wakeup of timer thread for Modbus client %%s.\n", client_nodes[client_node_id].location);          
       
   524 
   521     }
   525     }
   522 
   526 
   523     // timer was created, so we try to destroy it!
   527     // timer was created, so we try to destroy it!
   524     int res = timer_delete(client_nodes[client_node_id].timer_id);
   528     int res = timer_delete(client_nodes[client_node_id].timer_id);
   525     if (res < 0)
   529     if (res < 0)
   789 
   793 
   790 		close = 0;
   794 		close = 0;
   791 		if (client_nodes[index].init_state >= 4) {
   795 		if (client_nodes[index].init_state >= 4) {
   792             stop_mb_client_timer_thread = 1;
   796             stop_mb_client_timer_thread = 1;
   793             pthread_kill(client_nodes[index].timer_thread_id, SIGALRM);
   797             pthread_kill(client_nodes[index].timer_thread_id, SIGALRM);
   794 			// thread was launched, so we try to cancel it!
       
   795 			close  = pthread_cancel(client_nodes[index].timer_thread_id);
       
   796 			close |= pthread_join  (client_nodes[index].timer_thread_id, NULL);
   798 			close |= pthread_join  (client_nodes[index].timer_thread_id, NULL);
   797 			if (close < 0)
   799 			if (close < 0)
   798 				fprintf(stderr, "Modbus plugin: Error closing timer thread for modbus client node %%s\n", client_nodes[index].location);
   800 				fprintf(stderr, "Modbus plugin: Error closing timer thread for modbus client node %%s\n", client_nodes[index].location);
   799 
   801 
   800 		}
   802 		}