1 /****************************************************************************** 2 * 3 * Copyright International Business Machines Corp., 2006-2008 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 13 * the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 18 * 19 * NAME 20 * sched_jitter.c 21 * 22 * DESCRIPTION 23 * This test measures scheduling jitter w/ realtime processes. 24 * 25 * It spawns a realtime thread that repeatedly times how long it takes to 26 * do a fixed amount of work. It then prints out the maximum jitter seen 27 * (longest execution time - the shortest execution time). 28 * It also spawns off a realtime thread of higher priority that simply 29 * wakes up and goes back to sleep. This tries to measure how much overhead 30 * the scheduler adds in switching quickly to another task and back. 31 * 32 * USAGE: 33 * Use run_auto.sh script in current directory to build and run test. 34 * 35 * AUTHOR 36 * John Stultz <johnstul (at) us.ibm.com> 37 * 38 * HISTORY 39 * 2006-May-05: Initial version by John Stultz <johnstul (at) us.ibm.com> 40 * 2007-July-18: Support to gather stats by Ankita Garg <ankita (at) in.ibm.com> 41 * 42 * This line has to be added to avoid a stupid CVS problem 43 *****************************************************************************/ 44 45 #include <stdio.h> 46 #include <time.h> 47 #include <pthread.h> 48 #include <sched.h> 49 #include <unistd.h> 50 #include <libstats.h> 51 #include <librttest.h> 52 53 #define NUMRUNS 1000 54 #define NUMLOOPS 1000000 55 #define NSEC_PER_SEC 1000000000 56 #define WORKLEN 64 57 #define ISLEEP 50000 58 59 int array[WORKLEN]; 60 61 volatile int flag; /*let interrupter know we're done */ 62 63 void usage(void) 64 { 65 rt_help(); 66 printf("sched_jitter specific options:\n"); 67 } 68 69 int parse_args(int c, char *v) 70 { 71 72 int handled = 1; 73 switch (c) { 74 case 'h': 75 usage(); 76 exit(0); 77 default: 78 handled = 0; 79 break; 80 } 81 return handled; 82 } 83 84 unsigned long long ts_sub(struct timespec a, struct timespec b) 85 { 86 unsigned long long first, second; 87 88 first = (unsigned long long)a.tv_sec * NSEC_PER_SEC + a.tv_nsec; 89 second = (unsigned long long)b.tv_sec * NSEC_PER_SEC + b.tv_nsec; 90 return first - second; 91 } 92 93 void print_unit(unsigned long long val) 94 { 95 if (val > 1000000) 96 printf("%f ms\n", (float)(val) / 1000000); 97 else if (val > 1000) 98 printf("%f us\n", (float)(val) / 1000); 99 else 100 printf("%f ns\n", (float)val); 101 102 } 103 104 void do_work(int runs) 105 { 106 int i, j; 107 for (i = 0; i < runs; i++) { 108 for (j = 0; j < WORKLEN - 1; j++) 109 array[j] = array[j] + array[j + 1]; 110 for (j = 0; j < WORKLEN - 1; j++) 111 array[j] = array[j] - array[j + 1]; 112 } 113 } 114 115 void *thread_worker(void *arg) 116 { 117 struct timespec start, stop; 118 int i; 119 unsigned long long delta; 120 unsigned long long min = -1, max = 0; 121 122 stats_container_t dat; 123 stats_record_t rec; 124 125 stats_container_init(&dat, NUMRUNS); 126 127 for (i = 0; i < NUMRUNS; i++) { 128 129 do_work(1); /* warm cache */ 130 131 /* do test */ 132 clock_gettime(CLOCK_MONOTONIC, &start); 133 do_work(NUMLOOPS); 134 clock_gettime(CLOCK_MONOTONIC, &stop); 135 136 /* calc delta, min and max */ 137 delta = ts_sub(stop, start); 138 if (delta < min) 139 min = delta; 140 if (delta > max) 141 max = delta; 142 rec.x = i; 143 rec.y = delta; 144 stats_container_append(&dat, rec); 145 146 printf("delta: %llu ns\n", delta); 147 usleep(1); /* let other things happen */ 148 } 149 150 printf("max jitter: "); 151 print_unit(max - min); 152 stats_container_save("samples", "Scheduling Jitter Scatter Plot", 153 "Iteration", "Delay (ns)", &dat, "points"); 154 return NULL; 155 } 156 157 void *thread_interrupter(void *arg) 158 { 159 while (!flag) 160 usleep(ISLEEP); 161 return NULL; 162 } 163 164 int main(int argc, char *argv[]) 165 { 166 int worker, interrupter; 167 168 setup(); 169 170 rt_init("h", parse_args, argc, argv); 171 172 interrupter = create_fifo_thread(thread_interrupter, NULL, 80); 173 sleep(1); 174 worker = create_fifo_thread(thread_worker, NULL, 10); 175 176 join_thread(worker); 177 flag = 1; 178 join_thread(interrupter); 179 180 return 0; 181 } 182