Mark Hounschell wrote: > Before asking this on the lkml and waisting peoples time I thought I > would seek advice here first. I am experimenting with Ingo Molnars rt > patch which among other things, includes high res timer support. I'm not > having a problems with the timers them selves but am seeing an anomaly > with clock_nanosleep. It seems to return early. I have a short sample > program that shows the anomaly. Could someone tell me if I am crazy, > just plain wrong, or maybe even right? I am running the 2.6.16-rt23 > patch and have the userland high-res timers hooks in place. The > following program shows early returns on every 2.6.16-rt23 box I have > tried it on. I don't want to bother the developers if my program is > broken so if anyone can advise I would appreciate it. > > Thanks and regards > Mark > > To build this: > > cc hr_nsleep.c -o hr_nsleep -lposix-time > > > #include <stdlib.h> > #include <stdint.h> > #include <stdio.h> > #include <posix_time.h> > > int64_t get_nsec_64(); > > #define MAX_FAILURES 50 > > int main() > { > int64_t start_nsecs; > int64_t elapsed_nsecs; > int64_t latency_nsecs; > int32_t i, x; > int32_t failures = 0; > struct timespec tim; > > int64_t failed_elapsed_nsecs[MAX_FAILURES]; > int64_t failed_latency_nsecs[MAX_FAILURES]; > struct timespec failed_sleeps[MAX_FAILURES]; > > struct timespec sleep[16] = { > {0, 10 * 1000}, > {0, 20 * 1000}, > {0, 40 * 1000}, > {0, 80 * 1000}, > {0, 100 * 1000}, > {0, 200 * 1000}, > {0, 400 * 1000}, > {0, 800 * 1000}, > {0, 1000 * 1000}, > {0, 2000 * 1000}, > {0, 4000 * 1000}, > {0, 8000 * 1000}, > {0, 10000 * 1000}, > {0, 20000 * 1000}, > {0, 40000 * 1000}, > {0, 80000 * 1000}, > }; > > for (x = 0; x < 10000; x++) { > for (i = 0; i < 16; i++) { Its because of the time it takes to get from here > clock_gettime(CLOCK_MONOTONIC, &tim); > tim.tv_sec += sleep[i].tv_sec; > tim.tv_nsec += sleep[i].tv_nsec; > if (tim.tv_nsec > 1000000000) { > tim.tv_sec++; > tim.tv_nsec -= 1000000000; > } > start_nsecs = get_nsec_64(); to here in conjunction with the use of the TIMER_ABSTIME flag. > while (clock_nanosleep(CLOCK_MONOTONIC, > TIMER_ABSTIME, > &tim, NULL) && errno == EINTR); > elapsed_nsecs = (get_nsec_64() - start_nsecs); > latency_nsecs = > (elapsed_nsecs - > (int64_t)(sleep[i].tv_nsec)); > if (latency_nsecs <= 0) { > failed_elapsed_nsecs[failures] = elapsed_nsecs; > failed_latency_nsecs[failures] = latency_nsecs; > failed_sleeps[failures] = sleep[i]; > failures++; > } > if (failures >= MAX_FAILURES) break; > } > if (failures >= MAX_FAILURES) break; > } > for (i = 0; i < failures; i++) { > printf("\nAttempted sleep of %8d nsecs.\n" \ > "Actual sleep %8lld nsecs. BAD %8lld nsecs\n", > (int32_t) failed_sleeps[i].tv_nsec, > failed_elapsed_nsecs[i], failed_latency_nsecs[i]); > } > exit(0); > } > > int64_t get_nsec_64() > { > int64_t ret; > struct timespec ts; > > clock_gettime(CLOCK_MONOTONIC, &ts); > ret = (int64_t) (((int64_t) ts.tv_sec * 1000000000) + > (int64_t) ts.tv_nsec); > return (ret); > } > > -- Kernelnewbies: Help each other learn about the Linux kernel. Archive: http://mail.nl.linux.org/kernelnewbies/ FAQ: http://kernelnewbies.org/faq/