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 * gtod_infinite.c 21 * 22 * DESCRIPTION 23 * This 'test' is designed to run forever. It must manually be killed, 24 * so it is not ideally suited tobe part of a validation suite of tests. 25 * This test was initially designed to look for 'delays' between two 26 * calls to clock_gettime(), and helped locate SMI induced delays on 27 * several hardware platforms. 28 * 29 * As mentioned above, this test is designed to be run on a system for 30 * an unspecified period of time. It would not be unusual to let this 31 * test run for several days. 32 * 33 * During startup, the test will print out the 'maximum' delay between 34 * clock_gettime() calls. It starts with a predefined maximum of 35 * START_MAX(300ns) to eliminate noise during startup. In addition, 36 * it will print out every delay that exceeds REPORT_MIN (1000000ns). 37 * 38 * USAGE: 39 * Use run_auto.sh script in current directory to build and run test. 40 * 41 * AUTHOR 42 * Darren Hart <dvhltc@us.ibm.com> 43 * 44 * HISTORY 45 * 2006-Aug-17: Initial version by Darren Hart <dvhltc@us.ibm.com> 46 * 47 *****************************************************************************/ 48 49#include <stdio.h> 50#include <stdlib.h> 51#include <time.h> 52#include <sched.h> 53#include <librttest.h> 54#include <sys/mman.h> 55#include <unistd.h> 56#include <signal.h> 57 58#define CLOCK_TO_USE CLOCK_MONOTONIC 59 60#define START_MAX 3000 61#define REPORT_MIN 1000000 62 63static unsigned int max_window = 0; /* infinite, don't use a window */ 64static unsigned int test_duration = 0; /* infinite duration */ 65static int test_stop = 0; /* 1 to stop */ 66 67void usage(void) 68{ 69 rt_help(); 70 printf("gtod_infinite specific options:\n"); 71 printf 72 (" -wWINDOW iterations in max value window (default inf)\n"); 73 printf(" -tDURATION test duration in finite hours (default inf)\n"); 74} 75 76int parse_args(int c, char *v) 77{ 78 int handled = 1; 79 switch (c) { 80 case 'h': 81 usage(); 82 exit(0); 83 case 'w': 84 max_window = atoi(v); 85 break; 86 case 't': 87 test_duration = atoi(v); 88 break; 89 default: 90 handled = 0; 91 break; 92 } 93 return handled; 94} 95 96void alarm_handler(int sig) 97{ 98 /* Stop test execution */ 99 test_stop = 1; 100} 101 102int main(int argc, char *argv[]) 103{ 104 int /* i, */ rc; 105 struct timespec ts, p_ts; 106 nsec_t s_time, e_time, diff_time; 107 nsec_t max_time = START_MAX; 108// cpu_set_t mask; 109 struct sched_param param; 110 time_t tt; 111 unsigned int wi; 112 struct sigaction sact; 113 setup(); 114 115 /* Set signal handler for SIGALRM */ 116 sigfillset(&sact.sa_mask); 117 sact.sa_handler = alarm_handler; 118 rc = sigaction(SIGALRM, &sact, NULL); 119 if (rc) { 120 perror("sigaction"); 121 exit(1); 122 } 123/* 124 CPU_ZERO(&mask); 125 CPU_SET(0, &mask); 126 rc = sched_setaffinity(0, sizeof(mask), &mask); 127 if (rc) { 128 perror("sched_setaffinity"); 129 exit(1); 130 } 131*/ 132 rt_init("hw:t:", parse_args, argc, argv); 133 134 mlockall(MCL_CURRENT | MCL_FUTURE); 135 136 if (max_window > 0) { 137 printf("%d iterations in max calculation window\n", max_window); 138 } 139 140 param.sched_priority = sched_get_priority_min(SCHED_FIFO) + 80; 141 rc = sched_setscheduler(0, SCHED_FIFO, ¶m); 142 if (rc) { 143 perror("sched_setscheduler"); 144 exit(1); 145 } 146 147 rc = clock_gettime(CLOCK_TO_USE, &p_ts); 148 if (rc) { 149 perror("clock_gettime"); 150 exit(1); 151 } 152 153 /* Set alarm for test duration, if specified */ 154 if (test_duration > 0) { 155 rc = alarm(test_duration * 60 * 60); 156 if (rc) { 157 perror("alarm"); 158 exit(1); 159 } 160 } 161 162 wi = 0; 163 while (test_stop != 1) { 164 rc = clock_gettime(CLOCK_TO_USE, &p_ts); 165 rc = clock_gettime(CLOCK_TO_USE, &ts); 166 if (rc) { 167 perror("clock_gettime"); 168 exit(1); 169 } 170 171 ts_to_nsec(&p_ts, &s_time); 172 ts_to_nsec(&ts, &e_time); 173 174 diff_time = e_time - s_time; 175 176 if (max_window > 0 || 177 ((diff_time > max_time) || (diff_time > REPORT_MIN))) { 178 if (diff_time > max_time) 179 max_time = diff_time; 180 181 if (max_window == 0 || ++wi == max_window) { 182 tt = (time_t) ts.tv_sec; 183 printf("Task delayed for %lld nsec!!! %s", 184 max_time, ctime(&tt)); 185 fflush(stdout); 186 187 if (wi == max_window) { 188 max_time = 0; 189 wi = 0; 190 } 191 } 192 193 } 194 } 195 196 return 0; 197} 198