00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
#include <float.h>
00020
#include <stdio.h>
00021
#include <stdlib.h>
00022
#include <ctype.h>
00023
#include <signal.h>
00024
#include <string.h>
00025
#include <sys/mman.h>
00026
#include <sys/io.h>
00027
#include <getopt.h>
00028
#include <pthread.h>
00029
#include <math.h>
00030
00031
#include <stdio.h>
00032
#include <stdlib.h>
00033
#include <errno.h>
00034
#include <termio.h>
00035
#include <sys/poll.h>
00036
#include <sys/wait.h>
00037
#include <fcntl.h>
00038
#include <unistd.h>
00039
#include <ctype.h>
00040
#include <time.h>
00041
#include <signal.h>
00042
00043
#include <asm/rtai_srq.h>
00044
#include <rtai_fifos.h>
00045
#include "calibrate.h"
00046
00047 struct option
options[] = {
00048 {
"help", 0, 0,
'h' },
00049 {
"r8254", 0, 0,
'r' },
00050 {
"kernel", 0, 0,
'k' },
00051 {
"user", 0, 0,
'u' },
00052 {
"period", 1, 0,
'p' },
00053 {
"time", 1, 0,
't' },
00054 {
"cpu", 0, 0,
'c' },
00055 {
"apic", 0, 0,
'a' },
00056 {
"both", 0, 0,
'b' },
00057 {
"scope", 1, 0,
's' },
00058 {
"interrupt", 0, 0,
'i' },
00059 { NULL, 0, 0, 0 }
00060 };
00061
00062 void print_usage(
void)
00063 {
00064 fputs(
00065 (
"\n*** i386 calibrations ***\n"
00066
"\n"
00067
"OPTIONS:\n"
00068
" -h, --help\n"
00069
" print usage\n"
00070
" -r, --r8254\n"
00071
" calibrate 8254 oneshot programming type\n"
00072
" -k, --kernel\n"
00073
" oneshot latency calibrated for scheduling kernel space tasks\n"
00074
" -u, --user\n"
00075
" oneshot latency calibrated for scheduling user space tasks\n"
00076
" -p <period (us)>, --period <period (us)>\n"
00077
" the period of the underlying hard real time task/intr, default 100 (us)\n"
00078
" -t <duration (s)>, --time <duration (s)>\n"
00079
" set the duration of the requested calibration, default 5 (s)\n"
00080
" -c, --cpufreq\n"
00081
" calibrate cpu frequency\n"
00082
" -a, --apic\n"
00083
" calibrate apic frequency\n"
00084
" -b, --both\n"
00085
" calibrate both apic and cpu frequency\n"
00086
" -i, --interrupt\n"
00087
" check worst case interrupt locking/contention on your PC\n"
00088
" -s<y/n>, --scope<y/n>\n"
00089
" toggle parport bit to monitor scheduling on a scope, default y(es)\n"
00090
"\n")
00091 , stderr);
00092 }
00093
00094 static void endme(
int dummy) { }
00095
00096 static void unload_kernel_helper (
void)
00097
00098 {
00099
char modunload[1024];
00100
00101 snprintf(modunload,
sizeof(modunload),
"/sbin/rmmod %s >/dev/null 2>&1",KERNEL_HELPER_PATH);
00102 system(modunload);
00103 }
00104
00105 int main(
int argc,
char *argv[])
00106 {
00107
int srq, fifo, command, commands[20], ncommands, c, option_index, i;
00108
struct params_t params;
00109
char str[80], nm[
RTF_NAMELEN+1], modload[1024];
00110
unsigned long period = 100, duration = 5, parport =
'y';
00111
unsigned long args[
MAXARGS];
00112
struct pollfd polls[2] = { { 0, POLLIN }, { 0, POLLIN } };
00113
00114 option_index = ncommands = 0;
00115
while (1) {
00116
if ((c = getopt_long(argc, argv,
"hrkucabip:t:s:",
options, &option_index)) == -1) {
00117
break;
00118 }
00119
switch(c) {
00120
case 'h': {
00121
print_usage();
00122 exit(0);
00123 }
00124
case 'r':
00125
case 'u':
00126
case 'c':
00127
case 'b':
00128
case 'a':
00129
case 'i':
00130
case 'k': {
00131 commands[ncommands++] = c;
00132
break;
00133 }
00134
case 'p': {
00135 period = atoi(optarg);
00136
break;
00137 }
00138
case 't': {
00139 duration = atoi(optarg);
00140
break;
00141 }
00142
case 's': {
00143 parport = optarg[0] ==
'y' ?
'y' :
'n';
00144
break;
00145 }
00146 }
00147 }
00148
if (ncommands <= 0) {
00149 printf(
"\n*** NOTHING TO BE DONE ***\n");
00150 exit(0);
00151 }
00152
00153 atexit(&
unload_kernel_helper);
00154
00155 snprintf(modload,
sizeof(modload),
"/sbin/insmod %s >/dev/null 2>&1",KERNEL_HELPER_PATH);
00156 system(modload);
00157
00158 signal(SIGINT,
endme);
00159
00160
srq =
rtai_open_srq(
CALSRQ);
00161
if ((fifo = open(rtf_getfifobyminor(0,nm,
sizeof(nm)), O_RDONLY)) < 0) {
00162 printf(
"Error opening %s\n",nm);
00163 exit(1);
00164 }
00165 polls[1].fd = fifo;
00166
00167 args[0] =
GET_PARAMS;
00168
rtai_srq(
srq, (
unsigned long)args);
00169 read(fifo, ¶ms,
sizeof(params));
00170 printf(
"\n*** NUMBER OF REQUESTS: %d. ***\n", ncommands);
00171
00172
for (i = 0; i < ncommands; i++) {
00173
switch (command = commands[i]) {
00174
00175
case 'r': {
00176 args[0] =
CAL_8254;
00177 printf(
"\n*** '#define SETUP_TIME_8254 %lu', IN USE %lu ***\n\n", (
unsigned long)
rtai_srq(
srq, (
unsigned long)args), params.setup_time_8254);
00178
break;
00179 }
00180
00181
case 'k': {
00182
int average;
00183 args[0] =
KLATENCY;
00184 args[1] = period;
00185 args[2] = duration;
00186 printf(
"\n*** KERNEL SPACE LATENCY CALIBRATION, wait %lu seconds for it ... ***\n", args[2]);
00187 args[2] = (1000000*args[2])/args[1];
00188 args[1] *= 1000;
00189
rtai_srq(
srq, (
unsigned long)args);
00190 read(fifo, &average,
sizeof(average));
00191 average /= (
int)args[2];
00192
if (params.mp) {
00193 printf(
"\n*** '#define LATENCY_APIC %d' (IN USE %lu)\n\n", (
int)params.latency_apic + average, params.latency_apic);
00194 }
else {
00195 printf(
"\n*** '#define LATENCY_8254 %d' (IN USE %lu)\n\n", (
int)params.latency_8254 + average, params.latency_8254);
00196 }
00197 args[0] =
END_KLATENCY;
00198
rtai_srq(
srq, (
unsigned long)args);
00199
break;
00200 }
00201
00202
case 'u': {
00203
int pid, average;
00204 args[1] = period;
00205 args[2] = duration;
00206 printf(
"\n*** USER SPACE LATENCY CALIBRATION, wait %lu seconds for it ... ***\n", args[2]);
00207 args[2] = (1000000*args[2])/args[1];
00208 args[1] *= 1000;
00209 sprintf(str,
"%lu", args[1]);
00210 sprintf(str +
sizeof(str)/2,
"%lu", args[2]);
00211
pid = fork();
00212
if (!
pid) {
00213 execl(USER_HELPER_PATH, USER_HELPER_PATH, str, str +
sizeof(str)/2, NULL);
00214 _exit(1);
00215 }
00216 read(fifo, &average,
sizeof(average));
00217 waitpid(
pid, 0, 0);
00218
if (kill(
pid,0) < 0)
00219 {
00220
00221
00222 }
00223 average /= (
int)args[2];
00224
if (params.mp) {
00225 printf(
"\n*** '#define LATENCY_APIC %d' (IN USE %lu)\n\n", (
int)params.latency_apic + average, params.latency_apic);
00226 }
else {
00227 printf(
"\n*** '#define LATENCY_8254 %d' (IN USE %lu)\n\n", (
int)params.latency_8254 + average, params.latency_8254);
00228 }
00229
break;
00230 }
00231
00232
case 'a':
00233
if (!params.mp) {
00234 printf(
"*** APIC FREQUENCY CALIBRATION NOT AVAILABLE UNDER UP ***\n");
00235
break;
00236 }
00237
case 'b':
00238
case 'c': {
00239
unsigned long time, cpu_freq = 0, apic_freq = 0;
00240
struct times_t times;
00241 args[0] =
FREQ_CAL;
00242 args[1] = duration;
00243 printf(
"\n->>> FREQ CALIB (PRINTING EVERY %lu SECONDS, press enter to end calibrating) <<<-\n\n", args[1]);
00244
rtai_srq(
srq, (
unsigned long)args);
00245 time = 0;
00246
while (1) {
00247 time += args[1];
00248
if (poll(polls, 2, 1000*duration) > 0 &&polls[0].revents) {
00249 getchar();
00250 args[0] =
END_FREQ_CAL;
00251
rtai_srq(
srq, (
unsigned long)args);
00252
if (command ==
'c' || command ==
'b') {
00253 printf(
"\n*** '#define CPU_FREQ %lu', IN USE %lu ***\n\n", cpu_freq, params.cpu_freq);
00254 }
00255
if (params.mp && (command ==
'a' || command ==
'b')) {
00256 printf(
"\n*** '#define APIC_FREQ %lu', IN USE %lu ***\n\n", apic_freq, params.freq_apic);
00257 }
00258
break;
00259 }
00260 read(fifo, ×,
sizeof(times));
00261
if (command ==
'c' || command ==
'b') {
00262 cpu_freq = (((
double)times.cpu_time)*params.clock_tick_rate)/(((
double)times.intrs)*params.latch) + 0.49999999999999999;
00263 printf(
"\n->>> MEASURED CPU_FREQ: %lu (Hz) [%lu (s)], IN USE %lu (Hz) <<<-\n", cpu_freq, time, params.cpu_freq);
00264 }
00265
if (params.mp && (command ==
'a' || command ==
'b')) {
00266 apic_freq = (((
double)times.apic_time)*params.clock_tick_rate)/(((
double)times.intrs)*params.latch) + 0.49999999999999999;
00267 printf(
"\n->>> MEASURED APIC_FREQ: %lu (Hz) [%lu (s)], IN USE %lu (Hz) <<<-\n", apic_freq, time, params.freq_apic);
00268 }
00269 }
00270
break;
00271 }
00272
00273
case 'i': {
00274 time_t timestamp;
00275
struct tm *tm_timestamp;
00276 args[0] =
BUS_CHECK;
00277 args[1] = period;
00278 args[2] = 1;
00279 args[3] = parport;
00280 printf(
"\n->>> INTERRUPT LATENCY CHECK (press enter to end check) <<<-\n\n");
00281 args[1] *= 1000;
00282 args[2] *= 1000;
00283
rtai_srq(
srq, (
unsigned long)args);
00284
while (1) {
00285
int maxj;
00286
if (poll(polls, 2, 100) > 0) {
00287
if (polls[0].revents) {
00288 getchar();
00289 args[0] =
END_BUS_CHECK;
00290
rtai_srq(
srq, (
unsigned long)args);
00291
break;
00292 }
00293 read(fifo, &maxj,
sizeof(maxj));
00294 time(×tamp);
00295 tm_timestamp = localtime(×tamp);
00296 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);
00297 printf(
"%d.%-3d (us)\n", maxj/1000, maxj%1000);
00298 }
00299 }
00300
break;
00301 }
00302
00303 }
00304 }
00305 exit(0);
00306 }