/* * RTLinux scheduling accuracy measuring example * * This modules attempts to reserve a CPU for RTLinux on SMP machines. * Note that this feature is only supported on 2.4.x kernels. * * Written by Michael Barabanov, 2000 * (C) FSMLabs 2000. baraban@fsmlabs.com * Released under the GNU GENERAL PUBLIC LICENSE Version 2, June 1991 * Any use of this code must include this notice. */ #include #include #include #include #include #include #include #include #include #include "common.h" int ntests=500; int period=1000000; int fifo_size=4000; int advance=0; int nolinux=1; MODULE_PARM(period,"i"); MODULE_PARM(ntests,"i"); MODULE_PARM(advance,"i"); MODULE_PARM(nolinux,"i"); static pthread_t thread; static int fd_fifo; static void *thread_code(void *param); static int reserved; int init_module(void) { pthread_attr_t attr; struct sched_param sched_param; int ret; int cpu; rtf_destroy(0); rtf_create(0, fifo_size); cpu = rtl_getcpuid(); rtl_printf("RTLinux measurement module on CPU %d\n",rtl_getcpuid()); pthread_attr_init (&attr); sched_param.sched_priority = 1; reserved = 0; if (nolinux && rtl_num_cpus() > 1) { ret = rtl_reserve_cpus(1 << cpu); if (ret) { rtl_printf("failed to reserve CPU%d for RTLinux\n", cpu); } else { rtl_printf("reserved CPU%d for RTLinux\n", cpu); reserved = 1; } } pthread_attr_setschedparam (&attr, &sched_param); pthread_create (&thread, &attr, thread_code, (void *)1); rtl_printf("created RT-thread\n"); return 0; } void cleanup_module(void) { rtl_printf ("Removing module on CPU %d\n", rtl_getcpuid()); pthread_delete_np (thread); if (reserved) { rtl_unreserve_cpus(); } close(fd_fifo); rtf_destroy(0); } static void *thread_code(void *param) { hrtime_t expected; hrtime_t diff; hrtime_t now; hrtime_t min_diff; hrtime_t max_diff; struct sample samp; int i; int cnt = 0; int cpu_id = rtl_getcpuid(); rtl_printf ("Measurement task starts on CPU %d\n", cpu_id); expected = clock_gethrtime(CLOCK_REALTIME) + 2 * (hrtime_t) period; if (advance) { pthread_make_periodic_np (pthread_self(), expected - advance, period); } else { pthread_make_periodic_np (pthread_self(), expected, period); } fd_fifo = open("/dev/rtf0", O_NONBLOCK); if (fd_fifo < 0) { rtl_printf("/dev/rtf0 open returned %d\n", fd_fifo); return (void *) -1; } if (advance) { rtl_stop_interrupts(); /* Be careful with this! The task won't be preempted by anything else. This is probably only appropriate for small high-priority tasks. */ } do { min_diff = 2000000000; max_diff = -2000000000; for (i = 0; i < ntests; i++) { ++cnt; pthread_wait_np(); now = clock_gethrtime(CLOCK_MONOTONIC); if (advance) { if (now < expected) { rtl_delay (expected - now); } now = clock_gethrtime(CLOCK_MONOTONIC); } diff = now - expected; if (diff < min_diff) { min_diff = diff; } if (diff > max_diff) { max_diff = diff; } expected += period; } samp.min = min_diff; samp.max = max_diff; write (fd_fifo, &samp, sizeof(samp)); } while (1); return 0; }