📄 calibrate.c
字号:
/* * Copyright (C) 2003 Paolo Mantegazza <mantegazza@aero.polimi.it> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */#include <float.h>#include <stdio.h>#include <stdlib.h>#include <ctype.h>#include <signal.h>#include <string.h>#include <sys/mman.h>#include <sys/io.h>#include <getopt.h>#include <pthread.h>#include <math.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <termio.h>#include <sys/poll.h>#include <sys/wait.h>#include <fcntl.h>#include <unistd.h>#include <ctype.h>#include <time.h>#include <signal.h>#include <asm/rtai_srq.h>#include <rtai_fifos.h>#include "calibrate.h"struct option options[] = { { "help", 0, 0, 'h' }, { "r8254", 0, 0, 'r' }, { "kernel", 0, 0, 'k' },#ifdef CONFIG_RTAI_SCHED_LXRT { "user", 0, 0, 'u' },#endif { "period", 1, 0, 'p' }, { "time", 1, 0, 't' }, { "cpu", 0, 0, 'c' }, { "apic", 0, 0, 'a' }, { "both", 0, 0, 'b' }, { "scope", 1, 0, 's' }, { "interrupt", 0, 0, 'i' }, { NULL, 0, 0, 0 }};void print_usage(void){ fputs( ("\n*** i386 calibrations ***\n" "\n" "OPTIONS:\n" " -h, --help\n" " print usage\n" " -r, --r8254\n" " calibrate 8254 oneshot programming type\n" " -k, --kernel\n" " oneshot latency calibrated for scheduling kernel space tasks\n"#ifdef CONFIG_RTAI_SCHED_LXRT " -u, --user\n" " oneshot latency calibrated for scheduling user space tasks\n"#endif " -p <period (us)>, --period <period (us)>\n" " the period of the underlying hard real time task/intr, default 100 (us)\n" " -t <duration (s)>, --time <duration (s)>\n" " set the duration of the requested calibration, default 5 (s)\n" " -c, --cpufreq\n" " calibrate cpu frequency\n" " -a, --apic\n" " calibrate apic frequency\n" " -b, --both\n" " calibrate both apic and cpu frequency\n" " -i, --interrupt\n" " check worst case interrupt locking/contention on your PC\n" " -s<y/n>, --scope<y/n>\n" " toggle parport bit to monitor scheduling on a scope, default y(es)\n" "\n") , stderr);}static void endme(int dummy) { }static void unload_kernel_helper (void){ char modunload[1024]; snprintf(modunload,sizeof(modunload),"/sbin/rmmod %s >/dev/null 2>&1",KERNEL_HELPER_PATH); system(modunload);}int main(int argc, char *argv[]){ int srq, fifo, command, commands[20], ncommands, c, option_index, i; struct params_t params; char str[80], nm[RTF_NAMELEN+1], modload[1024]; unsigned long period = 100, duration = 5, parport = 'y'; unsigned long args[MAXARGS]; struct pollfd polls[2] = { { 0, POLLIN }, { 0, POLLIN } }; option_index = ncommands = 0; while (1) { if ((c = getopt_long(argc, argv, "hrkucabip:t:s:", options, &option_index)) == -1) { break; } switch(c) { case 'h': { print_usage(); exit(0); } case 'r':#ifdef CONFIG_RTAI_SCHED_LXRT case 'u':#endif case 'c': case 'b': case 'a': case 'i': case 'k': { commands[ncommands++] = c; break; } case 'p': { period = atoi(optarg); break; } case 't': { duration = atoi(optarg); break; } case 's': { parport = optarg[0] == 'y' ? 'y' : 'n'; break; } } } if (ncommands <= 0) { printf("\n*** NOTHING TO BE DONE ***\n"); exit(0); } atexit(&unload_kernel_helper); snprintf(modload,sizeof(modload),"/sbin/insmod %s >/dev/null 2>&1",KERNEL_HELPER_PATH); system(modload); signal(SIGINT, endme); srq = rtai_open_srq(CALSRQ); if ((fifo = open(rtf_getfifobyminor(0,nm,sizeof(nm)), O_RDONLY)) < 0) { printf("Error opening %s\n",nm); exit(1); } polls[1].fd = fifo; args[0] = GET_PARAMS; rtai_srq(srq, (unsigned int)args); read(fifo, ¶ms, sizeof(params)); printf("\n*** NUMBER OF REQUESTS: %d. ***\n", ncommands); for (i = 0; i < ncommands; i++) { switch (command = commands[i]) { case 'r': { args[0] = CAL_8254; printf("\n*** '#define SETUP_TIME_8254 %lu', IN USE %lu ***\n\n", (unsigned long) rtai_srq(srq, (unsigned int)args), params.setup_time_8254); break; } case 'k': { int average; args[0] = KLATENCY; args[1] = period; args[2] = duration; printf("\n*** KERNEL SPACE LATENCY CALIBRATION, wait %lu seconds for it ... ***\n", args[2]); args[2] = (1000000*args[2])/args[1]; args[1] *= 1000; rtai_srq(srq, (unsigned int)args); read(fifo, &average, sizeof(average)); average /= (int)args[2]; if (params.mp) { printf("\n*** '#define LATENCY_APIC %d' (IN USE %lu)\n\n", (int)params.latency_apic + average, params.latency_apic); } else { printf("\n*** '#define LATENCY_8254 %d' (IN USE %lu)\n\n", (int)params.latency_8254 + average, params.latency_8254); } args[0] = END_KLATENCY; rtai_srq(srq, (unsigned int)args); break; } case 'u': { int pid, average; args[1] = period; args[2] = duration; printf("\n*** USER SPACE LATENCY CALIBRATION, wait %lu seconds for it ... ***\n", args[2]); args[2] = (1000000*args[2])/args[1]; args[1] *= 1000; sprintf(str, "%lu", args[1]); sprintf(str + sizeof(str)/2, "%lu", args[2]); pid = fork(); if (!pid) { execl(USER_HELPER_PATH, USER_HELPER_PATH, str, str + sizeof(str)/2, NULL); _exit(1); } read(fifo, &average, sizeof(average)); waitpid(pid, 0, 0); if (kill(pid,0) < 0) { printf("\n*** Cannot execute calibration helper %s -- aborting\n",USER_HELPER_PATH); exit(1); } average /= (int)args[2]; if (params.mp) { printf("\n*** '#define LATENCY_APIC %d' (IN USE %lu)\n\n", (int)params.latency_apic + average, params.latency_apic); } else { printf("\n*** '#define LATENCY_8254 %d' (IN USE %lu)\n\n", (int)params.latency_8254 + average, params.latency_8254); } break; } case 'a': if (!params.mp) { printf("*** APIC FREQUENCY CALIBRATION NOT AVAILABLE UNDER UP ***\n"); break; } case 'b': case 'c': { unsigned long time, cpu_freq = 0, apic_freq = 0; struct times_t times; args[0] = FREQ_CAL; args[1] = duration; printf("\n->>> FREQ CALIB (PRINTING EVERY %lu SECONDS, press enter to end calibrating) <<<-\n\n", args[1]); rtai_srq(srq, (unsigned int)args); time = 0; while (1) { time += args[1]; if (poll(polls, 2, 1000*duration) > 0 &&polls[0].revents) { getchar(); args[0] = END_FREQ_CAL; rtai_srq(srq, (unsigned int)args); if (command == 'c' || command == 'b') { printf("\n*** '#define CPU_FREQ %lu', IN USE %lu ***\n\n", cpu_freq, params.cpu_freq); } if (params.mp && (command == 'a' || command == 'b')) { printf("\n*** '#define APIC_FREQ %lu', IN USE %lu ***\n\n", apic_freq, params.freq_apic); } break; } read(fifo, ×, sizeof(times)); if (command == 'c' || command == 'b') { cpu_freq = (((double)times.cpu_time)*params.clock_tick_rate)/(((double)times.intrs)*params.latch) + 0.49999999999999999; printf("\n->>> MEASURED CPU_FREQ: %lu (Hz) [%lu (s)], IN USE %lu (Hz) <<<-\n", cpu_freq, time, params.cpu_freq); } if (params.mp && (command == 'a' || command == 'b')) { apic_freq = (((double)times.apic_time)*params.clock_tick_rate)/(((double)times.intrs)*params.latch) + 0.49999999999999999; printf("\n->>> MEASURED APIC_FREQ: %lu (Hz) [%lu (s)], IN USE %lu (Hz) <<<-\n", apic_freq, time, params.freq_apic); } } break; } case 'i': { time_t timestamp; struct tm *tm_timestamp; args[0] = BUS_CHECK; args[1] = period; args[2] = 1; args[3] = parport; printf("\n->>> INTERRUPT LATENCY CHECK (press enter to end check) <<<-\n\n"); args[1] *= 1000; args[2] *= 1000; rtai_srq(srq, (unsigned int)args); while (1) { int maxj; if (poll(polls, 2, 100) > 0) { if (polls[0].revents) { getchar(); args[0] = END_BUS_CHECK; rtai_srq(srq, (unsigned int)args); break; } read(fifo, &maxj, sizeof(maxj)); time(×tamp); tm_timestamp = localtime(×tamp); printf("%04d/%02d/%0d-%02d:%02d:%02d -> ", tm_timestamp->tm_year+1900, tm_timestamp->tm_mon+1, tm_timestamp->tm_mday, tm_timestamp->tm_hour, tm_timestamp->tm_min, tm_timestamp->tm_sec); printf("%d.%-3d (us)\n", maxj/1000, maxj%1000); } } break; } } } exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -