277 mb_slave_run(server_node->mb_nd /* nd */, callbacks, server_node->slave_id); |
277 mb_slave_run(server_node->mb_nd /* nd */, callbacks, server_node->slave_id); |
278 fprintf(stderr, "Modbus plugin: Modbus server for node %%s died unexpectedly!\n", server_node->location); /* should never occur */ |
278 fprintf(stderr, "Modbus plugin: Modbus server for node %%s died unexpectedly!\n", server_node->location); /* should never occur */ |
279 return NULL; |
279 return NULL; |
280 } |
280 } |
281 |
281 |
|
282 |
|
283 #define timespec_add(ts, sec, nsec) { \ |
|
284 ts.tv_sec += sec; \ |
|
285 ts.tv_nsec += nsec; \ |
|
286 if (ts.tv_nsec >= 1000000000) { \ |
|
287 ts.tv_sec ++; \ |
|
288 ts.tv_nsec -= 1000000000; \ |
|
289 } \ |
|
290 } |
282 |
291 |
283 |
292 |
284 static void *__mb_client_thread(void *_index) { |
293 static void *__mb_client_thread(void *_index) { |
285 int client_node_id = (char *)_index - (char *)NULL; // Use pointer arithmetic (more portable than cast) |
294 int client_node_id = (char *)_index - (char *)NULL; // Use pointer arithmetic (more portable than cast) |
286 struct timespec next_cycle; |
295 struct timespec next_cycle; |
348 break; |
357 break; |
349 } |
358 } |
350 } |
359 } |
351 } |
360 } |
352 // Determine absolute time instant for starting the next cycle |
361 // Determine absolute time instant for starting the next cycle |
353 // struct timespec prev_cycle; |
362 struct timespec prev_cycle, now; |
354 // prev_cycle = next_cycle; |
363 prev_cycle = next_cycle; |
355 next_cycle.tv_sec += period_sec; |
364 timespec_add(next_cycle, period_sec, period_nsec); |
356 next_cycle.tv_nsec += period_nsec; |
365 /* NOTE A: |
357 if (next_cycle.tv_nsec >= 1000000000) { |
366 * When we have difficulty communicating with remote client and/or server, then the communications get delayed and we will |
358 next_cycle.tv_sec ++; |
367 * fall behind in the period. This means that when communication is re-established we may end up running this loop continuously |
359 next_cycle.tv_nsec -= 1000000000; |
368 * for some time until we catch up. |
360 } |
369 * This is undesirable, so we detect it by making sure the next_cycle will start in the future. |
361 /* It probably does not make sense to check for overflow of timer. |
370 * When this happens we will switch from a purely periodic task _activation_ sequence, to a fixed task suspension interval. |
|
371 * |
|
372 * NOTE B: |
|
373 * It probably does not make sense to check for overflow of timer. |
362 * Even in 32 bit systems this will take at least 68 years since the computer booted |
374 * Even in 32 bit systems this will take at least 68 years since the computer booted |
363 * (remember, we are using CLOCK_MONOTONIC, which should start counting from 0 |
375 * (remember, we are using CLOCK_MONOTONIC, which should start counting from 0 |
364 * every time the system boots). On 64 bit systems, it will take over |
376 * every time the system boots). On 64 bit systems, it will take over |
365 * 10^11 years to overflow. |
377 * 10^11 years to overflow. |
366 */ |
378 */ |
367 /* |
379 clock_gettime(CLOCK_MONOTONIC, &now); |
368 if (next_cycle.tv_sec) < prev_cycle.tv_sec) { |
380 if ( ((now.tv_sec > next_cycle.tv_sec) || ((now.tv_sec == next_cycle.tv_sec) && (now.tv_nsec > next_cycle.tv_nsec))) |
369 // we will lose some precision by reading the time again, |
381 /* We are falling behind. See NOTE A above */ |
370 // but it is better than the alternative... |
382 || (next_cycle.tv_sec < prev_cycle.tv_sec) |
371 clock_gettime(CLOCK_MONOTONIC, &next_cycle); |
383 /* Timer overflow. See NOTE B above */ |
372 next_cycle.tv_sec += period_sec; |
384 ) { |
373 next_cycle.tv_nsec += period_nsec; |
385 next_cycle = now; |
374 if (next_cycle.tv_nsec >= 1000000000) { |
386 timespec_add(next_cycle, period_sec, period_nsec); |
375 next_cycle.tv_sec ++; |
387 } |
376 next_cycle.tv_nsec -= 1000000000; |
|
377 } |
|
378 } |
|
379 */ |
|
380 clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next_cycle, NULL); |
388 clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next_cycle, NULL); |
381 } |
389 } |
382 |
390 |
383 // humour the compiler. |
391 // humour the compiler. |
384 return NULL; |
392 return NULL; |