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