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