I still think that your problems can be solved at the application level quite easily. Just out of curiosity, I wrote a little test program, below, and I think it shows a promising direction to solve your issue. (The 'clk_cmp' function was taken from the userland servo in the phc2sys program, from the linuxptp project.) I am not sure what your application wants to do if it should notice a jump in CLOCK_REALTIME: keep the old phase angle or re-align to the new UTC second. My test program does not shift its phase, but I think you would know how to do it. Running on my dinky atom netbook (32 bit, no vdso, no RT) in an unscientific test, I see the value of 'expected - offset' typically around a few hundred nanoseconds, with occasional outliers of a few microseconds. With RT-PREMPT these could surely be avoided, or by using a moving average of say, 10 readings. Also, rather than jumping to the new phase angle (if that is what you want in fact to do), you could smoothly ajust the loop phase using a PI controller or similar. Anyhow, here it is. What do you think? Thanks, Richard --- #include <errno.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <time.h> #include <unistd.h> #include <inttypes.h> #define NS_PER_SEC 1000000000LL static int clk_cmp(clockid_t clkid, clockid_t sysclk, int readings, int64_t *offset, uint64_t *ts) { struct timespec tdst1, tdst2, tsrc; int i; int64_t interval, best_interval = INT64_MAX; /* Pick the quickest clkid reading. */ for (i = 0; i < readings; i++) { if (clock_gettime(sysclk, &tdst1) || clock_gettime(clkid, &tsrc) || clock_gettime(sysclk, &tdst2)) { perror("clock_gettime"); return -1; } interval = (tdst2.tv_sec - tdst1.tv_sec) * NS_PER_SEC + tdst2.tv_nsec - tdst1.tv_nsec; if (best_interval > interval) { best_interval = interval; *offset = (tdst1.tv_sec - tsrc.tv_sec) * NS_PER_SEC + tdst1.tv_nsec - tsrc.tv_nsec + interval / 2; *ts = tdst2.tv_sec * NS_PER_SEC + tdst2.tv_nsec; } } return 0; } int main(int argc, char *argv[]) { int64_t expected, offset; uint64_t systs; struct timespec next; struct timespec incr = { 0, 250000000 }; clockid_t clk = CLOCK_MONOTONIC; int n_readings = 1; /* * Calibrate the offset. */ if (clk_cmp(clk, CLOCK_REALTIME, 25, &expected, &systs)) { return -1; } if (clock_gettime(clk, &next)) { perror("clock_gettime"); return -1; } next.tv_sec++; while (1) { if (clock_nanosleep(clk, TIMER_ABSTIME, &next, NULL)) { perror("clock_nanosleep"); break; } if (clk_cmp(clk, CLOCK_REALTIME, n_readings, &offset, &systs)) { break; } printf("%" PRId64 "\n", expected - offset); /* * At this point, if the difference is more than, say, * 10 microseconds, then you could simply recalibrate * the offset and set the next deadline. */ next.tv_sec += incr.tv_sec; next.tv_nsec += incr.tv_nsec; while (next.tv_nsec >= NS_PER_SEC) { next.tv_nsec -= NS_PER_SEC; next.tv_sec++; } } return 0; } -- To unsubscribe from this list: send the line "unsubscribe linux-rt-users" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html