high res timer ?

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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++) {
            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();
            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/


[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux