xref: /aosp_15_r20/external/ltp/testcases/realtime/func/rt-migrate/rt-migrate.c (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
1*49cdfc7eSAndroid Build Coastguard Worker 
2*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************
3*49cdfc7eSAndroid Build Coastguard Worker  *
4*49cdfc7eSAndroid Build Coastguard Worker  * Copyright (C) 2007-2009 Steven Rostedt <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker  *
6*49cdfc7eSAndroid Build Coastguard Worker  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7*49cdfc7eSAndroid Build Coastguard Worker  *
8*49cdfc7eSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or modify
9*49cdfc7eSAndroid Build Coastguard Worker  * it under the terms of the GNU General Public License as published by
10*49cdfc7eSAndroid Build Coastguard Worker  * the Free Software Foundation; version 2 of the License (not later!)
11*49cdfc7eSAndroid Build Coastguard Worker  *
12*49cdfc7eSAndroid Build Coastguard Worker  * This program is distributed in the hope that it will be useful,
13*49cdfc7eSAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*49cdfc7eSAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*49cdfc7eSAndroid Build Coastguard Worker  * GNU General Public License for more details.
16*49cdfc7eSAndroid Build Coastguard Worker  *
17*49cdfc7eSAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License
18*49cdfc7eSAndroid Build Coastguard Worker  * along with this program; if not, write to the Free Software
19*49cdfc7eSAndroid Build Coastguard Worker  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20*49cdfc7eSAndroid Build Coastguard Worker  *
21*49cdfc7eSAndroid Build Coastguard Worker  * NAME
22*49cdfc7eSAndroid Build Coastguard Worker  *      rt-migrate-test.c
23*49cdfc7eSAndroid Build Coastguard Worker  *
24*49cdfc7eSAndroid Build Coastguard Worker  * DESCRIPTION
25*49cdfc7eSAndroid Build Coastguard Worker  *	This test makes sure that all the high prio tasks that are in the
26*49cdfc7eSAndroid Build Coastguard Worker  *	running state are actually running on a CPU if it can.
27*49cdfc7eSAndroid Build Coastguard Worker  ** Steps:
28*49cdfc7eSAndroid Build Coastguard Worker  *	- Creates N+1 threads with lower real time priorities.
29*49cdfc7eSAndroid Build Coastguard Worker  *	  Where N is the number of CPUs in the system.
30*49cdfc7eSAndroid Build Coastguard Worker  *	- If the thread is high priority, and if a CPU is available, the
31*49cdfc7eSAndroid Build Coastguard Worker  *	  thread runs on that CPU.
32*49cdfc7eSAndroid Build Coastguard Worker  *	- The thread records the start time and the number of ticks in the run
33*49cdfc7eSAndroid Build Coastguard Worker  *	  interval.
34*49cdfc7eSAndroid Build Coastguard Worker  *	- The output indicates if lower prio task is quicker than higher
35*49cdfc7eSAndroid Build Coastguard Worker  *	  priority task.
36*49cdfc7eSAndroid Build Coastguard Worker  *
37*49cdfc7eSAndroid Build Coastguard Worker  * USAGE:
38*49cdfc7eSAndroid Build Coastguard Worker  *	Use run_auto.sh in the current directory to build and run the test.
39*49cdfc7eSAndroid Build Coastguard Worker  *
40*49cdfc7eSAndroid Build Coastguard Worker  * AUTHOR
41*49cdfc7eSAndroid Build Coastguard Worker  *      Steven Rostedt <[email protected]>
42*49cdfc7eSAndroid Build Coastguard Worker  *
43*49cdfc7eSAndroid Build Coastguard Worker  * HISTORY
44*49cdfc7eSAndroid Build Coastguard Worker  *      30 July, 2009: Initial version by Steven Rostedt
45*49cdfc7eSAndroid Build Coastguard Worker  *      11 Aug, 2009: Converted the coding style to the one used by the realtime
46*49cdfc7eSAndroid Build Coastguard Worker  *		    testcases by Kiran Prakash
47*49cdfc7eSAndroid Build Coastguard Worker  *
48*49cdfc7eSAndroid Build Coastguard Worker  */
49*49cdfc7eSAndroid Build Coastguard Worker #ifndef _GNU_SOURCE
50*49cdfc7eSAndroid Build Coastguard Worker #define _GNU_SOURCE
51*49cdfc7eSAndroid Build Coastguard Worker #endif
52*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
53*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
54*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
55*49cdfc7eSAndroid Build Coastguard Worker #include <getopt.h>
56*49cdfc7eSAndroid Build Coastguard Worker #include <stdarg.h>
57*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
58*49cdfc7eSAndroid Build Coastguard Worker #include <ctype.h>
59*49cdfc7eSAndroid Build Coastguard Worker #include <time.h>
60*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
61*49cdfc7eSAndroid Build Coastguard Worker #include <sys/stat.h>
62*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
63*49cdfc7eSAndroid Build Coastguard Worker #include <signal.h>
64*49cdfc7eSAndroid Build Coastguard Worker #include <sys/time.h>
65*49cdfc7eSAndroid Build Coastguard Worker #include <linux/unistd.h>
66*49cdfc7eSAndroid Build Coastguard Worker #include <sys/syscall.h>
67*49cdfc7eSAndroid Build Coastguard Worker #include <errno.h>
68*49cdfc7eSAndroid Build Coastguard Worker #include <sched.h>
69*49cdfc7eSAndroid Build Coastguard Worker #include <pthread.h>
70*49cdfc7eSAndroid Build Coastguard Worker #include <librttest.h>
71*49cdfc7eSAndroid Build Coastguard Worker #include <libstats.h>
72*49cdfc7eSAndroid Build Coastguard Worker 
73*49cdfc7eSAndroid Build Coastguard Worker #define gettid() syscall(__NR_gettid)
74*49cdfc7eSAndroid Build Coastguard Worker 
75*49cdfc7eSAndroid Build Coastguard Worker #define VERSION_STRING "V 0.4LTP"
76*49cdfc7eSAndroid Build Coastguard Worker 
77*49cdfc7eSAndroid Build Coastguard Worker #define CLAMP(x, lower, upper) (MIN(upper, MAX(x, lower)))
78*49cdfc7eSAndroid Build Coastguard Worker #define CLAMP_PRIO(prio) CLAMP(prio, prio_min, prio_max)
79*49cdfc7eSAndroid Build Coastguard Worker 
80*49cdfc7eSAndroid Build Coastguard Worker int nr_tasks;
81*49cdfc7eSAndroid Build Coastguard Worker int lfd;
82*49cdfc7eSAndroid Build Coastguard Worker 
83*49cdfc7eSAndroid Build Coastguard Worker int numcpus;
84*49cdfc7eSAndroid Build Coastguard Worker static int mark_fd = -1;
85*49cdfc7eSAndroid Build Coastguard Worker static __thread char buff[BUFSIZ + 1];
86*49cdfc7eSAndroid Build Coastguard Worker 
setup_ftrace_marker(void)87*49cdfc7eSAndroid Build Coastguard Worker static void setup_ftrace_marker(void)
88*49cdfc7eSAndroid Build Coastguard Worker {
89*49cdfc7eSAndroid Build Coastguard Worker 	struct stat st;
90*49cdfc7eSAndroid Build Coastguard Worker 	char *files[] = {
91*49cdfc7eSAndroid Build Coastguard Worker 		"/sys/kernel/debug/tracing/trace_marker",
92*49cdfc7eSAndroid Build Coastguard Worker 		"/debug/tracing/trace_marker",
93*49cdfc7eSAndroid Build Coastguard Worker 		"/debugfs/tracing/trace_marker",
94*49cdfc7eSAndroid Build Coastguard Worker 	};
95*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
96*49cdfc7eSAndroid Build Coastguard Worker 	int i;
97*49cdfc7eSAndroid Build Coastguard Worker 
98*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < (sizeof(files) / sizeof(char *)); i++) {
99*49cdfc7eSAndroid Build Coastguard Worker 		ret = stat(files[i], &st);
100*49cdfc7eSAndroid Build Coastguard Worker 		if (ret >= 0)
101*49cdfc7eSAndroid Build Coastguard Worker 			goto found;
102*49cdfc7eSAndroid Build Coastguard Worker 	}
103*49cdfc7eSAndroid Build Coastguard Worker 	/* todo, check mounts system */
104*49cdfc7eSAndroid Build Coastguard Worker 	return;
105*49cdfc7eSAndroid Build Coastguard Worker found:
106*49cdfc7eSAndroid Build Coastguard Worker 	mark_fd = open(files[i], O_WRONLY);
107*49cdfc7eSAndroid Build Coastguard Worker }
108*49cdfc7eSAndroid Build Coastguard Worker 
ftrace_write(const char * fmt,...)109*49cdfc7eSAndroid Build Coastguard Worker static void ftrace_write(const char *fmt, ...)
110*49cdfc7eSAndroid Build Coastguard Worker {
111*49cdfc7eSAndroid Build Coastguard Worker 	va_list ap;
112*49cdfc7eSAndroid Build Coastguard Worker 	int n;
113*49cdfc7eSAndroid Build Coastguard Worker 
114*49cdfc7eSAndroid Build Coastguard Worker 	if (mark_fd < 0)
115*49cdfc7eSAndroid Build Coastguard Worker 		return;
116*49cdfc7eSAndroid Build Coastguard Worker 
117*49cdfc7eSAndroid Build Coastguard Worker 	va_start(ap, fmt);
118*49cdfc7eSAndroid Build Coastguard Worker 	n = vsnprintf(buff, BUFSIZ, fmt, ap);
119*49cdfc7eSAndroid Build Coastguard Worker 	va_end(ap);
120*49cdfc7eSAndroid Build Coastguard Worker 
121*49cdfc7eSAndroid Build Coastguard Worker 	/*
122*49cdfc7eSAndroid Build Coastguard Worker 	 * This doesn't return any valid vs invalid exit codes, so printing out
123*49cdfc7eSAndroid Build Coastguard Worker 	 * a perror to warn the end-user of an issue is sufficient.
124*49cdfc7eSAndroid Build Coastguard Worker 	 */
125*49cdfc7eSAndroid Build Coastguard Worker 	if (write(mark_fd, buff, n) < 0) {
126*49cdfc7eSAndroid Build Coastguard Worker 		perror("write");
127*49cdfc7eSAndroid Build Coastguard Worker 	}
128*49cdfc7eSAndroid Build Coastguard Worker }
129*49cdfc7eSAndroid Build Coastguard Worker 
130*49cdfc7eSAndroid Build Coastguard Worker #define INTERVAL 100ULL * NS_PER_MS
131*49cdfc7eSAndroid Build Coastguard Worker #define RUN_INTERVAL 20ULL * NS_PER_MS
132*49cdfc7eSAndroid Build Coastguard Worker #define NR_RUNS 50
133*49cdfc7eSAndroid Build Coastguard Worker #define PRIO_START 2
134*49cdfc7eSAndroid Build Coastguard Worker /* 1 millisec off */
135*49cdfc7eSAndroid Build Coastguard Worker #define MAX_ERR  1000 * NS_PER_US
136*49cdfc7eSAndroid Build Coastguard Worker 
137*49cdfc7eSAndroid Build Coastguard Worker #define PROGRESS_CHARS 70
138*49cdfc7eSAndroid Build Coastguard Worker 
139*49cdfc7eSAndroid Build Coastguard Worker static unsigned long long interval = INTERVAL;
140*49cdfc7eSAndroid Build Coastguard Worker static unsigned long long run_interval = RUN_INTERVAL;
141*49cdfc7eSAndroid Build Coastguard Worker static unsigned long long max_err = MAX_ERR;
142*49cdfc7eSAndroid Build Coastguard Worker static int nr_runs = NR_RUNS;
143*49cdfc7eSAndroid Build Coastguard Worker static int prio_start = PRIO_START, prio_min, prio_max;
144*49cdfc7eSAndroid Build Coastguard Worker static int check = 1;
145*49cdfc7eSAndroid Build Coastguard Worker static int stop;
146*49cdfc7eSAndroid Build Coastguard Worker 
147*49cdfc7eSAndroid Build Coastguard Worker static unsigned long long now;
148*49cdfc7eSAndroid Build Coastguard Worker 
149*49cdfc7eSAndroid Build Coastguard Worker static int done;
150*49cdfc7eSAndroid Build Coastguard Worker static int loop;
151*49cdfc7eSAndroid Build Coastguard Worker 
152*49cdfc7eSAndroid Build Coastguard Worker static pthread_barrier_t start_barrier;
153*49cdfc7eSAndroid Build Coastguard Worker static pthread_barrier_t end_barrier;
154*49cdfc7eSAndroid Build Coastguard Worker stats_container_t *intervals;
155*49cdfc7eSAndroid Build Coastguard Worker stats_container_t *intervals_length;
156*49cdfc7eSAndroid Build Coastguard Worker stats_container_t *intervals_loops;
157*49cdfc7eSAndroid Build Coastguard Worker static long *thread_pids;
158*49cdfc7eSAndroid Build Coastguard Worker 
print_progress_bar(int percent)159*49cdfc7eSAndroid Build Coastguard Worker static void print_progress_bar(int percent)
160*49cdfc7eSAndroid Build Coastguard Worker {
161*49cdfc7eSAndroid Build Coastguard Worker 	int i;
162*49cdfc7eSAndroid Build Coastguard Worker 	int p;
163*49cdfc7eSAndroid Build Coastguard Worker 
164*49cdfc7eSAndroid Build Coastguard Worker 	if (percent > 100)
165*49cdfc7eSAndroid Build Coastguard Worker 		percent = 100;
166*49cdfc7eSAndroid Build Coastguard Worker 
167*49cdfc7eSAndroid Build Coastguard Worker 	/* Use stderr, so we don't capture it */
168*49cdfc7eSAndroid Build Coastguard Worker 	putc('\r', stderr);
169*49cdfc7eSAndroid Build Coastguard Worker 	putc('|', stderr);
170*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < PROGRESS_CHARS; i++)
171*49cdfc7eSAndroid Build Coastguard Worker 		putc(' ', stderr);
172*49cdfc7eSAndroid Build Coastguard Worker 	putc('|', stderr);
173*49cdfc7eSAndroid Build Coastguard Worker 	putc('\r', stderr);
174*49cdfc7eSAndroid Build Coastguard Worker 	putc('|', stderr);
175*49cdfc7eSAndroid Build Coastguard Worker 
176*49cdfc7eSAndroid Build Coastguard Worker 	p = PROGRESS_CHARS * percent / 100;
177*49cdfc7eSAndroid Build Coastguard Worker 
178*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < p; i++)
179*49cdfc7eSAndroid Build Coastguard Worker 		putc('-', stderr);
180*49cdfc7eSAndroid Build Coastguard Worker 
181*49cdfc7eSAndroid Build Coastguard Worker 	fflush(stderr);
182*49cdfc7eSAndroid Build Coastguard Worker }
183*49cdfc7eSAndroid Build Coastguard Worker 
usage()184*49cdfc7eSAndroid Build Coastguard Worker static void usage()
185*49cdfc7eSAndroid Build Coastguard Worker {
186*49cdfc7eSAndroid Build Coastguard Worker 	rt_help();
187*49cdfc7eSAndroid Build Coastguard Worker 	printf("Usage:\n"
188*49cdfc7eSAndroid Build Coastguard Worker 	       "-a priority Priority of the threads"
189*49cdfc7eSAndroid Build Coastguard Worker 	       "-r time     Run time (ms) to busy loop the threads (20)\n"
190*49cdfc7eSAndroid Build Coastguard Worker 	       "-t time     Sleep time (ms) between intervals (100)\n"
191*49cdfc7eSAndroid Build Coastguard Worker 	       "-e time     Max allowed error (microsecs)\n"
192*49cdfc7eSAndroid Build Coastguard Worker 	       "-l loops    Number of iterations to run (50)\n");
193*49cdfc7eSAndroid Build Coastguard Worker }
194*49cdfc7eSAndroid Build Coastguard Worker 
195*49cdfc7eSAndroid Build Coastguard Worker /*
196*49cdfc7eSAndroid Build Coastguard Worker int rt_init(const char *options, int (*parse_arg)(int option, char *value),
197*49cdfc7eSAndroid Build Coastguard Worker 	    int argc, char *argv[]);
198*49cdfc7eSAndroid Build Coastguard Worker  */
parse_args(int c,char * v)199*49cdfc7eSAndroid Build Coastguard Worker static int parse_args(int c, char *v)
200*49cdfc7eSAndroid Build Coastguard Worker {
201*49cdfc7eSAndroid Build Coastguard Worker 	int handled = 1;
202*49cdfc7eSAndroid Build Coastguard Worker 	switch (c) {
203*49cdfc7eSAndroid Build Coastguard Worker 	case 'a':
204*49cdfc7eSAndroid Build Coastguard Worker 		prio_start = atoi(v);
205*49cdfc7eSAndroid Build Coastguard Worker 		break;
206*49cdfc7eSAndroid Build Coastguard Worker 	case 'r':
207*49cdfc7eSAndroid Build Coastguard Worker 		run_interval = atoi(v);
208*49cdfc7eSAndroid Build Coastguard Worker 		break;
209*49cdfc7eSAndroid Build Coastguard Worker 	case 't':
210*49cdfc7eSAndroid Build Coastguard Worker 		interval = atoi(v);
211*49cdfc7eSAndroid Build Coastguard Worker 		break;
212*49cdfc7eSAndroid Build Coastguard Worker 	case 'l':
213*49cdfc7eSAndroid Build Coastguard Worker 		nr_runs = atoi(v);
214*49cdfc7eSAndroid Build Coastguard Worker 		break;
215*49cdfc7eSAndroid Build Coastguard Worker 	case 'e':
216*49cdfc7eSAndroid Build Coastguard Worker 		max_err = atoi(v) * NS_PER_US;
217*49cdfc7eSAndroid Build Coastguard Worker 		break;
218*49cdfc7eSAndroid Build Coastguard Worker 	case '?':
219*49cdfc7eSAndroid Build Coastguard Worker 	case 'h':
220*49cdfc7eSAndroid Build Coastguard Worker 		usage();
221*49cdfc7eSAndroid Build Coastguard Worker 		handled = 0;
222*49cdfc7eSAndroid Build Coastguard Worker 	}
223*49cdfc7eSAndroid Build Coastguard Worker 	return handled;
224*49cdfc7eSAndroid Build Coastguard Worker }
225*49cdfc7eSAndroid Build Coastguard Worker 
record_time(int id,unsigned long long time,unsigned long l)226*49cdfc7eSAndroid Build Coastguard Worker static void record_time(int id, unsigned long long time, unsigned long l)
227*49cdfc7eSAndroid Build Coastguard Worker {
228*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long long ltime;
229*49cdfc7eSAndroid Build Coastguard Worker 	stats_record_t rec;
230*49cdfc7eSAndroid Build Coastguard Worker 	if (loop >= nr_runs)
231*49cdfc7eSAndroid Build Coastguard Worker 		return;
232*49cdfc7eSAndroid Build Coastguard Worker 	time -= now;
233*49cdfc7eSAndroid Build Coastguard Worker 	ltime = rt_gettime() / NS_PER_US;
234*49cdfc7eSAndroid Build Coastguard Worker 	ltime -= now;
235*49cdfc7eSAndroid Build Coastguard Worker 	rec.x = loop;
236*49cdfc7eSAndroid Build Coastguard Worker 	rec.y = time;
237*49cdfc7eSAndroid Build Coastguard Worker 	stats_container_append(&intervals[id], rec);
238*49cdfc7eSAndroid Build Coastguard Worker 	rec.x = loop;
239*49cdfc7eSAndroid Build Coastguard Worker 	rec.y = ltime;
240*49cdfc7eSAndroid Build Coastguard Worker 	stats_container_append(&intervals_length[id], rec);
241*49cdfc7eSAndroid Build Coastguard Worker 	rec.x = loop;
242*49cdfc7eSAndroid Build Coastguard Worker 	rec.y = l;
243*49cdfc7eSAndroid Build Coastguard Worker 	stats_container_append(&intervals_loops[id], rec);
244*49cdfc7eSAndroid Build Coastguard Worker }
245*49cdfc7eSAndroid Build Coastguard Worker 
print_results(void)246*49cdfc7eSAndroid Build Coastguard Worker static void print_results(void)
247*49cdfc7eSAndroid Build Coastguard Worker {
248*49cdfc7eSAndroid Build Coastguard Worker 	int i;
249*49cdfc7eSAndroid Build Coastguard Worker 	int t;
250*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long long tasks_max[nr_tasks];
251*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long long tasks_min[nr_tasks];
252*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long long tasks_avg[nr_tasks];
253*49cdfc7eSAndroid Build Coastguard Worker 
254*49cdfc7eSAndroid Build Coastguard Worker 	memset(tasks_max, 0, sizeof(tasks_max[0]) * nr_tasks);
255*49cdfc7eSAndroid Build Coastguard Worker 	memset(tasks_min, 0xff, sizeof(tasks_min[0]) * nr_tasks);
256*49cdfc7eSAndroid Build Coastguard Worker 	memset(tasks_avg, 0, sizeof(tasks_avg[0]) * nr_tasks);
257*49cdfc7eSAndroid Build Coastguard Worker 
258*49cdfc7eSAndroid Build Coastguard Worker 	printf("Iter: ");
259*49cdfc7eSAndroid Build Coastguard Worker 	for (t = 0; t < nr_tasks; t++)
260*49cdfc7eSAndroid Build Coastguard Worker 		printf("%6d  ", t);
261*49cdfc7eSAndroid Build Coastguard Worker 	printf("\n");
262*49cdfc7eSAndroid Build Coastguard Worker 
263*49cdfc7eSAndroid Build Coastguard Worker 	for (t = 0; t < nr_tasks; t++) {
264*49cdfc7eSAndroid Build Coastguard Worker 		tasks_max[t] = stats_max(&intervals[t]);
265*49cdfc7eSAndroid Build Coastguard Worker 		tasks_min[t] = stats_min(&intervals[t]);
266*49cdfc7eSAndroid Build Coastguard Worker 		tasks_avg[t] = stats_avg(&intervals[t]);
267*49cdfc7eSAndroid Build Coastguard Worker 	}
268*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < nr_runs; i++) {
269*49cdfc7eSAndroid Build Coastguard Worker 		printf("%4d:   ", i);
270*49cdfc7eSAndroid Build Coastguard Worker 		for (t = 0; t < nr_tasks; t++)
271*49cdfc7eSAndroid Build Coastguard Worker 			printf("%6ld  ", intervals[t].records[i].y);
272*49cdfc7eSAndroid Build Coastguard Worker 
273*49cdfc7eSAndroid Build Coastguard Worker 		printf("\n");
274*49cdfc7eSAndroid Build Coastguard Worker 		printf(" len:   ");
275*49cdfc7eSAndroid Build Coastguard Worker 		for (t = 0; t < nr_tasks; t++)
276*49cdfc7eSAndroid Build Coastguard Worker 			printf("%6ld  ", intervals_length[t].records[i].y);
277*49cdfc7eSAndroid Build Coastguard Worker 
278*49cdfc7eSAndroid Build Coastguard Worker 		printf("\n");
279*49cdfc7eSAndroid Build Coastguard Worker 		printf(" loops: ");
280*49cdfc7eSAndroid Build Coastguard Worker 		for (t = 0; t < nr_tasks; t++)
281*49cdfc7eSAndroid Build Coastguard Worker 			printf("%6ld  ", intervals_loops[t].records[i].y);
282*49cdfc7eSAndroid Build Coastguard Worker 
283*49cdfc7eSAndroid Build Coastguard Worker 		printf("\n");
284*49cdfc7eSAndroid Build Coastguard Worker 		printf("\n");
285*49cdfc7eSAndroid Build Coastguard Worker 	}
286*49cdfc7eSAndroid Build Coastguard Worker 
287*49cdfc7eSAndroid Build Coastguard Worker 	printf("Parent pid: %d\n", getpid());
288*49cdfc7eSAndroid Build Coastguard Worker 
289*49cdfc7eSAndroid Build Coastguard Worker 	for (t = 0; t < nr_tasks; t++) {
290*49cdfc7eSAndroid Build Coastguard Worker 		printf(" Task %d (prio %d) (pid %ld):\n", t,
291*49cdfc7eSAndroid Build Coastguard Worker 			   CLAMP_PRIO(t + prio_start), thread_pids[t]);
292*49cdfc7eSAndroid Build Coastguard Worker 		printf("   Max: %lld us\n", tasks_max[t]);
293*49cdfc7eSAndroid Build Coastguard Worker 		printf("   Min: %lld us\n", tasks_min[t]);
294*49cdfc7eSAndroid Build Coastguard Worker 		printf("   Tot: %lld us\n", tasks_avg[t] * nr_runs);
295*49cdfc7eSAndroid Build Coastguard Worker 		printf("   Avg: %lld us\n", tasks_avg[t]);
296*49cdfc7eSAndroid Build Coastguard Worker 		printf("\n");
297*49cdfc7eSAndroid Build Coastguard Worker 	}
298*49cdfc7eSAndroid Build Coastguard Worker 
299*49cdfc7eSAndroid Build Coastguard Worker 	printf(" Result: %s\n", (check < 0) ? "FAIL" : "PASS");
300*49cdfc7eSAndroid Build Coastguard Worker }
301*49cdfc7eSAndroid Build Coastguard Worker 
busy_loop(unsigned long long start_time)302*49cdfc7eSAndroid Build Coastguard Worker static unsigned long busy_loop(unsigned long long start_time)
303*49cdfc7eSAndroid Build Coastguard Worker {
304*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long long time;
305*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long l = 0;
306*49cdfc7eSAndroid Build Coastguard Worker 
307*49cdfc7eSAndroid Build Coastguard Worker 	do {
308*49cdfc7eSAndroid Build Coastguard Worker 		l++;
309*49cdfc7eSAndroid Build Coastguard Worker 		time = rt_gettime();
310*49cdfc7eSAndroid Build Coastguard Worker 	} while ((time - start_time) < RUN_INTERVAL);
311*49cdfc7eSAndroid Build Coastguard Worker 
312*49cdfc7eSAndroid Build Coastguard Worker 	return l;
313*49cdfc7eSAndroid Build Coastguard Worker }
314*49cdfc7eSAndroid Build Coastguard Worker 
start_task(void * data)315*49cdfc7eSAndroid Build Coastguard Worker void *start_task(void *data)
316*49cdfc7eSAndroid Build Coastguard Worker {
317*49cdfc7eSAndroid Build Coastguard Worker 	struct thread *thr = (struct thread *)data;
318*49cdfc7eSAndroid Build Coastguard Worker 	long id = (long)thr->arg;
319*49cdfc7eSAndroid Build Coastguard Worker 	thread_pids[id] = gettid();
320*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long long start_time;
321*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
322*49cdfc7eSAndroid Build Coastguard Worker 	int high = 0;
323*49cdfc7eSAndroid Build Coastguard Worker 	cpu_set_t cpumask;
324*49cdfc7eSAndroid Build Coastguard Worker 	cpu_set_t save_cpumask;
325*49cdfc7eSAndroid Build Coastguard Worker 	int cpu = 0;
326*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long l;
327*49cdfc7eSAndroid Build Coastguard Worker 	long pid;
328*49cdfc7eSAndroid Build Coastguard Worker 
329*49cdfc7eSAndroid Build Coastguard Worker 	ret = sched_getaffinity(0, sizeof(save_cpumask), &save_cpumask);
330*49cdfc7eSAndroid Build Coastguard Worker 	if (ret < 0)
331*49cdfc7eSAndroid Build Coastguard Worker 		debug(DBG_ERR, "sched_getaffinity failed: %s\n", strerror(ret));
332*49cdfc7eSAndroid Build Coastguard Worker 
333*49cdfc7eSAndroid Build Coastguard Worker 	pid = gettid();
334*49cdfc7eSAndroid Build Coastguard Worker 
335*49cdfc7eSAndroid Build Coastguard Worker 	/* Check if we are the highest prio task */
336*49cdfc7eSAndroid Build Coastguard Worker 	if (id == nr_tasks - 1)
337*49cdfc7eSAndroid Build Coastguard Worker 		high = 1;
338*49cdfc7eSAndroid Build Coastguard Worker 
339*49cdfc7eSAndroid Build Coastguard Worker 	while (!done) {
340*49cdfc7eSAndroid Build Coastguard Worker 		if (high) {
341*49cdfc7eSAndroid Build Coastguard Worker 			/* rotate around the CPUS */
342*49cdfc7eSAndroid Build Coastguard Worker 			if (!CPU_ISSET(cpu, &save_cpumask))
343*49cdfc7eSAndroid Build Coastguard Worker 				cpu = 0;
344*49cdfc7eSAndroid Build Coastguard Worker 			CPU_ZERO(&cpumask);
345*49cdfc7eSAndroid Build Coastguard Worker 			CPU_SET(cpu, &cpumask);
346*49cdfc7eSAndroid Build Coastguard Worker 			cpu++;
347*49cdfc7eSAndroid Build Coastguard Worker 			sched_setaffinity(0, sizeof(cpumask), &cpumask);
348*49cdfc7eSAndroid Build Coastguard Worker 		}
349*49cdfc7eSAndroid Build Coastguard Worker 		pthread_barrier_wait(&start_barrier);
350*49cdfc7eSAndroid Build Coastguard Worker 		start_time = rt_gettime();
351*49cdfc7eSAndroid Build Coastguard Worker 		ftrace_write("Thread %d: started %lld diff %lld\n",
352*49cdfc7eSAndroid Build Coastguard Worker 			     pid, start_time, start_time - now);
353*49cdfc7eSAndroid Build Coastguard Worker 		l = busy_loop(start_time);
354*49cdfc7eSAndroid Build Coastguard Worker 		record_time(id, start_time / NS_PER_US, l);
355*49cdfc7eSAndroid Build Coastguard Worker 		pthread_barrier_wait(&end_barrier);
356*49cdfc7eSAndroid Build Coastguard Worker 	}
357*49cdfc7eSAndroid Build Coastguard Worker 
358*49cdfc7eSAndroid Build Coastguard Worker 	return (void *)pid;
359*49cdfc7eSAndroid Build Coastguard Worker }
360*49cdfc7eSAndroid Build Coastguard Worker 
check_times(int l)361*49cdfc7eSAndroid Build Coastguard Worker static int check_times(int l)
362*49cdfc7eSAndroid Build Coastguard Worker {
363*49cdfc7eSAndroid Build Coastguard Worker 	int i;
364*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long long last;
365*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long long last_loops;
366*49cdfc7eSAndroid Build Coastguard Worker 	unsigned long long last_length;
367*49cdfc7eSAndroid Build Coastguard Worker 
368*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < nr_tasks; i++) {
369*49cdfc7eSAndroid Build Coastguard Worker 		if (i && last < intervals[i].records[l].y &&
370*49cdfc7eSAndroid Build Coastguard Worker 		    ((intervals[i].records[l].y - last) > max_err)) {
371*49cdfc7eSAndroid Build Coastguard Worker 			/*
372*49cdfc7eSAndroid Build Coastguard Worker 			 * May be a false positive.
373*49cdfc7eSAndroid Build Coastguard Worker 			 * Make sure that we did more loops
374*49cdfc7eSAndroid Build Coastguard Worker 			 * our start is before the end
375*49cdfc7eSAndroid Build Coastguard Worker 			 * and the end should be tested.
376*49cdfc7eSAndroid Build Coastguard Worker 			 */
377*49cdfc7eSAndroid Build Coastguard Worker 			if (intervals_loops[i].records[l].y < last_loops ||
378*49cdfc7eSAndroid Build Coastguard Worker 			    intervals[i].records[l].y > last_length ||
379*49cdfc7eSAndroid Build Coastguard Worker 			    (intervals_length[i].records[l].y > last_length &&
380*49cdfc7eSAndroid Build Coastguard Worker 			     intervals_length[i].records[l].y - last_length >
381*49cdfc7eSAndroid Build Coastguard Worker 			     max_err)) {
382*49cdfc7eSAndroid Build Coastguard Worker 				check = -1;
383*49cdfc7eSAndroid Build Coastguard Worker 				return 1;
384*49cdfc7eSAndroid Build Coastguard Worker 			}
385*49cdfc7eSAndroid Build Coastguard Worker 		}
386*49cdfc7eSAndroid Build Coastguard Worker 		last = intervals[i].records[l].y;
387*49cdfc7eSAndroid Build Coastguard Worker 		last_loops = intervals_loops[i].records[l].y;
388*49cdfc7eSAndroid Build Coastguard Worker 		last_length = intervals_length[i].records[l].y;
389*49cdfc7eSAndroid Build Coastguard Worker 	}
390*49cdfc7eSAndroid Build Coastguard Worker 	return 0;
391*49cdfc7eSAndroid Build Coastguard Worker }
392*49cdfc7eSAndroid Build Coastguard Worker 
stop_log(int sig)393*49cdfc7eSAndroid Build Coastguard Worker static void stop_log(int sig)
394*49cdfc7eSAndroid Build Coastguard Worker {
395*49cdfc7eSAndroid Build Coastguard Worker 	stop = 1;
396*49cdfc7eSAndroid Build Coastguard Worker }
397*49cdfc7eSAndroid Build Coastguard Worker 
main(int argc,char ** argv)398*49cdfc7eSAndroid Build Coastguard Worker int main(int argc, char **argv)
399*49cdfc7eSAndroid Build Coastguard Worker {
400*49cdfc7eSAndroid Build Coastguard Worker 	/*
401*49cdfc7eSAndroid Build Coastguard Worker 	 * Determine the valid priority range; subtracting one from the
402*49cdfc7eSAndroid Build Coastguard Worker 	 * maximum to reserve the highest prio for main thread.
403*49cdfc7eSAndroid Build Coastguard Worker 	 */
404*49cdfc7eSAndroid Build Coastguard Worker 	prio_min = sched_get_priority_min(SCHED_FIFO);
405*49cdfc7eSAndroid Build Coastguard Worker 	prio_max = sched_get_priority_max(SCHED_FIFO) - 1;
406*49cdfc7eSAndroid Build Coastguard Worker 
407*49cdfc7eSAndroid Build Coastguard Worker 	int *threads;
408*49cdfc7eSAndroid Build Coastguard Worker 	long i;
409*49cdfc7eSAndroid Build Coastguard Worker 	int ret;
410*49cdfc7eSAndroid Build Coastguard Worker 	struct timespec intv;
411*49cdfc7eSAndroid Build Coastguard Worker 	struct sched_param param;
412*49cdfc7eSAndroid Build Coastguard Worker 
413*49cdfc7eSAndroid Build Coastguard Worker 	rt_init("a:r:t:e:l:h:", parse_args, argc, argv);
414*49cdfc7eSAndroid Build Coastguard Worker 	signal(SIGINT, stop_log);
415*49cdfc7eSAndroid Build Coastguard Worker 
416*49cdfc7eSAndroid Build Coastguard Worker 	if (argc >= (optind + 1))
417*49cdfc7eSAndroid Build Coastguard Worker 		nr_tasks = atoi(argv[optind]);
418*49cdfc7eSAndroid Build Coastguard Worker 	else {
419*49cdfc7eSAndroid Build Coastguard Worker 		numcpus = sysconf(_SC_NPROCESSORS_ONLN);
420*49cdfc7eSAndroid Build Coastguard Worker 		nr_tasks = numcpus + 1;
421*49cdfc7eSAndroid Build Coastguard Worker 	}
422*49cdfc7eSAndroid Build Coastguard Worker 	if (nr_tasks < 0) {
423*49cdfc7eSAndroid Build Coastguard Worker 		printf("The number of tasks must not be negative.\n");
424*49cdfc7eSAndroid Build Coastguard Worker 		exit(EXIT_FAILURE);
425*49cdfc7eSAndroid Build Coastguard Worker 	}
426*49cdfc7eSAndroid Build Coastguard Worker 
427*49cdfc7eSAndroid Build Coastguard Worker 	intervals = malloc(sizeof(stats_container_t) * nr_tasks);
428*49cdfc7eSAndroid Build Coastguard Worker 	if (!intervals)
429*49cdfc7eSAndroid Build Coastguard Worker 		debug(DBG_ERR, "malloc failed\n");
430*49cdfc7eSAndroid Build Coastguard Worker 	memset(intervals, 0, sizeof(stats_container_t) * nr_tasks);
431*49cdfc7eSAndroid Build Coastguard Worker 
432*49cdfc7eSAndroid Build Coastguard Worker 	intervals_length = malloc(sizeof(stats_container_t) * nr_tasks);
433*49cdfc7eSAndroid Build Coastguard Worker 	if (!intervals_length)
434*49cdfc7eSAndroid Build Coastguard Worker 		debug(DBG_ERR, "malloc failed\n");
435*49cdfc7eSAndroid Build Coastguard Worker 	memset(intervals_length, 0, sizeof(stats_container_t) * nr_tasks);
436*49cdfc7eSAndroid Build Coastguard Worker 
437*49cdfc7eSAndroid Build Coastguard Worker 	if (!intervals_loops)
438*49cdfc7eSAndroid Build Coastguard Worker 		debug(DBG_ERR, "malloc failed\n");
439*49cdfc7eSAndroid Build Coastguard Worker 	intervals_loops = malloc(sizeof(stats_container_t) * nr_tasks);
440*49cdfc7eSAndroid Build Coastguard Worker 	memset(intervals_loops, 0, sizeof(stats_container_t) * nr_tasks);
441*49cdfc7eSAndroid Build Coastguard Worker 
442*49cdfc7eSAndroid Build Coastguard Worker 	threads = malloc(sizeof(*threads) * nr_tasks);
443*49cdfc7eSAndroid Build Coastguard Worker 	if (!threads)
444*49cdfc7eSAndroid Build Coastguard Worker 		debug(DBG_ERR, "malloc failed\n");
445*49cdfc7eSAndroid Build Coastguard Worker 	memset(threads, 0, sizeof(*threads) * nr_tasks);
446*49cdfc7eSAndroid Build Coastguard Worker 
447*49cdfc7eSAndroid Build Coastguard Worker 	ret = pthread_barrier_init(&start_barrier, NULL, nr_tasks + 1);
448*49cdfc7eSAndroid Build Coastguard Worker 	ret = pthread_barrier_init(&end_barrier, NULL, nr_tasks + 1);
449*49cdfc7eSAndroid Build Coastguard Worker 	if (ret < 0)
450*49cdfc7eSAndroid Build Coastguard Worker 		debug(DBG_ERR, "pthread_barrier_init failed: %s\n",
451*49cdfc7eSAndroid Build Coastguard Worker 		      strerror(ret));
452*49cdfc7eSAndroid Build Coastguard Worker 
453*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < nr_tasks; i++) {
454*49cdfc7eSAndroid Build Coastguard Worker 		stats_container_init(&intervals[i], nr_runs);
455*49cdfc7eSAndroid Build Coastguard Worker 		stats_container_init(&intervals_length[i], nr_runs);
456*49cdfc7eSAndroid Build Coastguard Worker 		stats_container_init(&intervals_loops[i], nr_runs);
457*49cdfc7eSAndroid Build Coastguard Worker 	}
458*49cdfc7eSAndroid Build Coastguard Worker 
459*49cdfc7eSAndroid Build Coastguard Worker 	thread_pids = malloc(sizeof(long) * nr_tasks);
460*49cdfc7eSAndroid Build Coastguard Worker 	if (!thread_pids)
461*49cdfc7eSAndroid Build Coastguard Worker 		debug(DBG_ERR, "malloc thread_pids failed\n");
462*49cdfc7eSAndroid Build Coastguard Worker 
463*49cdfc7eSAndroid Build Coastguard Worker 	for (i = 0; i < nr_tasks; i++) {
464*49cdfc7eSAndroid Build Coastguard Worker 		threads[i] = create_fifo_thread(start_task, (void *)i,
465*49cdfc7eSAndroid Build Coastguard Worker 						CLAMP_PRIO(prio_start + i));
466*49cdfc7eSAndroid Build Coastguard Worker 	}
467*49cdfc7eSAndroid Build Coastguard Worker 
468*49cdfc7eSAndroid Build Coastguard Worker 	/*
469*49cdfc7eSAndroid Build Coastguard Worker 	 * Progress bar uses stderr to let users see it when
470*49cdfc7eSAndroid Build Coastguard Worker 	 * redirecting output. So we convert stderr to use line
471*49cdfc7eSAndroid Build Coastguard Worker 	 * buffering so the progress bar doesn't flicker.
472*49cdfc7eSAndroid Build Coastguard Worker 	 */
473*49cdfc7eSAndroid Build Coastguard Worker 	setlinebuf(stderr);
474*49cdfc7eSAndroid Build Coastguard Worker 
475*49cdfc7eSAndroid Build Coastguard Worker 	/* up our prio above all tasks */
476*49cdfc7eSAndroid Build Coastguard Worker 	memset(&param, 0, sizeof(param));
477*49cdfc7eSAndroid Build Coastguard Worker 	param.sched_priority = CLAMP(nr_tasks + prio_start, prio_min,
478*49cdfc7eSAndroid Build Coastguard Worker 								 prio_max + 1);
479*49cdfc7eSAndroid Build Coastguard Worker 	if (sched_setscheduler(0, SCHED_FIFO, &param))
480*49cdfc7eSAndroid Build Coastguard Worker 		debug(DBG_WARN, "Warning, can't set priority of main thread!\n");
481*49cdfc7eSAndroid Build Coastguard Worker 	intv.tv_sec = INTERVAL / NS_PER_SEC;
482*49cdfc7eSAndroid Build Coastguard Worker 	intv.tv_nsec = INTERVAL % (1 * NS_PER_SEC);
483*49cdfc7eSAndroid Build Coastguard Worker 
484*49cdfc7eSAndroid Build Coastguard Worker 	print_progress_bar(0);
485*49cdfc7eSAndroid Build Coastguard Worker 
486*49cdfc7eSAndroid Build Coastguard Worker 	setup_ftrace_marker();
487*49cdfc7eSAndroid Build Coastguard Worker 
488*49cdfc7eSAndroid Build Coastguard Worker 	for (loop = 0; loop < nr_runs; loop++) {
489*49cdfc7eSAndroid Build Coastguard Worker 		unsigned long long end;
490*49cdfc7eSAndroid Build Coastguard Worker 
491*49cdfc7eSAndroid Build Coastguard Worker 		now = rt_gettime() / NS_PER_US;
492*49cdfc7eSAndroid Build Coastguard Worker 
493*49cdfc7eSAndroid Build Coastguard Worker 		ftrace_write("Loop %d now=%lld\n", loop, now);
494*49cdfc7eSAndroid Build Coastguard Worker 
495*49cdfc7eSAndroid Build Coastguard Worker 		pthread_barrier_wait(&start_barrier);
496*49cdfc7eSAndroid Build Coastguard Worker 
497*49cdfc7eSAndroid Build Coastguard Worker 		ftrace_write("All running!!!\n");
498*49cdfc7eSAndroid Build Coastguard Worker 
499*49cdfc7eSAndroid Build Coastguard Worker 		rt_nanosleep(intv.tv_nsec);
500*49cdfc7eSAndroid Build Coastguard Worker 		print_progress_bar((loop * 100) / nr_runs);
501*49cdfc7eSAndroid Build Coastguard Worker 
502*49cdfc7eSAndroid Build Coastguard Worker 		end = rt_gettime() / NS_PER_US;
503*49cdfc7eSAndroid Build Coastguard Worker 		ftrace_write("Loop %d end now=%lld diff=%lld\n",
504*49cdfc7eSAndroid Build Coastguard Worker 			     loop, end, end - now);
505*49cdfc7eSAndroid Build Coastguard Worker 		ret = pthread_barrier_wait(&end_barrier);
506*49cdfc7eSAndroid Build Coastguard Worker 
507*49cdfc7eSAndroid Build Coastguard Worker 		if (stop || (check && check_times(loop))) {
508*49cdfc7eSAndroid Build Coastguard Worker 			loop++;
509*49cdfc7eSAndroid Build Coastguard Worker 			nr_runs = loop;
510*49cdfc7eSAndroid Build Coastguard Worker 			break;
511*49cdfc7eSAndroid Build Coastguard Worker 		}
512*49cdfc7eSAndroid Build Coastguard Worker 	}
513*49cdfc7eSAndroid Build Coastguard Worker 	putc('\n', stderr);
514*49cdfc7eSAndroid Build Coastguard Worker 
515*49cdfc7eSAndroid Build Coastguard Worker 	pthread_barrier_wait(&start_barrier);
516*49cdfc7eSAndroid Build Coastguard Worker 	done = 1;
517*49cdfc7eSAndroid Build Coastguard Worker 	pthread_barrier_wait(&end_barrier);
518*49cdfc7eSAndroid Build Coastguard Worker 
519*49cdfc7eSAndroid Build Coastguard Worker 	join_threads();
520*49cdfc7eSAndroid Build Coastguard Worker 	print_results();
521*49cdfc7eSAndroid Build Coastguard Worker 
522*49cdfc7eSAndroid Build Coastguard Worker 	if (stop) {
523*49cdfc7eSAndroid Build Coastguard Worker 		/*
524*49cdfc7eSAndroid Build Coastguard Worker 		 * We use this test in bash while loops
525*49cdfc7eSAndroid Build Coastguard Worker 		 * So if we hit Ctrl-C then let the while
526*49cdfc7eSAndroid Build Coastguard Worker 		 * loop know to break.
527*49cdfc7eSAndroid Build Coastguard Worker 		 */
528*49cdfc7eSAndroid Build Coastguard Worker 		if (check < 0)
529*49cdfc7eSAndroid Build Coastguard Worker 			exit(-1);
530*49cdfc7eSAndroid Build Coastguard Worker 		else
531*49cdfc7eSAndroid Build Coastguard Worker 			exit(1);
532*49cdfc7eSAndroid Build Coastguard Worker 	}
533*49cdfc7eSAndroid Build Coastguard Worker 
534*49cdfc7eSAndroid Build Coastguard Worker 	if (check < 0)
535*49cdfc7eSAndroid Build Coastguard Worker 		exit(-1);
536*49cdfc7eSAndroid Build Coastguard Worker 	else
537*49cdfc7eSAndroid Build Coastguard Worker 		exit(0);
538*49cdfc7eSAndroid Build Coastguard Worker }
539