int main(void) { RT_TASK *Main_Task; long msg; if (!(Main_Task = rt_thread_init(nam2num("MNTSK"), 10, 0, SCHED_FIFO, 0xF))) { printf("CANNOT INIT MAIN TASK\n"); exit(1); } if (!(hard_timer_running = rt_is_hard_timer_running())) { start_rt_timer(0); } barrier = rt_sem_init(nam2num("PREMS"), 4); latency_thread = rt_thread_create(latency_fun, NULL, 0); fast_thread = rt_thread_create(fast_fun, NULL, 0); slow_thread = rt_thread_create(slow_fun, NULL, 0); start = rt_get_time() + nano2count(200000000); rt_sem_wait_barrier(barrier); rt_receive(0, &msg); end = 1; rt_sem_wait_barrier(barrier); rt_thread_join(latency_thread); rt_thread_join(fast_thread); rt_thread_join(slow_thread); if (!hard_timer_running) { stop_rt_timer(); } rt_sem_delete(barrier); rt_thread_delete(Main_Task); return 0; }
static int __latency_init(void) { /* XXX check option ranges here */ /* register a proc entry */ #ifdef CONFIG_PROC_FS create_proc_read_entry("rtai/latency_calibrate", /* name */ 0, /* default mode */ NULL, /* parent dir */ proc_read, /* function */ NULL /* client data */ ); #endif rtf_create(DEBUG_FIFO, 16000); /* create a fifo length: 16000 bytes */ rt_linux_use_fpu(use_fpu); /* declare if we use the FPU */ rt_task_init( /* create our measuring task */ &thread, /* poiter to our RT_TASK */ fun, /* implementation of the task */ 0, /* we could transfer data -> task */ 3000, /* stack size */ 0, /* priority */ use_fpu, /* do we use the FPU? */ 0 /* signal? XXX */ ); rt_set_runnable_on_cpus( /* select on which CPUs the task is */ &thread, /* allowed to run */ RUN_ON_CPUS ); /* Test if we have to start the timer */ if (start_timer || (start_timer = !rt_is_hard_timer_running())) { if (timer_mode) { rt_set_periodic_mode(); } else { rt_set_oneshot_mode(); } rt_assign_irq_to_cpu(TIMER_8254_IRQ, TIMER_TO_CPU); period_counts = start_rt_timer(nano2count(period)); } else { period_counts = nano2count(period); } loops = (1000000000*avrgtime)/period; /* Calculate the start time for the task. */ /* We set this to "now plus 10 periods" */ expected = rt_get_time() + 10 * period_counts; rt_task_make_periodic(&thread, expected, period_counts); return 0; }
void latency (void *cookie) { int err, count, nsamples, warmup = 1; RTIME expected_tsc, period_tsc, start_ticks; RT_TIMER_INFO timer_info; RT_QUEUE q; rt_queue_create(&q, "queue", 0, 100, 0); if (!(hard_timer_running = rt_is_hard_timer_running())) { err = rt_timer_start(TM_ONESHOT); if (err) { fprintf(stderr,"latency: cannot start timer, code %d\n",err); return; } } err = rt_timer_inquire(&timer_info); if (err) { fprintf(stderr,"latency: rt_timer_inquire, code %d\n",err); return; } nsamples = ONE_BILLION / period_ns / 1; 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,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++) { expected_tsc += period_tsc; err = rt_task_wait_period(NULL); if (err) { if (err != -ETIMEDOUT) { rt_queue_delete(&q); rt_task_delete(NULL); /* Timer stopped. */ } overrun++; } dt = (long)(rt_timer_tsc() - expected_tsc); if (dt > maxj) maxj = dt; if (dt < minj) minj = dt; sumj += 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); struct smpl_t { long minjitter, avgjitter, maxjitter, overrun; } *smpl; smpl = rt_queue_alloc(&q, sizeof(struct smpl_t)); #if 1 smpl->minjitter = rt_timer_tsc2ns(minj); smpl->maxjitter = rt_timer_tsc2ns(maxj); smpl->avgjitter = rt_timer_tsc2ns(sumj / nsamples); smpl->overrun = goverrun; rt_queue_send(&q, smpl, sizeof(struct smpl_t), TM_NONBLOCK); #endif } if(warmup && test_loops == WARMUP_TIME) { test_loops = 0; warmup = 0; } } }
int main(int argc, char *argv[]) { int diff; int sample; long average; int min_diff; int max_diff; int period; int i; RTIME t, svt; RTIME expected, exectime[3]; MBX *mbx; RT_TASK *task, *latchk; struct sample { long long min; long long max; int index, ovrn; } samp; double s = 0.0, sref; long long max = -1000000000, min = 1000000000; signal(SIGINT, endme); signal(SIGKILL, endme); signal(SIGTERM, endme); if (!(mbx = rt_mbx_init(nam2num("LATMBX"), 20*sizeof(samp)))) { printf("CANNOT CREATE MAILBOX\n"); exit(1); } if (!(task = rt_task_init_schmod(nam2num("LATCAL"), 0, 0, 0, SCHED_FIFO, 0xF))) { printf("CANNOT INIT MASTER LATENCY TASK\n"); exit(1); } printf("\n## RTAI latency calibration tool ##\n"); printf("# period = %i (ns) \n", PERIOD); printf("# average time = %i (s)\n", (int)AVRGTIME); printf("# use the FPU\n"); printf("#%sstart the timer\n", argc == 1 ? " " : " do not "); printf("# timer_mode is %s\n", TIMER_MODE ? "periodic" : "oneshot"); printf("\n"); if (!(hard_timer_running = rt_is_hard_timer_running())) { if (TIMER_MODE) { rt_set_periodic_mode(); } else { rt_set_oneshot_mode(); } period = start_rt_timer(nano2count(PERIOD)); } else { period = nano2count(PERIOD); } for(i = 0; i < MAXDIM; i++) { a[i] = b[i] = 3.141592; } sref = dot(a, b, MAXDIM); mlockall(MCL_CURRENT | MCL_FUTURE); rt_make_hard_real_time(); expected = rt_get_time() + 200*period; rt_task_make_periodic(task, expected, period); svt = rt_get_cpu_time_ns(); i = 0; samp.ovrn = 0; while (!end) { min_diff = 1000000000; max_diff = -1000000000; average = 0; for (sample = 0; sample < SMPLSXAVRG && !end; sample++) { expected += period; if (!rt_task_wait_period()) { if (TIMER_MODE) { diff = (int) ((t = rt_get_cpu_time_ns()) - svt - PERIOD); svt = t; } else { diff = (int) count2nano(rt_get_time() - expected); } } else { samp.ovrn++; diff = 0; if (TIMER_MODE) { svt = rt_get_cpu_time_ns(); } } outb(i = 1 - i, 0x378); if (diff < min_diff) { min_diff = diff; } if (diff > max_diff) { max_diff = diff; } average += diff; s = dot(a, b, MAXDIM); if (fabs((s - sref)/sref) > 1.0e-15) { printf("\nDOT PRODUCT RESULT = %20.16e %20.16e %20.16e\n", s, sref, fabs((s - sref)/sref)); return 0; } } samp.min = min_diff; samp.max = max_diff; samp.index = average/SMPLSXAVRG; #if SOLO if (max < samp.max) max = samp.max; if (min > samp.min) min = samp.min; rt_printk("SOLO * min: %lld/%lld, max: %lld/%lld average: %d (%d) <Hit [RETURN] to stop> *\n", samp.min, min, samp.max, max, samp.index, samp.ovrn); #else rt_mbx_send_if(mbx, &samp, sizeof(samp)); if ((latchk = rt_get_adr(nam2num("LATCHK"))) && (rt_receive_if(latchk, &average) || end)) { rt_return(latchk, average); break; } #endif } while (rt_get_adr(nam2num("LATCHK"))) { rt_sleep(nano2count(1000000)); } rt_make_soft_real_time(); if (!hard_timer_running) { stop_rt_timer(); } rt_get_exectime(task, exectime); if (exectime[1] && exectime[2]) { printf("\n>>> S = %g, EXECTIME = %G\n", s, (double)exectime[0]/(double)(exectime[2] - exectime[1])); } rt_task_delete(task); rt_mbx_delete(mbx); return 0; }
int main(int argc, char *argv[]) { int sock; struct sockaddr_in SPRT_ADDR; char buf[200]; int fd; int diff; int sample; int average; int min_diff; int max_diff; int period; int i; int cnt; RTIME t, svt; RTIME expected, exectime[3]; RT_TASK *task; long long max = -1000000000, min = 1000000000; struct sample { long long min; long long max; int index, ovrn; } samp; double s, sref; if (!(task = rt_task_init_schmod(nam2num("LATCAL"), 0, 0, 0, SCHED_FIFO, 0xF))) { printf("CANNOT INIT MASTER LATENCY TASK\n"); exit(1); } sock = socket(AF_INET, SOCK_DGRAM, 0); bzero(&SPRT_ADDR, sizeof(struct sockaddr_in)); SPRT_ADDR.sin_family = AF_INET; SPRT_ADDR.sin_port = htons(5000); SPRT_ADDR.sin_addr.s_addr = inet_addr("127.0.0.1"); fd = open("echo", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); printf("\n## RTAI latency calibration tool ##\n"); printf("# period = %i (ns) \n", PERIOD); printf("# average time = %i (s)\n", (int)AVRGTIME); printf("# use the FPU\n"); printf("#%sstart the timer\n", argc == 1 ? " " : " do not "); printf("# timer_mode is %s\n", TIMER_MODE ? "periodic" : "oneshot"); printf("\n"); rt_sync_async_linux_syscall_server_create(NULL, ASYNC_LINUX_SYSCALL, async_callback, 120); if (!(hard_timer_running = rt_is_hard_timer_running())) { if (TIMER_MODE) { rt_set_periodic_mode(); } else { rt_set_oneshot_mode(); } period = start_rt_timer(nano2count(PERIOD)); } else { period = nano2count(PERIOD); } for(i = 0; i < MAXDIM; i++) { a[i] = b[i] = 3.141592; } sref = dot(a, b, MAXDIM); s = 0.0; mlockall(MCL_CURRENT | MCL_FUTURE); rt_make_hard_real_time(); expected = rt_get_time() + 200*period; rt_task_make_periodic(task, expected, period); svt = rt_get_cpu_time_ns(); cnt = 0; i = 0; samp.ovrn = 0; while (!end) { min_diff = 1000000000; max_diff = -1000000000; average = 0; for (sample = 0; sample < SMPLSXAVRG && !end; sample++) { expected += period; if (!rt_task_wait_period()) { if (TIMER_MODE) { diff = (int) ((t = rt_get_cpu_time_ns()) - svt - PERIOD); svt = t; } else { diff = (int) count2nano(rt_get_time() - expected); } } else { samp.ovrn++; diff = 0; if (TIMER_MODE) { svt = rt_get_cpu_time_ns(); } } if (diff < min_diff) { min_diff = diff; } if (diff > max_diff) { max_diff = diff; } average += diff; s = dot(a, b, MAXDIM); if (fabs(s/sref - 1.0) > 1.0e-16) { printf("\nDOT PRODUCT RESULT = %lf %lf %lf\n", s, sref, sref - s); return 0; } } samp.min = min_diff; samp.max = max_diff; samp.index = average/SMPLSXAVRG; if (max < samp.max) max = samp.max; if (min > samp.min) min = samp.min; ++cnt; // printf("* %d - min: %lld/%lld, max: %lld/%lld average: %d <RET to stop> %d *\n", cnt, samp.min, min, samp.max, max, samp.index, samp.ovrn); sprintf(buf, "* %d - min: %lld/%lld, max: %lld/%lld average: %d <RET to stop> %d *\n", cnt, samp.min, min, samp.max, max, samp.index, samp.ovrn); i = write(STDOUT_FILENO, buf, strlen(buf)); fdatasync(STDOUT_FILENO); i = write(fd, buf, strlen(buf)); fsync(fd); sendto(sock, buf, strlen(buf), 0, (struct sockaddr *)&SPRT_ADDR, sizeof(struct sockaddr_in)); } close(sock); close(fd); rt_make_soft_real_time(); if (!hard_timer_running) { stop_rt_timer(); } rt_get_exectime(task, exectime); if (exectime[1] && exectime[2]) { printf("\n>>> S = %g, EXECTIME = %G\n", s, (double)exectime[0]/(double)(exectime[2] - exectime[1])); } rt_task_delete(task); return 0; }
int main(int argc, char *argv[]) { RT_TASK *task; RTIME trp, max = 0, min = 1000000000, avrg = 0; int sockfd, ret, hard_timer_running, i; struct sockaddr_in local_addr, server_addr; struct { long long count; char msg[100]; } msg = { 0LL, "this message was sent using rtnet-rtai." }; signal(SIGTERM, sigh); signal(SIGINT, sigh); signal(SIGHUP, sigh); /* Set address structures to zero. */ memset(&local_addr, 0, sizeof(struct sockaddr_in)); memset(&server_addr, 0, sizeof(struct sockaddr_in)); /* Check arguments and set addresses. */ if (argc == 6) { local_addr.sin_family = AF_INET; local_addr.sin_addr.s_addr = INADDR_ANY; local_addr.sin_port = htons(atoi(argv[1])); server_addr.sin_family = AF_INET; inet_aton(argv[2], &server_addr.sin_addr); server_addr.sin_port = htons(atoi(argv[3])); NR_TRIPS = atoi(argv[4]); PERIOD = atoi(argv[5])*1000LL; } else { fprintf(stderr, "Usage: " "%s <local-port> " "<server-ip> <server-port> " "<number-of-trips> <sending-period-us>\n", argv[0]); return 1; } /* Create new socket. */ sockfd = rt_dev_socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { printf("Error opening socket: %d\n", sockfd); return 1; } /* Link the Linux process to RTAI. */ if (!(hard_timer_running = rt_is_hard_timer_running())) { start_rt_timer(0); } task = rt_thread_init(nam2num("SMPCLT"), 1, 0, SCHED_OTHER, 0xFF); if (task == NULL) { rt_dev_close(sockfd); printf("CANNOT LINK LINUX SIMPLECLIENT PROCESS TO RTAI\n"); return 1; } /* Lock allocated memory into RAM. */ printf("RTnet, simpleclient for RTAI (user space).\n"); mlockall(MCL_CURRENT|MCL_FUTURE); /* Switch over to hard realtime mode. */ rt_make_hard_real_time(); /* Bind socket to local address specified as parameter. */ ret = rt_dev_bind(sockfd, (struct sockaddr *)&local_addr, sizeof(struct sockaddr_in)); /* Specify destination address for socket; needed for rt_socket_send(). */ rt_dev_connect(sockfd, (struct sockaddr *) &server_addr, sizeof(struct sockaddr_in)); /* Send messages */ for (i = 1; i <= NR_TRIPS && !end; i++) { rt_sleep(nano2count(PERIOD)); msg.count = i; trp = rt_get_time_ns(); rt_dev_send(sockfd, &msg, sizeof(long long) + strlen(msg.msg) + 1, 0); rt_dev_recv(sockfd, &msg, sizeof(msg), 0); trp = (msg.count - trp)/1000; if (trp < min) min = trp; if (i > 3 && trp > max) max = trp; avrg += trp; printf("Client received: trip time %lld (us), %s\n", trp, msg.msg); } msg.count = -1; rt_dev_send(sockfd, &msg, sizeof(long long) + strlen(msg.msg) + 1, 0); /* Switch over to soft realtime mode. */ rt_make_soft_real_time(); /* Close socket, must be in soft-mode because socket was created as non-rt. */ rt_dev_close(sockfd); /* Unlink the Linux process from RTAI. */ if (!hard_timer_running) { stop_rt_timer(); } rt_task_delete(task); printf("Min trip time %lld, Max trip time %lld, Average trip time %lld\n", min, max, avrg/i); return 0; }