1*49cdfc7eSAndroid Build Coastguard Worker /******************************************************************************
2*49cdfc7eSAndroid Build Coastguard Worker *
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright © International Business Machines Corp., 2007, 2008
4*49cdfc7eSAndroid Build Coastguard Worker *
5*49cdfc7eSAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or modify
6*49cdfc7eSAndroid Build Coastguard Worker * it under the terms of the GNU General Public License as published by
7*49cdfc7eSAndroid Build Coastguard Worker * the Free Software Foundation; either version 2 of the License, or
8*49cdfc7eSAndroid Build Coastguard Worker * (at your option) any later version.
9*49cdfc7eSAndroid Build Coastguard Worker *
10*49cdfc7eSAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
11*49cdfc7eSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
12*49cdfc7eSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
13*49cdfc7eSAndroid Build Coastguard Worker * the GNU General Public License for more details.
14*49cdfc7eSAndroid Build Coastguard Worker *
15*49cdfc7eSAndroid Build Coastguard Worker * You should have received a copy of the GNU General Public License
16*49cdfc7eSAndroid Build Coastguard Worker * along with this program; if not, write to the Free Software
17*49cdfc7eSAndroid Build Coastguard Worker * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18*49cdfc7eSAndroid Build Coastguard Worker *
19*49cdfc7eSAndroid Build Coastguard Worker * NAME
20*49cdfc7eSAndroid Build Coastguard Worker * hrtimer-prio.c
21*49cdfc7eSAndroid Build Coastguard Worker *
22*49cdfc7eSAndroid Build Coastguard Worker * DESCRIPTION
23*49cdfc7eSAndroid Build Coastguard Worker * Test the latency of hrtimers under rt load.
24*49cdfc7eSAndroid Build Coastguard Worker * The busy_threads should run at a priority higher than the system
25*49cdfc7eSAndroid Build Coastguard Worker * softirq_hrtimer, but lower than the timer_thread. The timer_thread
26*49cdfc7eSAndroid Build Coastguard Worker * measure the time it takes to return from a nanosleep call. If the
27*49cdfc7eSAndroid Build Coastguard Worker * lower priority threads can increase the latency of the higher
28*49cdfc7eSAndroid Build Coastguard Worker * priority thread, it is considered a failure.
29*49cdfc7eSAndroid Build Coastguard Worker *
30*49cdfc7eSAndroid Build Coastguard Worker * USAGE:
31*49cdfc7eSAndroid Build Coastguard Worker * Use run_auto.sh script in current directory to build and run test.
32*49cdfc7eSAndroid Build Coastguard Worker *
33*49cdfc7eSAndroid Build Coastguard Worker * AUTHOR
34*49cdfc7eSAndroid Build Coastguard Worker * Darren Hart <[email protected]>
35*49cdfc7eSAndroid Build Coastguard Worker *
36*49cdfc7eSAndroid Build Coastguard Worker * HISTORY
37*49cdfc7eSAndroid Build Coastguard Worker * 2007-Aug-08: Initial version by Darren Hart <[email protected]>
38*49cdfc7eSAndroid Build Coastguard Worker *
39*49cdfc7eSAndroid Build Coastguard Worker * This line has to be added to avoid a stupid CVS problem
40*49cdfc7eSAndroid Build Coastguard Worker *****************************************************************************/
41*49cdfc7eSAndroid Build Coastguard Worker
42*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
43*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
44*49cdfc7eSAndroid Build Coastguard Worker #include <math.h>
45*49cdfc7eSAndroid Build Coastguard Worker #include <librttest.h>
46*49cdfc7eSAndroid Build Coastguard Worker #include <libstats.h>
47*49cdfc7eSAndroid Build Coastguard Worker
48*49cdfc7eSAndroid Build Coastguard Worker #define DEF_MED_PRIO 60 // (softirqd-hrtimer,98)
49*49cdfc7eSAndroid Build Coastguard Worker #define DEF_ITERATIONS 10000
50*49cdfc7eSAndroid Build Coastguard Worker #define HIST_BUCKETS 100
51*49cdfc7eSAndroid Build Coastguard Worker #define DEF_BUSY_TIME 10 // Duration of busy work in milliseconds
52*49cdfc7eSAndroid Build Coastguard Worker #define DEF_SLEEP_TIME 10000 // Duration of nanosleep in nanoseconds
53*49cdfc7eSAndroid Build Coastguard Worker #define DEF_CRITERIA 10 // maximum timer latency in microseconds
54*49cdfc7eSAndroid Build Coastguard Worker
55*49cdfc7eSAndroid Build Coastguard Worker static int med_prio = DEF_MED_PRIO;
56*49cdfc7eSAndroid Build Coastguard Worker static int high_prio;
57*49cdfc7eSAndroid Build Coastguard Worker static int busy_time = DEF_BUSY_TIME;
58*49cdfc7eSAndroid Build Coastguard Worker static int iterations = DEF_ITERATIONS;
59*49cdfc7eSAndroid Build Coastguard Worker static int busy_threads;
60*49cdfc7eSAndroid Build Coastguard Worker
61*49cdfc7eSAndroid Build Coastguard Worker static stats_container_t dat;
62*49cdfc7eSAndroid Build Coastguard Worker static stats_record_t rec;
63*49cdfc7eSAndroid Build Coastguard Worker static atomic_t busy_threads_started;
64*49cdfc7eSAndroid Build Coastguard Worker static unsigned long min_delta;
65*49cdfc7eSAndroid Build Coastguard Worker static unsigned long max_delta;
66*49cdfc7eSAndroid Build Coastguard Worker
usage(void)67*49cdfc7eSAndroid Build Coastguard Worker void usage(void)
68*49cdfc7eSAndroid Build Coastguard Worker {
69*49cdfc7eSAndroid Build Coastguard Worker rt_help();
70*49cdfc7eSAndroid Build Coastguard Worker printf("hrtimer-prio specific options:\n");
71*49cdfc7eSAndroid Build Coastguard Worker printf(" -t# #:busy work time in ms, defaults to %d ms\n",
72*49cdfc7eSAndroid Build Coastguard Worker DEF_BUSY_TIME);
73*49cdfc7eSAndroid Build Coastguard Worker printf(" -i# #:number of iterations, defaults to %d\n",
74*49cdfc7eSAndroid Build Coastguard Worker DEF_ITERATIONS);
75*49cdfc7eSAndroid Build Coastguard Worker printf(" -n# #:number of busy threads, defaults to NR_CPUS*2\n");
76*49cdfc7eSAndroid Build Coastguard Worker printf
77*49cdfc7eSAndroid Build Coastguard Worker (" -f# #:rt fifo priority of busy threads (1,98), defaults to %d\n",
78*49cdfc7eSAndroid Build Coastguard Worker DEF_MED_PRIO);
79*49cdfc7eSAndroid Build Coastguard Worker }
80*49cdfc7eSAndroid Build Coastguard Worker
parse_args(int c,char * v)81*49cdfc7eSAndroid Build Coastguard Worker int parse_args(int c, char *v)
82*49cdfc7eSAndroid Build Coastguard Worker {
83*49cdfc7eSAndroid Build Coastguard Worker
84*49cdfc7eSAndroid Build Coastguard Worker int handled = 1;
85*49cdfc7eSAndroid Build Coastguard Worker switch (c) {
86*49cdfc7eSAndroid Build Coastguard Worker case 'h':
87*49cdfc7eSAndroid Build Coastguard Worker usage();
88*49cdfc7eSAndroid Build Coastguard Worker exit(0);
89*49cdfc7eSAndroid Build Coastguard Worker case 't':
90*49cdfc7eSAndroid Build Coastguard Worker busy_time = atoi(v);
91*49cdfc7eSAndroid Build Coastguard Worker break;
92*49cdfc7eSAndroid Build Coastguard Worker case 'n':
93*49cdfc7eSAndroid Build Coastguard Worker busy_threads = atoi(v);
94*49cdfc7eSAndroid Build Coastguard Worker break;
95*49cdfc7eSAndroid Build Coastguard Worker case 'f':
96*49cdfc7eSAndroid Build Coastguard Worker med_prio = MIN(atoi(v), 98);
97*49cdfc7eSAndroid Build Coastguard Worker break;
98*49cdfc7eSAndroid Build Coastguard Worker case 'i':
99*49cdfc7eSAndroid Build Coastguard Worker iterations = atoi(v);
100*49cdfc7eSAndroid Build Coastguard Worker if (iterations < 100) {
101*49cdfc7eSAndroid Build Coastguard Worker fprintf(stderr,
102*49cdfc7eSAndroid Build Coastguard Worker "Number of iterations cannot be less than 100.\n");
103*49cdfc7eSAndroid Build Coastguard Worker exit(1);
104*49cdfc7eSAndroid Build Coastguard Worker }
105*49cdfc7eSAndroid Build Coastguard Worker break;
106*49cdfc7eSAndroid Build Coastguard Worker default:
107*49cdfc7eSAndroid Build Coastguard Worker handled = 0;
108*49cdfc7eSAndroid Build Coastguard Worker break;
109*49cdfc7eSAndroid Build Coastguard Worker }
110*49cdfc7eSAndroid Build Coastguard Worker return handled;
111*49cdfc7eSAndroid Build Coastguard Worker }
112*49cdfc7eSAndroid Build Coastguard Worker
busy_thread(void * thread)113*49cdfc7eSAndroid Build Coastguard Worker void *busy_thread(void *thread)
114*49cdfc7eSAndroid Build Coastguard Worker {
115*49cdfc7eSAndroid Build Coastguard Worker atomic_inc(&busy_threads_started);
116*49cdfc7eSAndroid Build Coastguard Worker while (1) {
117*49cdfc7eSAndroid Build Coastguard Worker busy_work_ms(busy_time);
118*49cdfc7eSAndroid Build Coastguard Worker sched_yield();
119*49cdfc7eSAndroid Build Coastguard Worker }
120*49cdfc7eSAndroid Build Coastguard Worker return NULL;
121*49cdfc7eSAndroid Build Coastguard Worker }
122*49cdfc7eSAndroid Build Coastguard Worker
timer_thread(void * thread)123*49cdfc7eSAndroid Build Coastguard Worker void *timer_thread(void *thread)
124*49cdfc7eSAndroid Build Coastguard Worker {
125*49cdfc7eSAndroid Build Coastguard Worker int i;
126*49cdfc7eSAndroid Build Coastguard Worker nsec_t start, end;
127*49cdfc7eSAndroid Build Coastguard Worker unsigned long delta_us;
128*49cdfc7eSAndroid Build Coastguard Worker while (atomic_get(&busy_threads_started) < busy_threads) {
129*49cdfc7eSAndroid Build Coastguard Worker rt_nanosleep(10000);
130*49cdfc7eSAndroid Build Coastguard Worker }
131*49cdfc7eSAndroid Build Coastguard Worker printf("All Busy Threads started, commencing test\n"); // FIXME: use debug infrastructure
132*49cdfc7eSAndroid Build Coastguard Worker max_delta = 0;
133*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < iterations; i++) {
134*49cdfc7eSAndroid Build Coastguard Worker start = rt_gettime();
135*49cdfc7eSAndroid Build Coastguard Worker rt_nanosleep(DEF_SLEEP_TIME);
136*49cdfc7eSAndroid Build Coastguard Worker end = rt_gettime();
137*49cdfc7eSAndroid Build Coastguard Worker delta_us =
138*49cdfc7eSAndroid Build Coastguard Worker ((unsigned long)(end - start) - DEF_SLEEP_TIME) / NS_PER_US;
139*49cdfc7eSAndroid Build Coastguard Worker rec.x = i;
140*49cdfc7eSAndroid Build Coastguard Worker rec.y = delta_us;
141*49cdfc7eSAndroid Build Coastguard Worker stats_container_append(&dat, rec);
142*49cdfc7eSAndroid Build Coastguard Worker max_delta = MAX(max_delta, delta_us);
143*49cdfc7eSAndroid Build Coastguard Worker min_delta = (i == 0) ? delta_us : MIN(min_delta, delta_us);
144*49cdfc7eSAndroid Build Coastguard Worker }
145*49cdfc7eSAndroid Build Coastguard Worker return NULL;
146*49cdfc7eSAndroid Build Coastguard Worker }
147*49cdfc7eSAndroid Build Coastguard Worker
main(int argc,char * argv[])148*49cdfc7eSAndroid Build Coastguard Worker int main(int argc, char *argv[])
149*49cdfc7eSAndroid Build Coastguard Worker {
150*49cdfc7eSAndroid Build Coastguard Worker int ret = 1;
151*49cdfc7eSAndroid Build Coastguard Worker int b;
152*49cdfc7eSAndroid Build Coastguard Worker float avg_delta;
153*49cdfc7eSAndroid Build Coastguard Worker int t_id;
154*49cdfc7eSAndroid Build Coastguard Worker setup();
155*49cdfc7eSAndroid Build Coastguard Worker busy_threads = 2 * sysconf(_SC_NPROCESSORS_ONLN); // default busy_threads
156*49cdfc7eSAndroid Build Coastguard Worker pass_criteria = DEF_CRITERIA;
157*49cdfc7eSAndroid Build Coastguard Worker rt_init("f:i:jhn:t:", parse_args, argc, argv);
158*49cdfc7eSAndroid Build Coastguard Worker high_prio = med_prio + 1;
159*49cdfc7eSAndroid Build Coastguard Worker
160*49cdfc7eSAndroid Build Coastguard Worker // Set main()'s prio to one above the timer_thread so it is sure to not
161*49cdfc7eSAndroid Build Coastguard Worker // be starved
162*49cdfc7eSAndroid Build Coastguard Worker if (set_priority(high_prio + 1) < 0) {
163*49cdfc7eSAndroid Build Coastguard Worker printf("Failed to set main()'s priority to %d\n",
164*49cdfc7eSAndroid Build Coastguard Worker high_prio + 1);
165*49cdfc7eSAndroid Build Coastguard Worker exit(1);
166*49cdfc7eSAndroid Build Coastguard Worker }
167*49cdfc7eSAndroid Build Coastguard Worker
168*49cdfc7eSAndroid Build Coastguard Worker printf("\n-------------------------------------------\n");
169*49cdfc7eSAndroid Build Coastguard Worker printf("High Resolution Timer Priority (Starvation)\n");
170*49cdfc7eSAndroid Build Coastguard Worker printf("-------------------------------------------\n\n");
171*49cdfc7eSAndroid Build Coastguard Worker printf("Running %d iterations\n", iterations);
172*49cdfc7eSAndroid Build Coastguard Worker printf("Running with %d busy threads\n", busy_threads);
173*49cdfc7eSAndroid Build Coastguard Worker printf("Busy thread work time: %d\n", busy_time);
174*49cdfc7eSAndroid Build Coastguard Worker printf("Busy thread priority: %d\n", med_prio);
175*49cdfc7eSAndroid Build Coastguard Worker printf("Timer thread priority: %d\n", high_prio);
176*49cdfc7eSAndroid Build Coastguard Worker
177*49cdfc7eSAndroid Build Coastguard Worker stats_container_t hist;
178*49cdfc7eSAndroid Build Coastguard Worker stats_quantiles_t quantiles;
179*49cdfc7eSAndroid Build Coastguard Worker if (stats_container_init(&dat, iterations)) {
180*49cdfc7eSAndroid Build Coastguard Worker printf("Cannot init stat containers for dat\n");
181*49cdfc7eSAndroid Build Coastguard Worker exit(1);
182*49cdfc7eSAndroid Build Coastguard Worker }
183*49cdfc7eSAndroid Build Coastguard Worker if (stats_container_init(&hist, HIST_BUCKETS)) {
184*49cdfc7eSAndroid Build Coastguard Worker printf("Cannot init stat containers for hist\n");
185*49cdfc7eSAndroid Build Coastguard Worker exit(1);
186*49cdfc7eSAndroid Build Coastguard Worker }
187*49cdfc7eSAndroid Build Coastguard Worker if (stats_quantiles_init(&quantiles, (int)log10(iterations))) {
188*49cdfc7eSAndroid Build Coastguard Worker printf("Cannot init stat quantiles\n");
189*49cdfc7eSAndroid Build Coastguard Worker exit(1);
190*49cdfc7eSAndroid Build Coastguard Worker }
191*49cdfc7eSAndroid Build Coastguard Worker
192*49cdfc7eSAndroid Build Coastguard Worker t_id = create_fifo_thread(timer_thread, NULL, high_prio);
193*49cdfc7eSAndroid Build Coastguard Worker if (t_id == -1) {
194*49cdfc7eSAndroid Build Coastguard Worker printf("Failed to create timer thread\n");
195*49cdfc7eSAndroid Build Coastguard Worker exit(1);
196*49cdfc7eSAndroid Build Coastguard Worker }
197*49cdfc7eSAndroid Build Coastguard Worker for (b = 0; b < busy_threads; b++) {
198*49cdfc7eSAndroid Build Coastguard Worker if (create_fifo_thread(busy_thread, NULL, med_prio) < 0) {
199*49cdfc7eSAndroid Build Coastguard Worker printf("Failed to create a busy thread\n");
200*49cdfc7eSAndroid Build Coastguard Worker exit(1);
201*49cdfc7eSAndroid Build Coastguard Worker }
202*49cdfc7eSAndroid Build Coastguard Worker }
203*49cdfc7eSAndroid Build Coastguard Worker join_thread(t_id);
204*49cdfc7eSAndroid Build Coastguard Worker
205*49cdfc7eSAndroid Build Coastguard Worker avg_delta = stats_avg(&dat);
206*49cdfc7eSAndroid Build Coastguard Worker stats_hist(&hist, &dat);
207*49cdfc7eSAndroid Build Coastguard Worker stats_container_save("samples",
208*49cdfc7eSAndroid Build Coastguard Worker "High Resolution Timer Latency Scatter Plot",
209*49cdfc7eSAndroid Build Coastguard Worker "Iteration", "Latency (us)", &dat, "points");
210*49cdfc7eSAndroid Build Coastguard Worker stats_container_save("hist", "High Resolution Timer Latency Histogram",
211*49cdfc7eSAndroid Build Coastguard Worker "Latency (us)", "Samples", &hist, "steps");
212*49cdfc7eSAndroid Build Coastguard Worker
213*49cdfc7eSAndroid Build Coastguard Worker if (max_delta <= pass_criteria)
214*49cdfc7eSAndroid Build Coastguard Worker ret = 0;
215*49cdfc7eSAndroid Build Coastguard Worker
216*49cdfc7eSAndroid Build Coastguard Worker printf("Minimum: %ld us\n", min_delta);
217*49cdfc7eSAndroid Build Coastguard Worker printf("Maximum: %ld us\n", max_delta);
218*49cdfc7eSAndroid Build Coastguard Worker printf("Average: %f us\n", avg_delta);
219*49cdfc7eSAndroid Build Coastguard Worker printf("Standard Deviation: %f\n", stats_stddev(&dat));
220*49cdfc7eSAndroid Build Coastguard Worker printf("Quantiles:\n");
221*49cdfc7eSAndroid Build Coastguard Worker stats_quantiles_calc(&dat, &quantiles);
222*49cdfc7eSAndroid Build Coastguard Worker stats_quantiles_print(&quantiles);
223*49cdfc7eSAndroid Build Coastguard Worker printf("\nCriteria: Maximum wakeup latency < %lu us\n",
224*49cdfc7eSAndroid Build Coastguard Worker (unsigned long)pass_criteria);
225*49cdfc7eSAndroid Build Coastguard Worker printf("Result: %s\n", ret ? "FAIL" : "PASS");
226*49cdfc7eSAndroid Build Coastguard Worker
227*49cdfc7eSAndroid Build Coastguard Worker return ret;
228*49cdfc7eSAndroid Build Coastguard Worker }
229