latency.c

来自「xenomai 很好的linux实时补丁」· C语言 代码 · 共 592 行 · 第 1/2 页

C
592
字号
#include <sys/mman.h>#include <sys/time.h>#include <unistd.h>#include <stdlib.h>#include <math.h>#include <stdio.h>#include <string.h>#include <signal.h>#include <getopt.h>#include <time.h>#include <native/task.h>#include <native/timer.h>#include <native/sem.h>#include <rtdm/rtbenchmark.h>RT_TASK latency_task, display_task;RT_SEM display_sem;#define ONE_BILLION  1000000000#define TEN_MILLION    10000000long minjitter, maxjitter, avgjitter;long gminjitter = TEN_MILLION,    gmaxjitter = -TEN_MILLION,    gavgjitter = 0,    goverrun = 0;long long period_ns = 0;int test_duration = 0;  /* sec of testing, via -T <sec>, 0 is inf */int data_lines = 21;    /* data lines per header line, -l <lines> to change */int quiet = 0;          /* suppress printing of RTH, RTD lines when -T given */int benchdev_no = 0;int benchdev = -1;int freeze_max = 0;#define USER_TASK       0#define KERNEL_TASK     1#define TIMER_HANDLER   2int test_mode = USER_TASK;const char *test_mode_names[] = {    "periodic user-mode task",    "in-kernel periodic task",    "in-kernel timer handler"};time_t test_start, test_end;    /* report test duration */int test_loops = 0;             /* outer loop count */#define MEASURE_PERIOD ONE_BILLION#define SAMPLE_COUNT (MEASURE_PERIOD / period_ns)/* Warmup time : in order to avoid spurious cache effects on low-end machines. */#define WARMUP_TIME 1#define HISTOGRAM_CELLS 100int histogram_size = HISTOGRAM_CELLS;long *histogram_avg = NULL,     *histogram_max = NULL,     *histogram_min = NULL;int do_histogram = 0, do_stats = 0, finished = 0;int bucketsize = 1000;  /* default = 1000ns, -B <size> to override */static inline void add_histogram (long *histogram, long addval){    /* bucketsize steps */    long inabs = rt_timer_tsc2ns(addval >= 0 ? addval : -addval) / bucketsize;    histogram[inabs < histogram_size ? inabs : histogram_size-1]++;}void latency (void *cookie){    int err, count, nsamples, warmup = 1;    RTIME expected_tsc, period_tsc, start_ticks;    RT_TIMER_INFO timer_info;    err = rt_timer_inquire(&timer_info);        if (err)        {        fprintf(stderr,"latency: rt_timer_inquire, code %d\n",err);        return;        }    nsamples = ONE_BILLION / period_ns;    period_tsc = rt_timer_ns2tsc(period_ns);    /* start time: one millisecond from now. */    start_ticks = timer_info.date + rt_timer_ns2ticks(1000000);    expected_tsc = timer_info.tsc + rt_timer_ns2tsc(1000000);    err = rt_task_set_periodic(NULL,start_ticks,rt_timer_ns2ticks(period_ns));    if (err)        {        fprintf(stderr,"latency: failed to set periodic, code %d\n",err);        return;        }    for (;;)        {        long minj = TEN_MILLION, maxj = -TEN_MILLION, dt, sumj;        long overrun = 0;        test_loops++;        for (count = sumj = 0; count < nsamples; count++)            {	    unsigned long ov;            expected_tsc += period_tsc;            err = rt_task_wait_period(&ov);            if (err)                {                if (err != -ETIMEDOUT)		    {		    fprintf(stderr,"latency: wait period failed, code %d\n",err);                    rt_task_delete(NULL); /* Timer stopped. */		    }                overrun += ov;                }            dt = (long)(rt_timer_tsc() - expected_tsc);            if (dt > maxj) maxj = dt;            if (dt < minj) minj = dt;            sumj += dt;            if (freeze_max && (dt > gmaxjitter) && !(finished || warmup))                {                rt_dev_ioctl(benchdev, RTBNCH_RTIOC_REFREEZE_TRACE,                             rt_timer_tsc2ns(dt));                gmaxjitter = dt;                }            if (!(finished || warmup) && (do_histogram || do_stats))                add_histogram(histogram_avg, dt);            }        if(!warmup)            {            if (!finished && (do_histogram || do_stats))                {                add_histogram(histogram_max, maxj);                add_histogram(histogram_min, minj);                }            minjitter = minj;            if(minj < gminjitter)                gminjitter = minj;            maxjitter = maxj;            if(maxj > gmaxjitter)                gmaxjitter = maxj;            avgjitter = sumj / nsamples;            gavgjitter += avgjitter;            goverrun += overrun;            rt_sem_v(&display_sem);            }        if(warmup && test_loops == WARMUP_TIME)            {            test_loops = 0;            warmup = 0;            }        }}void display (void *cookie){    int err, n = 0;    time_t start;    if (test_mode == USER_TASK) {        err = rt_sem_create(&display_sem,"dispsem",0,S_FIFO);        if (err)            {            fprintf(stderr,"latency: cannot create semaphore: %s\n",strerror(-err));            return;            }    } else {        struct rtbnch_timerconfig   config;        if (test_mode == KERNEL_TASK)            config.mode = RTBNCH_TIMER_TASK;        else            config.mode = RTBNCH_TIMER_HANDLER;        config.period               = period_ns;        config.warmup_loops         = WARMUP_TIME;        config.histogram_size       = (do_histogram || do_stats) ? histogram_size : 0;        config.histogram_bucketsize = bucketsize;        config.freeze_max           = freeze_max;        err = rt_dev_ioctl(benchdev, RTBNCH_RTIOC_START_TMTEST, &config);        if (err)            {            fprintf(stderr,"latency: failed to start in-kernel timer benchmark, code %d\n",err);            return;            }    }    time(&start);    if (WARMUP_TIME)        printf("warming up...\n");    if (quiet)        fprintf(stderr, "running quietly for %d seconds\n", test_duration);    for (;;)        {        long minj, gminj, maxj, gmaxj, avgj;        if (test_mode == USER_TASK) {            err = rt_sem_p(&display_sem,TM_INFINITE);            if (err)                {                if (err != -EIDRM)                    fprintf(stderr,"latency: failed to pend on semaphore, code %d\n",err);                return;                }            /* convert jitters to nanoseconds. */            minj = rt_timer_tsc2ns(minjitter);            gminj = rt_timer_tsc2ns(gminjitter);            avgj = rt_timer_tsc2ns(avgjitter);            maxj = rt_timer_tsc2ns(maxjitter);            gmaxj = rt_timer_tsc2ns(gmaxjitter);        } else {            struct rtbnch_interm_result result;            err = rt_dev_ioctl(benchdev, RTBNCH_RTIOC_INTERM_RESULT, &result);            if (err)                {                if (err != -EIDRM)                    fprintf(stderr,"latency: failed to call RTBNCH_RTIOC_INTERM_RESULT, code %d\n",err);                return;                }            minj = result.last.min;            gminj = result.overall.min;            avgj = result.last.avg;            maxj = result.last.max;            gmaxj = result.overall.max;            goverrun = result.overall.overruns;        }        if (!quiet)            {            if (data_lines && (n++ % data_lines)==0)                {                time_t now, dt;                time(&now);                dt = now - start - WARMUP_TIME;                printf("RTT|  %.2ld:%.2ld:%.2ld  (%s, %Ld us period)\n",                       dt / 3600,(dt / 60) % 60,dt % 60,                       test_mode_names[test_mode],period_ns / 1000);                printf("RTH|%12s|%12s|%12s|%8s|%12s|%12s\n",                       "-----lat min","-----lat avg","-----lat max","-overrun",                       "----lat best","---lat worst");                }            printf("RTD|%12.3f|%12.3f|%12.3f|%8ld|%12.3f|%12.3f\n",                   (double)minj / 1000,                   (double)avgj / 1000,                   (double)maxj / 1000,                   goverrun,                   (double)gminj / 1000,                   (double)gmaxj / 1000);            }        }}double dump_histogram (long *histogram, char* kind){    int n, total_hits = 0;    double avg = 0;             /* used to sum hits 1st */    if (do_histogram)        fprintf(stderr,"---|--param|----range-|--samples\n");    for (n = 0; n < histogram_size; n++)        {        long hits = histogram[n];        if (hits)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?