The material found here has been derived from a similar directory distributed
with RTLinux 1.2a.

This directory contains a test module to make, if needed, a fine tuning of the
oneshot real-time scheduler.
The idea here is to measure the difference in time between the expected 
switch time and the time when a task is actually called by the scheduler.

1. Install rtl_fifo and rtl_sched modules by running:
	> insmod Your_RTLinux_DIR/modules/rtl_fifo  
	> insmod Your_RTLinux_DIR/modules/rtl_sched
2. Install tune_me module by running:
	> insmod rt_process
3. Run "check" program.

The output:
Check will print a sequence of 3 "miss" numbers (nanosecs) - min, max, average.
Use these numbers to change LATENCY value in rtl_sched.c or to set the
it at rtl_sched installation by typing
"insmod Your_RTLinux_DIR/modules/rtl_sched Latency= where  is 
derived from running check and should make the average value printed by it
approximately zero. In practice that means you should set LATENCY to the
average value printed by check if this is greater than 500. Tuning beyond such
a precision is illusory. 


#include <stdio.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>

#include <asm/rt_time.h>
#include <rtl_fifo.h>

#include "common.h"

int main()
{
	int fd0;
	struct sample samp;
	
	if ((fd0 = open("/dev/rtf0", O_RDONLY)) < 0) {
		fprintf(stderr, "Error opening /dev/rtf1\n");
		exit(1);
	}


	while (1) {
		read(fd0, &samp, sizeof(samp));
		printf("*** min: %8d, max: %8d average: %d ***\n", (int) samp.min, (int) samp.max, samp.index);
		fflush(stdout);
	}

	return 0;
}

#define MODULE
#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/io.h>

#include <asm/rt_irq.h>
#include <asm/rt_time.h>
#include <rtl_fifo.h>
#include <rtl_sched.h>

#include "common.h"

#define TIMEOUT 100000
#define SKIP 4000
#define USE_FPU 0

int period;
RTIME expected;
RT_TASK task;
struct sample samp;

void fun(int task) {

	int diff;
	int skip;
	int average;
	int min_diff;
	int max_diff;

	while (1) {
		min_diff = 1000000000;
		max_diff = -1000000000;
		average = 0;

		for (skip = 0; skip < SKIP; skip++) {
			expected += period;
			rt_task_wait_period();

			diff = (int)count2nano(rt_get_time() - expected);
			if (diff < min_diff) {
				min_diff = diff;
			}
			if (diff > max_diff) {
				max_diff = diff;
			}
		average += diff;
		}
		samp.min = min_diff;
		samp.max = max_diff;
		samp.index = average/SKIP;
		rtf_put(DEBUG_FIFO, &samp, sizeof(samp));
	}
}

int init_module(void)
{
	RTIME start;
	rtf_create(DEBUG_FIFO, 16000);
	rt_linux_use_fpu(USE_FPU);
	rt_task_init(&task, fun, 0, 3000, 0, USE_FPU, 0);
	rt_set_oneshot_mode();
	period = start_rt_timer(nano2count(200000));
	start = rt_get_time() + nano2count(10000000);
	expected = start;
	rt_task_make_periodic(&task, start, period);
	return 0;
}

void cleanup_module(void)
{
	rtf_destroy(DEBUG_FIFO);
	stop_rt_timer();	
	rt_task_delete(&task);
}