• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
63 static unsigned int max_window = 0;	/* infinite, don't use a window */
64 static unsigned int test_duration = 0;	/* infinite duration */
65 static int test_stop = 0;	/* 1 to stop */
66 
usage(void)67 void 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 
parse_args(int c,char * v)76 int 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 
alarm_handler(int sig)96 void alarm_handler(int sig)
97 {
98 	/* Stop test execution */
99 	test_stop = 1;
100 }
101 
main(int argc,char * argv[])102 int 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, &param);
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