16acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak/******************************************************************************
26acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *
31378205b23aad2d399f74f0ab2e97a1cd3f8ecf9subrata_modak *   Copyright © International Business Machines  Corp., 2006-2008
46acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *
56acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *   This program is free software;  you can redistribute it and/or modify
66acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *   it under the terms of the GNU General Public License as published by
76acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *   the Free Software Foundation; either version 2 of the License, or
86acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *   (at your option) any later version.
96acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *
106acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *   This program is distributed in the hope that it will be useful,
116acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
126acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
136acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *   the GNU General Public License for more details.
146acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *
156acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *   You should have received a copy of the GNU General Public License
166acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *   along with this program;  if not, write to the Free Software
174548c6cf9bcdd96d8303caa4130ab638b61f8a30Wanlong Gao *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
186acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *
196acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak * NAME
206acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *      sched_jitter.c
216acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *
226acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak * DESCRIPTION
236acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *      This test measures scheduling jitter w/ realtime processes.
246acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *
251378205b23aad2d399f74f0ab2e97a1cd3f8ecf9subrata_modak *      It spawns a realtime thread that repeatedly times how long it takes to
261378205b23aad2d399f74f0ab2e97a1cd3f8ecf9subrata_modak *      do a fixed amount of work. It then prints out the maximum jitter seen
271378205b23aad2d399f74f0ab2e97a1cd3f8ecf9subrata_modak *      (longest execution time - the shortest execution time).
281378205b23aad2d399f74f0ab2e97a1cd3f8ecf9subrata_modak *      It also spawns off a realtime thread of higher priority that simply
291378205b23aad2d399f74f0ab2e97a1cd3f8ecf9subrata_modak *      wakes up and goes back to sleep. This tries to measure how much overhead
301378205b23aad2d399f74f0ab2e97a1cd3f8ecf9subrata_modak *      the scheduler adds in switching quickly to another task and back.
316acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *
326acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak * USAGE:
336acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *      Use run_auto.sh script in current directory to build and run test.
346acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *
356acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak * AUTHOR
361378205b23aad2d399f74f0ab2e97a1cd3f8ecf9subrata_modak *      John Stultz <johnstul@us.ibm.com>
376acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *
386acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak * HISTORY
391378205b23aad2d399f74f0ab2e97a1cd3f8ecf9subrata_modak *      2006-May-05: Initial version by John Stultz <johnstul@us.ibm.com>
401378205b23aad2d399f74f0ab2e97a1cd3f8ecf9subrata_modak *      2007-July-18: Support to gather stats by Ankita Garg <ankita@in.ibm.com>
416acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *
42aacd331fd8aefb25e888c518dae9153a1ca9d43dsubrata_modak *      This line has to be added to avoid a stupid CVS problem
436acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak *****************************************************************************/
446acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
456acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak#include <stdio.h>
466acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak#include <time.h>
476acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak#include <pthread.h>
486acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak#include <sched.h>
496acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak#include <unistd.h>
506acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak#include <libstats.h>
516acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak#include <librttest.h>
526acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
536acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak#define NUMRUNS 1000
546acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak#define NUMLOOPS 1000000
556acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak#define NSEC_PER_SEC 1000000000
566acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak#define WORKLEN 64
576acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak#define ISLEEP 50000
586acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
596acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modakint array[WORKLEN];
606acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
61354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovolatile int flag;		/*let interrupter know we're done */
626acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
636acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modakvoid usage(void)
646acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak{
657d0a4a57fbcd47f72b67c08df532e8ef47f6fdaeGarrett Cooper	rt_help();
667d0a4a57fbcd47f72b67c08df532e8ef47f6fdaeGarrett Cooper	printf("sched_jitter specific options:\n");
676acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak}
686acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
696acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modakint parse_args(int c, char *v)
706acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak{
716acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
727d0a4a57fbcd47f72b67c08df532e8ef47f6fdaeGarrett Cooper	int handled = 1;
737d0a4a57fbcd47f72b67c08df532e8ef47f6fdaeGarrett Cooper	switch (c) {
74354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	case 'h':
75354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		usage();
76354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(0);
77354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	default:
78354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		handled = 0;
79354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		break;
807d0a4a57fbcd47f72b67c08df532e8ef47f6fdaeGarrett Cooper	}
817d0a4a57fbcd47f72b67c08df532e8ef47f6fdaeGarrett Cooper	return handled;
826acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak}
836acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
84354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaounsigned long long ts_sub(struct timespec a, struct timespec b)
856acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak{
866acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	unsigned long long first, second;
876acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
886acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	first = (unsigned long long)a.tv_sec * NSEC_PER_SEC + a.tv_nsec;
896acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	second = (unsigned long long)b.tv_sec * NSEC_PER_SEC + b.tv_nsec;
906acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	return first - second;
916acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak}
926acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
936acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modakvoid print_unit(unsigned long long val)
946acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak{
956acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	if (val > 1000000)
96354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("%f ms\n", (float)(val) / 1000000);
976acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	else if (val > 1000)
98354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		printf("%f us\n", (float)(val) / 1000);
996acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	else
1006acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak		printf("%f ns\n", (float)val);
1016acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
1026acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak}
1036acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
1046acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modakvoid do_work(int runs)
1056acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak{
1066acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	int i, j;
107354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	for (i = 0; i < runs; i++) {
108354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		for (j = 0; j < WORKLEN - 1; j++)
109354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			array[j] = array[j] + array[j + 1];
110354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		for (j = 0; j < WORKLEN - 1; j++)
111354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			array[j] = array[j] - array[j + 1];
1126acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	}
1136acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak}
1146acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
115354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid *thread_worker(void *arg)
1166acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak{
1176acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	struct timespec start, stop;
1186acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	int i;
1196acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	unsigned long long delta;
120354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	unsigned long long min = -1, max = 0;
1216acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
1226acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	stats_container_t dat;
1231897ec4e75abb88c0c249e759036b20a339e456csubrata_modak	stats_record_t rec;
1246acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
1256acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	stats_container_init(&dat, NUMRUNS);
1266acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
127354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	for (i = 0; i < NUMRUNS; i++) {
1286acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
129354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		do_work(1);	/* warm cache */
1306acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
1316acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak		/* do test */
1326acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak		clock_gettime(CLOCK_MONOTONIC, &start);
1336acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak		do_work(NUMLOOPS);
1346acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak		clock_gettime(CLOCK_MONOTONIC, &stop);
1356acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
1366acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak		/* calc delta, min and max */
1376acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak		delta = ts_sub(stop, start);
1386acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak		if (delta < min)
1396acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak			min = delta;
140354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (delta > max)
1416acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak			max = delta;
1421897ec4e75abb88c0c249e759036b20a339e456csubrata_modak		rec.x = i;
1431897ec4e75abb88c0c249e759036b20a339e456csubrata_modak		rec.y = delta;
1441897ec4e75abb88c0c249e759036b20a339e456csubrata_modak		stats_container_append(&dat, rec);
1456acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
1466acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak		printf("delta: %llu ns\n", delta);
147354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		usleep(1);	/* let other things happen */
1486acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	}
1496acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
1506acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	printf("max jitter: ");
1516acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	print_unit(max - min);
152354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	stats_container_save("samples", "Scheduling Jitter Scatter Plot",
153354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			     "Iteration", "Delay (ns)", &dat, "points");
1546acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	return NULL;
1556acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak}
1566acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
157354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid *thread_interrupter(void *arg)
1586acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak{
1596acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	while (!flag)
160354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		usleep(ISLEEP);
1616acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	return NULL;
1626acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak}
1636acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
1646acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modakint main(int argc, char *argv[])
1656acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak{
1664ada1ca5036b7ebe90f3922696f45fbc3b362ef9subrata_modak	int worker, interrupter;
1674ada1ca5036b7ebe90f3922696f45fbc3b362ef9subrata_modak
1686acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	setup();
1696acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
170354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	rt_init("h", parse_args, argc, argv);
1716acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
1724ada1ca5036b7ebe90f3922696f45fbc3b362ef9subrata_modak	interrupter = create_fifo_thread(thread_interrupter, NULL, 80);
1736acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	sleep(1);
1744ada1ca5036b7ebe90f3922696f45fbc3b362ef9subrata_modak	worker = create_fifo_thread(thread_worker, NULL, 10);
1756acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
1764ada1ca5036b7ebe90f3922696f45fbc3b362ef9subrata_modak	join_thread(worker);
1776acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak	flag = 1;
1784ada1ca5036b7ebe90f3922696f45fbc3b362ef9subrata_modak	join_thread(interrupter);
1796acdc8efa73ceb0c3b515cd34c333d929e8b4273subrata_modak
180ef78227f9275d780649e14a8785c6913c18b7462Cyril Hrubis	return 0;
181ef78227f9275d780649e14a8785c6913c18b7462Cyril Hrubis}
182