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 *      rdtsc-latency.c
21f08c3bdfSopenharmony_ci *
22f08c3bdfSopenharmony_ci * DESCRIPTION
23f08c3bdfSopenharmony_ci *       Simple program to measure the time between several pairs of calls to
24f08c3bdfSopenharmony_ci *       rdtsc().  Based off of gtod-latency.c
25f08c3bdfSopenharmony_ci *
26f08c3bdfSopenharmony_ci * USAGE:
27f08c3bdfSopenharmony_ci *      Use run_auto.sh script in current directory to build and run test.
28f08c3bdfSopenharmony_ci *      Use "-j" to enable jvm simulator.
29f08c3bdfSopenharmony_ci *
30f08c3bdfSopenharmony_ci * AUTHOR
31f08c3bdfSopenharmony_ci *      Darren Hart <dvhltc@us.ibm.com>
32f08c3bdfSopenharmony_ci *
33f08c3bdfSopenharmony_ci * HISTORY
34f08c3bdfSopenharmony_ci *      2006-Nov-15: Initial version by Darren Hart <dvhltc@us.ibm.com>
35f08c3bdfSopenharmony_ci *
36f08c3bdfSopenharmony_ci *****************************************************************************/
37f08c3bdfSopenharmony_ci
38f08c3bdfSopenharmony_ci#include <stdio.h>
39f08c3bdfSopenharmony_ci#include <stdlib.h>
40f08c3bdfSopenharmony_ci#include <unistd.h>
41f08c3bdfSopenharmony_ci#include <sys/time.h>
42f08c3bdfSopenharmony_ci#include <sys/types.h>
43f08c3bdfSopenharmony_ci#include <sched.h>
44f08c3bdfSopenharmony_ci#include <errno.h>
45f08c3bdfSopenharmony_ci#include <stdint.h>
46f08c3bdfSopenharmony_ci#include <librttest.h>
47f08c3bdfSopenharmony_ci
48f08c3bdfSopenharmony_ci#include "tst_tsc.h"
49f08c3bdfSopenharmony_ci
50f08c3bdfSopenharmony_ci#define ITERATIONS 1000000
51f08c3bdfSopenharmony_ci
52f08c3bdfSopenharmony_civoid usage(void)
53f08c3bdfSopenharmony_ci{
54f08c3bdfSopenharmony_ci	rt_help();
55f08c3bdfSopenharmony_ci	printf("rdtsc-latency specific options:\n");
56f08c3bdfSopenharmony_ci	printf(" This testcase don't expect any commandline options\n");
57f08c3bdfSopenharmony_ci}
58f08c3bdfSopenharmony_ci
59f08c3bdfSopenharmony_ciint parse_args(int c, char *v)
60f08c3bdfSopenharmony_ci{
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_ci	int handled = 1;
63f08c3bdfSopenharmony_ci	switch (c) {
64f08c3bdfSopenharmony_ci	case 'h':
65f08c3bdfSopenharmony_ci		usage();
66f08c3bdfSopenharmony_ci		exit(0);
67f08c3bdfSopenharmony_ci	default:
68f08c3bdfSopenharmony_ci		handled = 0;
69f08c3bdfSopenharmony_ci		break;
70f08c3bdfSopenharmony_ci	}
71f08c3bdfSopenharmony_ci	return handled;
72f08c3bdfSopenharmony_ci}
73f08c3bdfSopenharmony_ci
74f08c3bdfSopenharmony_ci/* return difference in nanoseconds */
75f08c3bdfSopenharmony_ciunsigned long long tv_minus(struct timeval *tv_start, struct timeval *tv_end)
76f08c3bdfSopenharmony_ci{
77f08c3bdfSopenharmony_ci	unsigned long long nsecs;
78f08c3bdfSopenharmony_ci	nsecs = (tv_end->tv_sec - tv_start->tv_sec) * 1000000000ULL;
79f08c3bdfSopenharmony_ci	nsecs += (tv_end->tv_usec - tv_start->tv_usec) * 1000;
80f08c3bdfSopenharmony_ci	return nsecs;
81f08c3bdfSopenharmony_ci}
82f08c3bdfSopenharmony_ci
83f08c3bdfSopenharmony_ci/* calculate the tsc period */
84f08c3bdfSopenharmony_ciunsigned long long tsc_period_ps(void)
85f08c3bdfSopenharmony_ci{
86f08c3bdfSopenharmony_ci	struct timeval tv_start;
87f08c3bdfSopenharmony_ci	struct timeval tv_end;
88f08c3bdfSopenharmony_ci	unsigned long long tsc_start, tsc_end;
89f08c3bdfSopenharmony_ci
90f08c3bdfSopenharmony_ci	rdtscll(tsc_start);
91f08c3bdfSopenharmony_ci	gettimeofday(&tv_start, NULL);
92f08c3bdfSopenharmony_ci	sleep(1);
93f08c3bdfSopenharmony_ci	rdtscll(tsc_end);
94f08c3bdfSopenharmony_ci	gettimeofday(&tv_end, NULL);
95f08c3bdfSopenharmony_ci
96f08c3bdfSopenharmony_ci	return (1000 * tv_minus(&tv_start, &tv_end)) / tsc_minus(tsc_start,
97f08c3bdfSopenharmony_ci								 tsc_end);
98f08c3bdfSopenharmony_ci}
99f08c3bdfSopenharmony_ci
100f08c3bdfSopenharmony_ciint main(int argc, char *argv[])
101f08c3bdfSopenharmony_ci{
102f08c3bdfSopenharmony_ci	int i, err;
103f08c3bdfSopenharmony_ci	unsigned long long deltas[ITERATIONS];
104f08c3bdfSopenharmony_ci	unsigned long long max, min, avg, tsc_a, tsc_b, tsc_period;
105f08c3bdfSopenharmony_ci	struct sched_param param;
106f08c3bdfSopenharmony_ci
107f08c3bdfSopenharmony_ci#ifdef TSC_UNSUPPORTED
108f08c3bdfSopenharmony_ci	printf("Error: test cannot be executed on an arch wihout TSC.\n");
109f08c3bdfSopenharmony_ci	return ENOTSUP;
110f08c3bdfSopenharmony_ci#endif
111f08c3bdfSopenharmony_ci
112f08c3bdfSopenharmony_ci	setup();
113f08c3bdfSopenharmony_ci
114f08c3bdfSopenharmony_ci	rt_init("h", parse_args, argc, argv);
115f08c3bdfSopenharmony_ci
116f08c3bdfSopenharmony_ci	/* no arguments */
117f08c3bdfSopenharmony_ci	if (argc > 1) {
118f08c3bdfSopenharmony_ci		fprintf(stderr, "%s accepts no arguments\n", argv[0]);
119f08c3bdfSopenharmony_ci		exit(1);
120f08c3bdfSopenharmony_ci	}
121f08c3bdfSopenharmony_ci
122f08c3bdfSopenharmony_ci	/* switch to SCHED_FIFO 99 */
123f08c3bdfSopenharmony_ci	param.sched_priority = sched_get_priority_max(SCHED_FIFO);
124f08c3bdfSopenharmony_ci	err = sched_setscheduler(0, SCHED_FIFO, &param);
125f08c3bdfSopenharmony_ci
126f08c3bdfSopenharmony_ci	/* Check that the user has the appropriate privileges */
127f08c3bdfSopenharmony_ci	if (err) {
128f08c3bdfSopenharmony_ci		if (errno == EPERM) {
129f08c3bdfSopenharmony_ci			fprintf(stderr,
130f08c3bdfSopenharmony_ci				"This program runs with a scheduling policy of SCHED_FIFO at priority %d\n",
131f08c3bdfSopenharmony_ci				param.sched_priority);
132f08c3bdfSopenharmony_ci			fprintf(stderr,
133f08c3bdfSopenharmony_ci				"You don't have the necessary privileges to create such a real-time process.\n");
134f08c3bdfSopenharmony_ci		} else {
135f08c3bdfSopenharmony_ci			fprintf(stderr, "Failed to set scheduler, errno %d\n",
136f08c3bdfSopenharmony_ci				errno);
137f08c3bdfSopenharmony_ci		}
138f08c3bdfSopenharmony_ci		exit(1);
139f08c3bdfSopenharmony_ci	}
140f08c3bdfSopenharmony_ci
141f08c3bdfSopenharmony_ci	/* calculate the tsc period in picoseconds */
142f08c3bdfSopenharmony_ci	tsc_period = tsc_period_ps();
143f08c3bdfSopenharmony_ci
144f08c3bdfSopenharmony_ci	/* collect ITERATIONS pairs of gtod calls */
145f08c3bdfSopenharmony_ci	max = min = avg = 0;
146f08c3bdfSopenharmony_ci	for (i = 0; i < ITERATIONS; i++) {
147f08c3bdfSopenharmony_ci		rdtscll(tsc_a);
148f08c3bdfSopenharmony_ci		rdtscll(tsc_b);
149f08c3bdfSopenharmony_ci		deltas[i] = (tsc_minus(tsc_a, tsc_b) * tsc_period) / 1000;	/* tsc period is in ps */
150f08c3bdfSopenharmony_ci		if (i == 0 || deltas[i] < min)
151f08c3bdfSopenharmony_ci			min = deltas[i];
152f08c3bdfSopenharmony_ci		if (deltas[i] > max)
153f08c3bdfSopenharmony_ci			max = deltas[i];
154f08c3bdfSopenharmony_ci		avg += deltas[i];
155f08c3bdfSopenharmony_ci	}
156f08c3bdfSopenharmony_ci	avg /= ITERATIONS;
157f08c3bdfSopenharmony_ci
158f08c3bdfSopenharmony_ci	/* report on deltas */
159f08c3bdfSopenharmony_ci	printf("Calculated tsc period = %llu ps\n", tsc_period);
160f08c3bdfSopenharmony_ci	printf("%d pairs of rdtsc() calls completed\n", ITERATIONS);
161f08c3bdfSopenharmony_ci	printf("Time between calls:\n");
162f08c3bdfSopenharmony_ci	printf("     Max: %llu ns\n", max);
163f08c3bdfSopenharmony_ci	printf("     Min: %llu ns\n", min);
164f08c3bdfSopenharmony_ci	printf("     Avg: %llu ns\n", avg);
165f08c3bdfSopenharmony_ci
166f08c3bdfSopenharmony_ci	return 0;
167f08c3bdfSopenharmony_ci}
168