1fe42c8a09884c2305ce101b1f3438e077d282495mbligh/*
2fe42c8a09884c2305ce101b1f3438e077d282495mbligh * High resolution timer test software
3fe42c8a09884c2305ce101b1f3438e077d282495mbligh *
4fe42c8a09884c2305ce101b1f3438e077d282495mbligh * (C) 2005-2007 Thomas Gleixner <tglx@linutronix.de>
5fe42c8a09884c2305ce101b1f3438e077d282495mbligh *
6fe42c8a09884c2305ce101b1f3438e077d282495mbligh * This program is free software; you can redistribute it and/or
7fe42c8a09884c2305ce101b1f3438e077d282495mbligh * modify it under the terms of the GNU General Public License Version
8fe42c8a09884c2305ce101b1f3438e077d282495mbligh * 2 as published by the Free Software Foundation.
9fe42c8a09884c2305ce101b1f3438e077d282495mbligh *
10fe42c8a09884c2305ce101b1f3438e077d282495mbligh */
11fe42c8a09884c2305ce101b1f3438e077d282495mbligh
12fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define VERSION_STRING "V 0.15"
13fe42c8a09884c2305ce101b1f3438e077d282495mbligh
14fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <fcntl.h>
15fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <getopt.h>
16fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <pthread.h>
17fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <signal.h>
18fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <stdlib.h>
19fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <stdio.h>
20fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <string.h>
21fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <time.h>
22fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <unistd.h>
23fe42c8a09884c2305ce101b1f3438e077d282495mbligh
24fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <linux/unistd.h>
25fe42c8a09884c2305ce101b1f3438e077d282495mbligh
26fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <sys/prctl.h>
27fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <sys/stat.h>
28fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <sys/types.h>
29fe42c8a09884c2305ce101b1f3438e077d282495mbligh#include <sys/time.h>
30fe42c8a09884c2305ce101b1f3438e077d282495mbligh
31fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
32fe42c8a09884c2305ce101b1f3438e077d282495mbligh
33fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* Ugly, but .... */
34fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define gettid() syscall(__NR_gettid)
35fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define sigev_notify_thread_id _sigev_un._tid
36fe42c8a09884c2305ce101b1f3438e077d282495mbligh
37fe42c8a09884c2305ce101b1f3438e077d282495mblighextern int clock_nanosleep(clockid_t __clock_id, int __flags,
38fe42c8a09884c2305ce101b1f3438e077d282495mbligh			   __const struct timespec *__req,
39fe42c8a09884c2305ce101b1f3438e077d282495mbligh			   struct timespec *__rem);
40fe42c8a09884c2305ce101b1f3438e077d282495mbligh
41fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define USEC_PER_SEC		1000000
42fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define NSEC_PER_SEC		1000000000
43fe42c8a09884c2305ce101b1f3438e077d282495mbligh
44fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define MODE_CYCLIC		0
45fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define MODE_CLOCK_NANOSLEEP	1
46fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define MODE_SYS_ITIMER		2
47fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define MODE_SYS_NANOSLEEP	3
48fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define MODE_SYS_OFFSET		2
49fe42c8a09884c2305ce101b1f3438e077d282495mbligh
50fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define TIMER_RELTIME		0
51fe42c8a09884c2305ce101b1f3438e077d282495mbligh
52fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* Must be power of 2 ! */
53fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define VALBUF_SIZE		16384
54fe42c8a09884c2305ce101b1f3438e077d282495mbligh
55fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define KVARS			32
56fe42c8a09884c2305ce101b1f3438e077d282495mbligh#define KVARNAMELEN		32
57fe42c8a09884c2305ce101b1f3438e077d282495mbligh
58fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* Struct to transfer parameters to the thread */
59fe42c8a09884c2305ce101b1f3438e077d282495mblighstruct thread_param {
60fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int prio;
61fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int mode;
62fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int timermode;
63fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int signal;
64fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int clock;
65fe42c8a09884c2305ce101b1f3438e077d282495mbligh	unsigned long max_cycles;
66fe42c8a09884c2305ce101b1f3438e077d282495mbligh	struct thread_stat *stats;
67fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int bufmsk;
68fe42c8a09884c2305ce101b1f3438e077d282495mbligh	unsigned long interval;
69fe42c8a09884c2305ce101b1f3438e077d282495mbligh};
70fe42c8a09884c2305ce101b1f3438e077d282495mbligh
71fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* Struct for statistics */
72fe42c8a09884c2305ce101b1f3438e077d282495mblighstruct thread_stat {
73fe42c8a09884c2305ce101b1f3438e077d282495mbligh	unsigned long cycles;
74fe42c8a09884c2305ce101b1f3438e077d282495mbligh	unsigned long cyclesread;
75fe42c8a09884c2305ce101b1f3438e077d282495mbligh	long min;
76fe42c8a09884c2305ce101b1f3438e077d282495mbligh	long max;
77fe42c8a09884c2305ce101b1f3438e077d282495mbligh	long act;
78fe42c8a09884c2305ce101b1f3438e077d282495mbligh	double avg;
79fe42c8a09884c2305ce101b1f3438e077d282495mbligh	long *values;
80fe42c8a09884c2305ce101b1f3438e077d282495mbligh	pthread_t thread;
81fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int threadstarted;
82fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int tid;
83fe42c8a09884c2305ce101b1f3438e077d282495mbligh};
84fe42c8a09884c2305ce101b1f3438e077d282495mbligh
85fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int shutdown;
86fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int tracelimit = 0;
87fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int ftrace = 0;
88fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int oldtrace = 0;
89fe42c8a09884c2305ce101b1f3438e077d282495mbligh
90fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* Backup of kernel variables that we modify */
91fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic struct kvars {
92fe42c8a09884c2305ce101b1f3438e077d282495mbligh	char name[KVARNAMELEN];
93fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int value;
94fe42c8a09884c2305ce101b1f3438e077d282495mbligh} kv[KVARS];
95fe42c8a09884c2305ce101b1f3438e077d282495mbligh
96fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic char *procfileprefix = "/proc/sys/kernel/";
97fe42c8a09884c2305ce101b1f3438e077d282495mbligh
98fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int kernvar(int mode, char *name, int *value)
99fe42c8a09884c2305ce101b1f3438e077d282495mbligh{
100fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int retval = 1;
101fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int procfilepath;
102fe42c8a09884c2305ce101b1f3438e077d282495mbligh	char procfilename[128];
103fe42c8a09884c2305ce101b1f3438e077d282495mbligh
104fe42c8a09884c2305ce101b1f3438e077d282495mbligh	strncpy(procfilename, procfileprefix, sizeof(procfilename));
105fe42c8a09884c2305ce101b1f3438e077d282495mbligh	strncat(procfilename, name,
106fe42c8a09884c2305ce101b1f3438e077d282495mbligh		sizeof(procfilename) - sizeof(procfileprefix));
107fe42c8a09884c2305ce101b1f3438e077d282495mbligh	procfilepath = open(procfilename, mode);
108fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (procfilepath >= 0) {
109fe42c8a09884c2305ce101b1f3438e077d282495mbligh		char buffer[32];
110fe42c8a09884c2305ce101b1f3438e077d282495mbligh
111fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (mode == O_RDONLY) {
112fe42c8a09884c2305ce101b1f3438e077d282495mbligh			if (read(procfilepath, buffer, sizeof(buffer)) > 0) {
113fe42c8a09884c2305ce101b1f3438e077d282495mbligh				char *endptr;
114fe42c8a09884c2305ce101b1f3438e077d282495mbligh				*value = strtol(buffer, &endptr, 0);
115fe42c8a09884c2305ce101b1f3438e077d282495mbligh				if (endptr != buffer)
116fe42c8a09884c2305ce101b1f3438e077d282495mbligh					retval = 0;
117fe42c8a09884c2305ce101b1f3438e077d282495mbligh			}
118fe42c8a09884c2305ce101b1f3438e077d282495mbligh		} else if (mode == O_WRONLY) {
119fe42c8a09884c2305ce101b1f3438e077d282495mbligh			snprintf(buffer, sizeof(buffer), "%d\n", *value);
120fe42c8a09884c2305ce101b1f3438e077d282495mbligh			if (write(procfilepath, buffer, strlen(buffer))
121fe42c8a09884c2305ce101b1f3438e077d282495mbligh			    == strlen(buffer))
122fe42c8a09884c2305ce101b1f3438e077d282495mbligh				retval = 0;
123fe42c8a09884c2305ce101b1f3438e077d282495mbligh		}
124fe42c8a09884c2305ce101b1f3438e077d282495mbligh		close(procfilepath);
125fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
126fe42c8a09884c2305ce101b1f3438e077d282495mbligh	return retval;
127fe42c8a09884c2305ce101b1f3438e077d282495mbligh}
128fe42c8a09884c2305ce101b1f3438e077d282495mbligh
129fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic void setkernvar(char *name, int value)
130fe42c8a09884c2305ce101b1f3438e077d282495mbligh{
131fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int i;
132fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int oldvalue;
133fe42c8a09884c2305ce101b1f3438e077d282495mbligh
134fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (kernvar(O_RDONLY, name, &oldvalue))
135fe42c8a09884c2305ce101b1f3438e077d282495mbligh		fprintf(stderr, "could not retrieve %s\n", name);
136fe42c8a09884c2305ce101b1f3438e077d282495mbligh	else {
137fe42c8a09884c2305ce101b1f3438e077d282495mbligh		for (i = 0; i < KVARS; i++) {
138fe42c8a09884c2305ce101b1f3438e077d282495mbligh			if (!strcmp(kv[i].name, name))
139fe42c8a09884c2305ce101b1f3438e077d282495mbligh				break;
140fe42c8a09884c2305ce101b1f3438e077d282495mbligh			if (kv[i].name[0] == '\0') {
141fe42c8a09884c2305ce101b1f3438e077d282495mbligh				strncpy(kv[i].name, name, sizeof(kv[i].name));
142fe42c8a09884c2305ce101b1f3438e077d282495mbligh				kv[i].value = oldvalue;
143fe42c8a09884c2305ce101b1f3438e077d282495mbligh				break;
144fe42c8a09884c2305ce101b1f3438e077d282495mbligh			}
145fe42c8a09884c2305ce101b1f3438e077d282495mbligh		}
146fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (i == KVARS)
147fe42c8a09884c2305ce101b1f3438e077d282495mbligh			fprintf(stderr, "could not backup %s (%d)\n", name,
148fe42c8a09884c2305ce101b1f3438e077d282495mbligh				oldvalue);
149fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
150fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (kernvar(O_WRONLY, name, &value))
151fe42c8a09884c2305ce101b1f3438e077d282495mbligh		fprintf(stderr, "could not set %s to %d\n", name, value);
152fe42c8a09884c2305ce101b1f3438e077d282495mbligh}
153fe42c8a09884c2305ce101b1f3438e077d282495mbligh
154fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic void restorekernvars(void)
155fe42c8a09884c2305ce101b1f3438e077d282495mbligh{
156fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int i;
157fe42c8a09884c2305ce101b1f3438e077d282495mbligh
158fe42c8a09884c2305ce101b1f3438e077d282495mbligh	for (i = 0; i < KVARS; i++) {
159fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (kv[i].name[0] != '\0') {
160fe42c8a09884c2305ce101b1f3438e077d282495mbligh			if (kernvar(O_WRONLY, kv[i].name, &kv[i].value))
161fe42c8a09884c2305ce101b1f3438e077d282495mbligh				fprintf(stderr, "could not restore %s to %d\n",
162fe42c8a09884c2305ce101b1f3438e077d282495mbligh					kv[i].name, kv[i].value);
163fe42c8a09884c2305ce101b1f3438e077d282495mbligh		}
164fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
165fe42c8a09884c2305ce101b1f3438e077d282495mbligh}
166fe42c8a09884c2305ce101b1f3438e077d282495mbligh
167fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic inline void tsnorm(struct timespec *ts)
168fe42c8a09884c2305ce101b1f3438e077d282495mbligh{
169fe42c8a09884c2305ce101b1f3438e077d282495mbligh	while (ts->tv_nsec >= NSEC_PER_SEC) {
170fe42c8a09884c2305ce101b1f3438e077d282495mbligh		ts->tv_nsec -= NSEC_PER_SEC;
171fe42c8a09884c2305ce101b1f3438e077d282495mbligh		ts->tv_sec++;
172fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
173fe42c8a09884c2305ce101b1f3438e077d282495mbligh}
174fe42c8a09884c2305ce101b1f3438e077d282495mbligh
175fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic inline long calcdiff(struct timespec t1, struct timespec t2)
176fe42c8a09884c2305ce101b1f3438e077d282495mbligh{
177fe42c8a09884c2305ce101b1f3438e077d282495mbligh	long diff;
178fe42c8a09884c2305ce101b1f3438e077d282495mbligh	diff = USEC_PER_SEC * ((int) t1.tv_sec - (int) t2.tv_sec);
179fe42c8a09884c2305ce101b1f3438e077d282495mbligh	diff += ((int) t1.tv_nsec - (int) t2.tv_nsec) / 1000;
180fe42c8a09884c2305ce101b1f3438e077d282495mbligh	return diff;
181fe42c8a09884c2305ce101b1f3438e077d282495mbligh}
182fe42c8a09884c2305ce101b1f3438e077d282495mbligh
183fe42c8a09884c2305ce101b1f3438e077d282495mbligh/*
184fe42c8a09884c2305ce101b1f3438e077d282495mbligh * timer thread
185fe42c8a09884c2305ce101b1f3438e077d282495mbligh *
186fe42c8a09884c2305ce101b1f3438e077d282495mbligh * Modes:
187fe42c8a09884c2305ce101b1f3438e077d282495mbligh * - clock_nanosleep based
188fe42c8a09884c2305ce101b1f3438e077d282495mbligh * - cyclic timer based
189fe42c8a09884c2305ce101b1f3438e077d282495mbligh *
190fe42c8a09884c2305ce101b1f3438e077d282495mbligh * Clock:
191fe42c8a09884c2305ce101b1f3438e077d282495mbligh * - CLOCK_MONOTONIC
192fe42c8a09884c2305ce101b1f3438e077d282495mbligh * - CLOCK_REALTIME
193fe42c8a09884c2305ce101b1f3438e077d282495mbligh * - CLOCK_MONOTONIC_HR
194fe42c8a09884c2305ce101b1f3438e077d282495mbligh * - CLOCK_REALTIME_HR
195fe42c8a09884c2305ce101b1f3438e077d282495mbligh *
196fe42c8a09884c2305ce101b1f3438e077d282495mbligh */
197fe42c8a09884c2305ce101b1f3438e077d282495mblighvoid *timerthread(void *param)
198fe42c8a09884c2305ce101b1f3438e077d282495mbligh{
199fe42c8a09884c2305ce101b1f3438e077d282495mbligh	struct thread_param *par = param;
200fe42c8a09884c2305ce101b1f3438e077d282495mbligh	struct sched_param schedp;
201fe42c8a09884c2305ce101b1f3438e077d282495mbligh	struct sigevent sigev;
202fe42c8a09884c2305ce101b1f3438e077d282495mbligh	sigset_t sigset;
203fe42c8a09884c2305ce101b1f3438e077d282495mbligh	timer_t timer;
204fe42c8a09884c2305ce101b1f3438e077d282495mbligh	struct timespec now, next, interval;
205fe42c8a09884c2305ce101b1f3438e077d282495mbligh	struct itimerval itimer;
206fe42c8a09884c2305ce101b1f3438e077d282495mbligh	struct itimerspec tspec;
207fe42c8a09884c2305ce101b1f3438e077d282495mbligh	struct thread_stat *stat = par->stats;
208fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int policy = par->prio ? SCHED_FIFO : SCHED_OTHER;
209fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int stopped = 0;
210fe42c8a09884c2305ce101b1f3438e077d282495mbligh
211fe42c8a09884c2305ce101b1f3438e077d282495mbligh	interval.tv_sec = par->interval / USEC_PER_SEC;
212fe42c8a09884c2305ce101b1f3438e077d282495mbligh	interval.tv_nsec = (par->interval % USEC_PER_SEC) * 1000;
213fe42c8a09884c2305ce101b1f3438e077d282495mbligh
214fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (tracelimit) {
215fe42c8a09884c2305ce101b1f3438e077d282495mbligh		setkernvar("trace_all_cpus", 1);
216fe42c8a09884c2305ce101b1f3438e077d282495mbligh		setkernvar("trace_freerunning", 1);
217fe42c8a09884c2305ce101b1f3438e077d282495mbligh		setkernvar("trace_print_on_crash", 0);
218fe42c8a09884c2305ce101b1f3438e077d282495mbligh		setkernvar("trace_user_triggered", 1);
219fe42c8a09884c2305ce101b1f3438e077d282495mbligh		setkernvar("trace_user_trigger_irq", -1);
220fe42c8a09884c2305ce101b1f3438e077d282495mbligh		setkernvar("trace_verbose", 0);
221fe42c8a09884c2305ce101b1f3438e077d282495mbligh		setkernvar("preempt_thresh", 0);
222fe42c8a09884c2305ce101b1f3438e077d282495mbligh		setkernvar("wakeup_timing", 0);
223fe42c8a09884c2305ce101b1f3438e077d282495mbligh		setkernvar("preempt_max_latency", 0);
224fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (ftrace)
225fe42c8a09884c2305ce101b1f3438e077d282495mbligh			setkernvar("mcount_enabled", 1);
226fe42c8a09884c2305ce101b1f3438e077d282495mbligh		setkernvar("trace_enabled", 1);
227fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
228fe42c8a09884c2305ce101b1f3438e077d282495mbligh
229fe42c8a09884c2305ce101b1f3438e077d282495mbligh	stat->tid = gettid();
230fe42c8a09884c2305ce101b1f3438e077d282495mbligh
231fe42c8a09884c2305ce101b1f3438e077d282495mbligh	sigemptyset(&sigset);
232fe42c8a09884c2305ce101b1f3438e077d282495mbligh	sigaddset(&sigset, par->signal);
233fe42c8a09884c2305ce101b1f3438e077d282495mbligh	sigprocmask(SIG_BLOCK, &sigset, NULL);
234fe42c8a09884c2305ce101b1f3438e077d282495mbligh
235fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (par->mode == MODE_CYCLIC) {
236fe42c8a09884c2305ce101b1f3438e077d282495mbligh		sigev.sigev_notify = SIGEV_THREAD_ID | SIGEV_SIGNAL;
237fe42c8a09884c2305ce101b1f3438e077d282495mbligh		sigev.sigev_signo = par->signal;
238fe42c8a09884c2305ce101b1f3438e077d282495mbligh		sigev.sigev_notify_thread_id = stat->tid;
239fe42c8a09884c2305ce101b1f3438e077d282495mbligh		timer_create(par->clock, &sigev, &timer);
240fe42c8a09884c2305ce101b1f3438e077d282495mbligh		tspec.it_interval = interval;
241fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
242fe42c8a09884c2305ce101b1f3438e077d282495mbligh
243fe42c8a09884c2305ce101b1f3438e077d282495mbligh	memset(&schedp, 0, sizeof(schedp));
244fe42c8a09884c2305ce101b1f3438e077d282495mbligh	schedp.sched_priority = par->prio;
245fe42c8a09884c2305ce101b1f3438e077d282495mbligh	sched_setscheduler(0, policy, &schedp);
246fe42c8a09884c2305ce101b1f3438e077d282495mbligh
247fe42c8a09884c2305ce101b1f3438e077d282495mbligh	/* Get current time */
248fe42c8a09884c2305ce101b1f3438e077d282495mbligh	clock_gettime(par->clock, &now);
249fe42c8a09884c2305ce101b1f3438e077d282495mbligh	next = now;
250fe42c8a09884c2305ce101b1f3438e077d282495mbligh	next.tv_sec++;
251fe42c8a09884c2305ce101b1f3438e077d282495mbligh
252fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (par->mode == MODE_CYCLIC) {
253fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (par->timermode == TIMER_ABSTIME)
254fe42c8a09884c2305ce101b1f3438e077d282495mbligh			tspec.it_value = next;
255fe42c8a09884c2305ce101b1f3438e077d282495mbligh		else {
256fe42c8a09884c2305ce101b1f3438e077d282495mbligh			tspec.it_value.tv_nsec = 0;
257fe42c8a09884c2305ce101b1f3438e077d282495mbligh			tspec.it_value.tv_sec = 1;
258fe42c8a09884c2305ce101b1f3438e077d282495mbligh		}
259fe42c8a09884c2305ce101b1f3438e077d282495mbligh		timer_settime(timer, par->timermode, &tspec, NULL);
260fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
261fe42c8a09884c2305ce101b1f3438e077d282495mbligh
262fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (par->mode == MODE_SYS_ITIMER) {
263fe42c8a09884c2305ce101b1f3438e077d282495mbligh		itimer.it_value.tv_sec = 1;
264fe42c8a09884c2305ce101b1f3438e077d282495mbligh		itimer.it_value.tv_usec = 0;
265fe42c8a09884c2305ce101b1f3438e077d282495mbligh		itimer.it_interval.tv_sec = interval.tv_sec;
266fe42c8a09884c2305ce101b1f3438e077d282495mbligh		itimer.it_interval.tv_usec = interval.tv_nsec / 1000;
267fe42c8a09884c2305ce101b1f3438e077d282495mbligh		setitimer (ITIMER_REAL,  &itimer, NULL);
268fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
269fe42c8a09884c2305ce101b1f3438e077d282495mbligh
270fe42c8a09884c2305ce101b1f3438e077d282495mbligh	stat->threadstarted++;
271fe42c8a09884c2305ce101b1f3438e077d282495mbligh
272fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (tracelimit) {
273fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (oldtrace)
274fe42c8a09884c2305ce101b1f3438e077d282495mbligh			gettimeofday(0,(struct timezone *)1);
275fe42c8a09884c2305ce101b1f3438e077d282495mbligh		else
276fe42c8a09884c2305ce101b1f3438e077d282495mbligh			prctl(0, 1);
277fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
278fe42c8a09884c2305ce101b1f3438e077d282495mbligh	while (!shutdown) {
279fe42c8a09884c2305ce101b1f3438e077d282495mbligh
280fe42c8a09884c2305ce101b1f3438e077d282495mbligh		long diff;
281fe42c8a09884c2305ce101b1f3438e077d282495mbligh		int sigs;
282fe42c8a09884c2305ce101b1f3438e077d282495mbligh
283fe42c8a09884c2305ce101b1f3438e077d282495mbligh		/* Wait for next period */
284fe42c8a09884c2305ce101b1f3438e077d282495mbligh		switch (par->mode) {
285fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case MODE_CYCLIC:
286fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case MODE_SYS_ITIMER:
287fe42c8a09884c2305ce101b1f3438e077d282495mbligh			if (sigwait(&sigset, &sigs) < 0)
288fe42c8a09884c2305ce101b1f3438e077d282495mbligh				goto out;
289fe42c8a09884c2305ce101b1f3438e077d282495mbligh			break;
290fe42c8a09884c2305ce101b1f3438e077d282495mbligh
291fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case MODE_CLOCK_NANOSLEEP:
292fe42c8a09884c2305ce101b1f3438e077d282495mbligh			if (par->timermode == TIMER_ABSTIME)
293fe42c8a09884c2305ce101b1f3438e077d282495mbligh				clock_nanosleep(par->clock, TIMER_ABSTIME,
294fe42c8a09884c2305ce101b1f3438e077d282495mbligh						&next, NULL);
295fe42c8a09884c2305ce101b1f3438e077d282495mbligh			else {
296fe42c8a09884c2305ce101b1f3438e077d282495mbligh				clock_gettime(par->clock, &now);
297fe42c8a09884c2305ce101b1f3438e077d282495mbligh				clock_nanosleep(par->clock, TIMER_RELTIME,
298fe42c8a09884c2305ce101b1f3438e077d282495mbligh						&interval, NULL);
299fe42c8a09884c2305ce101b1f3438e077d282495mbligh				next.tv_sec = now.tv_sec + interval.tv_sec;
300fe42c8a09884c2305ce101b1f3438e077d282495mbligh				next.tv_nsec = now.tv_nsec + interval.tv_nsec;
301fe42c8a09884c2305ce101b1f3438e077d282495mbligh				tsnorm(&next);
302fe42c8a09884c2305ce101b1f3438e077d282495mbligh			}
303fe42c8a09884c2305ce101b1f3438e077d282495mbligh			break;
304fe42c8a09884c2305ce101b1f3438e077d282495mbligh
305fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case MODE_SYS_NANOSLEEP:
306fe42c8a09884c2305ce101b1f3438e077d282495mbligh			clock_gettime(par->clock, &now);
307fe42c8a09884c2305ce101b1f3438e077d282495mbligh			nanosleep(&interval, NULL);
308fe42c8a09884c2305ce101b1f3438e077d282495mbligh			next.tv_sec = now.tv_sec + interval.tv_sec;
309fe42c8a09884c2305ce101b1f3438e077d282495mbligh			next.tv_nsec = now.tv_nsec + interval.tv_nsec;
310fe42c8a09884c2305ce101b1f3438e077d282495mbligh			tsnorm(&next);
311fe42c8a09884c2305ce101b1f3438e077d282495mbligh			break;
312fe42c8a09884c2305ce101b1f3438e077d282495mbligh		}
313fe42c8a09884c2305ce101b1f3438e077d282495mbligh		clock_gettime(par->clock, &now);
314fe42c8a09884c2305ce101b1f3438e077d282495mbligh
315fe42c8a09884c2305ce101b1f3438e077d282495mbligh		diff = calcdiff(now, next);
316fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (diff < stat->min)
317fe42c8a09884c2305ce101b1f3438e077d282495mbligh			stat->min = diff;
318fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (diff > stat->max)
319fe42c8a09884c2305ce101b1f3438e077d282495mbligh			stat->max = diff;
320fe42c8a09884c2305ce101b1f3438e077d282495mbligh		stat->avg += (double) diff;
321fe42c8a09884c2305ce101b1f3438e077d282495mbligh
322fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (!stopped && tracelimit && (diff > tracelimit)) {
323fe42c8a09884c2305ce101b1f3438e077d282495mbligh			stopped++;
324fe42c8a09884c2305ce101b1f3438e077d282495mbligh			if (oldtrace)
325fe42c8a09884c2305ce101b1f3438e077d282495mbligh				gettimeofday(0,0);
326fe42c8a09884c2305ce101b1f3438e077d282495mbligh			else
327fe42c8a09884c2305ce101b1f3438e077d282495mbligh				prctl(0, 0);
328fe42c8a09884c2305ce101b1f3438e077d282495mbligh			shutdown++;
329fe42c8a09884c2305ce101b1f3438e077d282495mbligh		}
330fe42c8a09884c2305ce101b1f3438e077d282495mbligh		stat->act = diff;
331fe42c8a09884c2305ce101b1f3438e077d282495mbligh		stat->cycles++;
332fe42c8a09884c2305ce101b1f3438e077d282495mbligh
333fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (par->bufmsk)
334fe42c8a09884c2305ce101b1f3438e077d282495mbligh			stat->values[stat->cycles & par->bufmsk] = diff;
335fe42c8a09884c2305ce101b1f3438e077d282495mbligh
336fe42c8a09884c2305ce101b1f3438e077d282495mbligh		next.tv_sec += interval.tv_sec;
337fe42c8a09884c2305ce101b1f3438e077d282495mbligh		next.tv_nsec += interval.tv_nsec;
338fe42c8a09884c2305ce101b1f3438e077d282495mbligh		tsnorm(&next);
339fe42c8a09884c2305ce101b1f3438e077d282495mbligh
340fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (par->max_cycles && par->max_cycles == stat->cycles)
341fe42c8a09884c2305ce101b1f3438e077d282495mbligh			break;
342fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
343fe42c8a09884c2305ce101b1f3438e077d282495mbligh
344fe42c8a09884c2305ce101b1f3438e077d282495mblighout:
345fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (par->mode == MODE_CYCLIC)
346fe42c8a09884c2305ce101b1f3438e077d282495mbligh		timer_delete(timer);
347fe42c8a09884c2305ce101b1f3438e077d282495mbligh
348fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (par->mode == MODE_SYS_ITIMER) {
349fe42c8a09884c2305ce101b1f3438e077d282495mbligh		itimer.it_value.tv_sec = 0;
350fe42c8a09884c2305ce101b1f3438e077d282495mbligh		itimer.it_value.tv_usec = 0;
351fe42c8a09884c2305ce101b1f3438e077d282495mbligh		itimer.it_interval.tv_sec = 0;
352fe42c8a09884c2305ce101b1f3438e077d282495mbligh		itimer.it_interval.tv_usec = 0;
353fe42c8a09884c2305ce101b1f3438e077d282495mbligh		setitimer (ITIMER_REAL,  &itimer, NULL);
354fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
355fe42c8a09884c2305ce101b1f3438e077d282495mbligh
356fe42c8a09884c2305ce101b1f3438e077d282495mbligh	/* switch to normal */
357fe42c8a09884c2305ce101b1f3438e077d282495mbligh	schedp.sched_priority = 0;
358fe42c8a09884c2305ce101b1f3438e077d282495mbligh	sched_setscheduler(0, SCHED_OTHER, &schedp);
359fe42c8a09884c2305ce101b1f3438e077d282495mbligh
360fe42c8a09884c2305ce101b1f3438e077d282495mbligh	stat->threadstarted = -1;
361fe42c8a09884c2305ce101b1f3438e077d282495mbligh
362fe42c8a09884c2305ce101b1f3438e077d282495mbligh	return NULL;
363fe42c8a09884c2305ce101b1f3438e077d282495mbligh}
364fe42c8a09884c2305ce101b1f3438e077d282495mbligh
365fe42c8a09884c2305ce101b1f3438e077d282495mbligh
366fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* Print usage information */
367fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic void display_help(void)
368fe42c8a09884c2305ce101b1f3438e077d282495mbligh{
369fe42c8a09884c2305ce101b1f3438e077d282495mbligh	printf("cyclictest %s\n", VERSION_STRING);
370fe42c8a09884c2305ce101b1f3438e077d282495mbligh	printf("Usage:\n"
371fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "cyclictest <options>\n\n"
372fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "-b USEC  --breaktrace=USEC send break trace command when latency > USEC\n"
373fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "-c CLOCK --clock=CLOCK     select clock\n"
374fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "                           0 = CLOCK_MONOTONIC (default)\n"
375fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "                           1 = CLOCK_REALTIME\n"
376fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "-d DIST  --distance=DIST   distance of thread intervals in us default=500\n"
377fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "-f                         function trace (when -b is active)\n"
378fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "-i INTV  --interval=INTV   base interval of thread in us default=1000\n"
379fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "-l LOOPS --loops=LOOPS     number of loops: default=0(endless)\n"
380fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "-n       --nanosleep       use clock_nanosleep\n"
381fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "-p PRIO  --prio=PRIO       priority of highest prio thread\n"
382fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "-q       --quiet           print only a summary on exit\n"
383fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "-r       --relative        use relative timer instead of absolute\n"
384fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "-s       --system          use sys_nanosleep and sys_setitimer\n"
385fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "-t NUM   --threads=NUM     number of threads: default=1\n"
386fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "-v       --verbose         output values on stdout for statistics\n"
387fe42c8a09884c2305ce101b1f3438e077d282495mbligh	       "                           format: n:c:v n=tasknum c=count v=value in us\n");
388fe42c8a09884c2305ce101b1f3438e077d282495mbligh	exit(0);
389fe42c8a09884c2305ce101b1f3438e077d282495mbligh}
390fe42c8a09884c2305ce101b1f3438e077d282495mbligh
391fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int use_nanosleep;
392fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int timermode  = TIMER_ABSTIME;
393fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int use_system;
394fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int priority;
395fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int num_threads = 1;
396fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int max_cycles;
397fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int clocksel = 0;
398fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int verbose;
399fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int quiet;
400fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int interval = 1000;
401fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int distance = 500;
402fe42c8a09884c2305ce101b1f3438e077d282495mbligh
403fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int clocksources[] = {
404fe42c8a09884c2305ce101b1f3438e077d282495mbligh	CLOCK_MONOTONIC,
405fe42c8a09884c2305ce101b1f3438e077d282495mbligh	CLOCK_REALTIME,
406fe42c8a09884c2305ce101b1f3438e077d282495mbligh};
407fe42c8a09884c2305ce101b1f3438e077d282495mbligh
408fe42c8a09884c2305ce101b1f3438e077d282495mbligh/* Process commandline options */
409fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic void process_options (int argc, char *argv[])
410fe42c8a09884c2305ce101b1f3438e077d282495mbligh{
411fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int error = 0;
412fe42c8a09884c2305ce101b1f3438e077d282495mbligh	for (;;) {
413fe42c8a09884c2305ce101b1f3438e077d282495mbligh		int option_index = 0;
414fe42c8a09884c2305ce101b1f3438e077d282495mbligh		/** Options for getopt */
415fe42c8a09884c2305ce101b1f3438e077d282495mbligh		static struct option long_options[] = {
416fe42c8a09884c2305ce101b1f3438e077d282495mbligh			{"breaktrace", required_argument, NULL, 'b'},
417fe42c8a09884c2305ce101b1f3438e077d282495mbligh			{"clock", required_argument, NULL, 'c'},
418fe42c8a09884c2305ce101b1f3438e077d282495mbligh			{"distance", required_argument, NULL, 'd'},
419fe42c8a09884c2305ce101b1f3438e077d282495mbligh			{"ftrace", no_argument, NULL, 'f'},
420fe42c8a09884c2305ce101b1f3438e077d282495mbligh			{"interval", required_argument, NULL, 'i'},
421fe42c8a09884c2305ce101b1f3438e077d282495mbligh			{"loops", required_argument, NULL, 'l'},
422fe42c8a09884c2305ce101b1f3438e077d282495mbligh			{"nanosleep", no_argument, NULL, 'n'},
423fe42c8a09884c2305ce101b1f3438e077d282495mbligh			{"priority", required_argument, NULL, 'p'},
424fe42c8a09884c2305ce101b1f3438e077d282495mbligh			{"quiet", no_argument, NULL, 'q'},
425fe42c8a09884c2305ce101b1f3438e077d282495mbligh			{"relative", no_argument, NULL, 'r'},
426fe42c8a09884c2305ce101b1f3438e077d282495mbligh			{"system", no_argument, NULL, 's'},
427fe42c8a09884c2305ce101b1f3438e077d282495mbligh			{"threads", required_argument, NULL, 't'},
428fe42c8a09884c2305ce101b1f3438e077d282495mbligh			{"verbose", no_argument, NULL, 'v'},
429fe42c8a09884c2305ce101b1f3438e077d282495mbligh			{"help", no_argument, NULL, '?'},
430fe42c8a09884c2305ce101b1f3438e077d282495mbligh			{NULL, 0, NULL, 0}
431fe42c8a09884c2305ce101b1f3438e077d282495mbligh		};
432fe42c8a09884c2305ce101b1f3438e077d282495mbligh		int c = getopt_long (argc, argv, "b:c:d:fi:l:np:qrst:v",
433fe42c8a09884c2305ce101b1f3438e077d282495mbligh			long_options, &option_index);
434fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (c == -1)
435fe42c8a09884c2305ce101b1f3438e077d282495mbligh			break;
436fe42c8a09884c2305ce101b1f3438e077d282495mbligh		switch (c) {
437fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case 'b': tracelimit = atoi(optarg); break;
438fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case 'c': clocksel = atoi(optarg); break;
439fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case 'd': distance = atoi(optarg); break;
440fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case 'f': ftrace = 1; break;
441fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case 'i': interval = atoi(optarg); break;
442fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case 'l': max_cycles = atoi(optarg); break;
443fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case 'n': use_nanosleep = MODE_CLOCK_NANOSLEEP; break;
444fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case 'p': priority = atoi(optarg); break;
445fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case 'q': quiet = 1; break;
446fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case 'r': timermode = TIMER_RELTIME; break;
447fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case 's': use_system = MODE_SYS_OFFSET; break;
448fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case 't': num_threads = atoi(optarg); break;
449fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case 'v': verbose = 1; break;
450fe42c8a09884c2305ce101b1f3438e077d282495mbligh		case '?': error = 1; break;
451fe42c8a09884c2305ce101b1f3438e077d282495mbligh		}
452fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
453fe42c8a09884c2305ce101b1f3438e077d282495mbligh
454fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (clocksel < 0 || clocksel > ARRAY_SIZE(clocksources))
455fe42c8a09884c2305ce101b1f3438e077d282495mbligh		error = 1;
456fe42c8a09884c2305ce101b1f3438e077d282495mbligh
457fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (priority < 0 || priority > 99)
458fe42c8a09884c2305ce101b1f3438e077d282495mbligh		error = 1;
459fe42c8a09884c2305ce101b1f3438e077d282495mbligh
460fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (num_threads < 1)
461fe42c8a09884c2305ce101b1f3438e077d282495mbligh		error = 1;
462fe42c8a09884c2305ce101b1f3438e077d282495mbligh
463fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (error)
464fe42c8a09884c2305ce101b1f3438e077d282495mbligh		display_help ();
465fe42c8a09884c2305ce101b1f3438e077d282495mbligh}
466fe42c8a09884c2305ce101b1f3438e077d282495mbligh
467fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic void check_kernel(void)
468fe42c8a09884c2305ce101b1f3438e077d282495mbligh{
469fe42c8a09884c2305ce101b1f3438e077d282495mbligh	size_t len;
470fe42c8a09884c2305ce101b1f3438e077d282495mbligh	char ver[256];
471fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int fd, maj, min, sub;
472fe42c8a09884c2305ce101b1f3438e077d282495mbligh
473fe42c8a09884c2305ce101b1f3438e077d282495mbligh	fd = open("/proc/version", O_RDONLY, 0666);
474fe42c8a09884c2305ce101b1f3438e077d282495mbligh	len = read(fd, ver, 255);
475fe42c8a09884c2305ce101b1f3438e077d282495mbligh	close(fd);
476fe42c8a09884c2305ce101b1f3438e077d282495mbligh	ver[len-1] = 0x0;
477fe42c8a09884c2305ce101b1f3438e077d282495mbligh	sscanf(ver, "Linux version %d.%d.%d", &maj, &min, &sub);
478fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (maj == 2 && min == 6 && sub < 18)
479fe42c8a09884c2305ce101b1f3438e077d282495mbligh		oldtrace = 1;
480fe42c8a09884c2305ce101b1f3438e077d282495mbligh}
481fe42c8a09884c2305ce101b1f3438e077d282495mbligh
482fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic int check_timer(void)
483fe42c8a09884c2305ce101b1f3438e077d282495mbligh{
484fe42c8a09884c2305ce101b1f3438e077d282495mbligh	struct timespec ts;
485fe42c8a09884c2305ce101b1f3438e077d282495mbligh
486fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (clock_getres(CLOCK_MONOTONIC, &ts))
487fe42c8a09884c2305ce101b1f3438e077d282495mbligh		return 1;
488fe42c8a09884c2305ce101b1f3438e077d282495mbligh
489fe42c8a09884c2305ce101b1f3438e077d282495mbligh	return (ts.tv_sec != 0 || ts.tv_nsec != 1);
490fe42c8a09884c2305ce101b1f3438e077d282495mbligh}
491fe42c8a09884c2305ce101b1f3438e077d282495mbligh
492fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic void sighand(int sig)
493fe42c8a09884c2305ce101b1f3438e077d282495mbligh{
494fe42c8a09884c2305ce101b1f3438e077d282495mbligh	shutdown = 1;
495fe42c8a09884c2305ce101b1f3438e077d282495mbligh}
496fe42c8a09884c2305ce101b1f3438e077d282495mbligh
497fe42c8a09884c2305ce101b1f3438e077d282495mblighstatic void print_stat(struct thread_param *par, int index, int verbose)
498fe42c8a09884c2305ce101b1f3438e077d282495mbligh{
499fe42c8a09884c2305ce101b1f3438e077d282495mbligh	struct thread_stat *stat = par->stats;
500fe42c8a09884c2305ce101b1f3438e077d282495mbligh
501fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (!verbose) {
502fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (quiet != 1) {
503fe42c8a09884c2305ce101b1f3438e077d282495mbligh			printf("T:%2d (%5d) P:%2d I:%ld C:%7lu "
504fe42c8a09884c2305ce101b1f3438e077d282495mbligh			       "Min:%7ld Act:%5ld Avg:%5ld Max:%8ld\n",
505fe42c8a09884c2305ce101b1f3438e077d282495mbligh			       index, stat->tid, par->prio, par->interval,
506fe42c8a09884c2305ce101b1f3438e077d282495mbligh			       stat->cycles, stat->min, stat->act,
507fe42c8a09884c2305ce101b1f3438e077d282495mbligh			       stat->cycles ?
508fe42c8a09884c2305ce101b1f3438e077d282495mbligh			       (long)(stat->avg/stat->cycles) : 0, stat->max);
509fe42c8a09884c2305ce101b1f3438e077d282495mbligh		}
510fe42c8a09884c2305ce101b1f3438e077d282495mbligh	} else {
511fe42c8a09884c2305ce101b1f3438e077d282495mbligh		while (stat->cycles != stat->cyclesread) {
512fe42c8a09884c2305ce101b1f3438e077d282495mbligh			long diff = stat->values[stat->cyclesread & par->bufmsk];
513fe42c8a09884c2305ce101b1f3438e077d282495mbligh			printf("%8d:%8lu:%8ld\n", index, stat->cyclesread, diff);
514fe42c8a09884c2305ce101b1f3438e077d282495mbligh			stat->cyclesread++;
515fe42c8a09884c2305ce101b1f3438e077d282495mbligh		}
516fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
517fe42c8a09884c2305ce101b1f3438e077d282495mbligh}
518fe42c8a09884c2305ce101b1f3438e077d282495mbligh
519fe42c8a09884c2305ce101b1f3438e077d282495mblighint main(int argc, char **argv)
520fe42c8a09884c2305ce101b1f3438e077d282495mbligh{
521fe42c8a09884c2305ce101b1f3438e077d282495mbligh	sigset_t sigset;
522fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int signum = SIGALRM;
523fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int mode;
524fe42c8a09884c2305ce101b1f3438e077d282495mbligh	struct thread_param *par;
525fe42c8a09884c2305ce101b1f3438e077d282495mbligh	struct thread_stat *stat;
526fe42c8a09884c2305ce101b1f3438e077d282495mbligh	int i, ret = -1;
527fe42c8a09884c2305ce101b1f3438e077d282495mbligh
528fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (geteuid()) {
529fe42c8a09884c2305ce101b1f3438e077d282495mbligh		fprintf(stderr, "cyclictest: need to run as root!\n");
530fe42c8a09884c2305ce101b1f3438e077d282495mbligh		exit(-1);
531fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
532fe42c8a09884c2305ce101b1f3438e077d282495mbligh
533fe42c8a09884c2305ce101b1f3438e077d282495mbligh	process_options(argc, argv);
534fe42c8a09884c2305ce101b1f3438e077d282495mbligh
535fe42c8a09884c2305ce101b1f3438e077d282495mbligh	check_kernel();
536fe42c8a09884c2305ce101b1f3438e077d282495mbligh
537fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (check_timer())
538fe42c8a09884c2305ce101b1f3438e077d282495mbligh		fprintf(stderr, "WARNING: High resolution timers not available\n");
539fe42c8a09884c2305ce101b1f3438e077d282495mbligh
540fe42c8a09884c2305ce101b1f3438e077d282495mbligh	mode = use_nanosleep + use_system;
541fe42c8a09884c2305ce101b1f3438e077d282495mbligh
542fe42c8a09884c2305ce101b1f3438e077d282495mbligh	sigemptyset(&sigset);
543fe42c8a09884c2305ce101b1f3438e077d282495mbligh	sigaddset(&sigset, signum);
544fe42c8a09884c2305ce101b1f3438e077d282495mbligh	sigprocmask (SIG_BLOCK, &sigset, NULL);
545fe42c8a09884c2305ce101b1f3438e077d282495mbligh
546fe42c8a09884c2305ce101b1f3438e077d282495mbligh	signal(SIGINT, sighand);
547fe42c8a09884c2305ce101b1f3438e077d282495mbligh	signal(SIGTERM, sighand);
548fe42c8a09884c2305ce101b1f3438e077d282495mbligh
549fe42c8a09884c2305ce101b1f3438e077d282495mbligh	par = calloc(num_threads, sizeof(struct thread_param));
550fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (!par)
551fe42c8a09884c2305ce101b1f3438e077d282495mbligh		goto out;
552fe42c8a09884c2305ce101b1f3438e077d282495mbligh	stat = calloc(num_threads, sizeof(struct thread_stat));
553fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (!stat)
554fe42c8a09884c2305ce101b1f3438e077d282495mbligh		goto outpar;
555fe42c8a09884c2305ce101b1f3438e077d282495mbligh
556fe42c8a09884c2305ce101b1f3438e077d282495mbligh	for (i = 0; i < num_threads; i++) {
557fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (verbose) {
558fe42c8a09884c2305ce101b1f3438e077d282495mbligh			stat[i].values = calloc(VALBUF_SIZE, sizeof(long));
559fe42c8a09884c2305ce101b1f3438e077d282495mbligh			if (!stat[i].values)
560fe42c8a09884c2305ce101b1f3438e077d282495mbligh				goto outall;
561fe42c8a09884c2305ce101b1f3438e077d282495mbligh			par[i].bufmsk = VALBUF_SIZE - 1;
562fe42c8a09884c2305ce101b1f3438e077d282495mbligh		}
563fe42c8a09884c2305ce101b1f3438e077d282495mbligh
564fe42c8a09884c2305ce101b1f3438e077d282495mbligh		par[i].prio = priority;
565fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (priority)
566fe42c8a09884c2305ce101b1f3438e077d282495mbligh			priority--;
567fe42c8a09884c2305ce101b1f3438e077d282495mbligh		par[i].clock = clocksources[clocksel];
568fe42c8a09884c2305ce101b1f3438e077d282495mbligh		par[i].mode = mode;
569fe42c8a09884c2305ce101b1f3438e077d282495mbligh		par[i].timermode = timermode;
570fe42c8a09884c2305ce101b1f3438e077d282495mbligh		par[i].signal = signum;
571fe42c8a09884c2305ce101b1f3438e077d282495mbligh		par[i].interval = interval;
572fe42c8a09884c2305ce101b1f3438e077d282495mbligh		interval += distance;
573fe42c8a09884c2305ce101b1f3438e077d282495mbligh		par[i].max_cycles = max_cycles;
574fe42c8a09884c2305ce101b1f3438e077d282495mbligh		par[i].stats = &stat[i];
575fe42c8a09884c2305ce101b1f3438e077d282495mbligh		stat[i].min = 1000000;
576fe42c8a09884c2305ce101b1f3438e077d282495mbligh		stat[i].max = -1000000;
577fe42c8a09884c2305ce101b1f3438e077d282495mbligh		stat[i].avg = 0.0;
578fe42c8a09884c2305ce101b1f3438e077d282495mbligh		pthread_create(&stat[i].thread, NULL, timerthread, &par[i]);
579fe42c8a09884c2305ce101b1f3438e077d282495mbligh		stat[i].threadstarted = 1;
580fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
581fe42c8a09884c2305ce101b1f3438e077d282495mbligh
582fe42c8a09884c2305ce101b1f3438e077d282495mbligh	while (!shutdown) {
583fe42c8a09884c2305ce101b1f3438e077d282495mbligh		char lavg[256];
584fe42c8a09884c2305ce101b1f3438e077d282495mbligh		int fd, len, allstopped = 0;
585fe42c8a09884c2305ce101b1f3438e077d282495mbligh
586fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (!verbose && !quiet) {
587fe42c8a09884c2305ce101b1f3438e077d282495mbligh			fd = open("/proc/loadavg", O_RDONLY, 0666);
588fe42c8a09884c2305ce101b1f3438e077d282495mbligh			len = read(fd, &lavg, 255);
589fe42c8a09884c2305ce101b1f3438e077d282495mbligh			close(fd);
590fe42c8a09884c2305ce101b1f3438e077d282495mbligh			lavg[len-1] = 0x0;
591fe42c8a09884c2305ce101b1f3438e077d282495mbligh			printf("%s          \n\n", lavg);
592fe42c8a09884c2305ce101b1f3438e077d282495mbligh		}
593fe42c8a09884c2305ce101b1f3438e077d282495mbligh
594fe42c8a09884c2305ce101b1f3438e077d282495mbligh		for (i = 0; i < num_threads; i++) {
595fe42c8a09884c2305ce101b1f3438e077d282495mbligh
596fe42c8a09884c2305ce101b1f3438e077d282495mbligh			print_stat(&par[i], i, verbose);
597fe42c8a09884c2305ce101b1f3438e077d282495mbligh			if(max_cycles && stat[i].cycles >= max_cycles)
598fe42c8a09884c2305ce101b1f3438e077d282495mbligh				allstopped++;
599fe42c8a09884c2305ce101b1f3438e077d282495mbligh		}
600fe42c8a09884c2305ce101b1f3438e077d282495mbligh		usleep(10000);
601fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (shutdown || allstopped)
602fe42c8a09884c2305ce101b1f3438e077d282495mbligh			break;
603fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (!verbose && !quiet)
604fe42c8a09884c2305ce101b1f3438e077d282495mbligh			printf("\033[%dA", num_threads + 2);
605fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
606fe42c8a09884c2305ce101b1f3438e077d282495mbligh	ret = 0;
607fe42c8a09884c2305ce101b1f3438e077d282495mbligh outall:
608fe42c8a09884c2305ce101b1f3438e077d282495mbligh	shutdown = 1;
609fe42c8a09884c2305ce101b1f3438e077d282495mbligh	usleep(50000);
610fe42c8a09884c2305ce101b1f3438e077d282495mbligh	if (quiet)
611fe42c8a09884c2305ce101b1f3438e077d282495mbligh		quiet = 2;
612fe42c8a09884c2305ce101b1f3438e077d282495mbligh	for (i = 0; i < num_threads; i++) {
613fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (stat[i].threadstarted > 0)
614fe42c8a09884c2305ce101b1f3438e077d282495mbligh			pthread_kill(stat[i].thread, SIGTERM);
615fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (stat[i].threadstarted) {
616fe42c8a09884c2305ce101b1f3438e077d282495mbligh			pthread_join(stat[i].thread, NULL);
617fe42c8a09884c2305ce101b1f3438e077d282495mbligh			if (quiet)
618fe42c8a09884c2305ce101b1f3438e077d282495mbligh				print_stat(&par[i], i, 0);
619fe42c8a09884c2305ce101b1f3438e077d282495mbligh		}
620fe42c8a09884c2305ce101b1f3438e077d282495mbligh		if (stat[i].values)
621fe42c8a09884c2305ce101b1f3438e077d282495mbligh			free(stat[i].values);
622fe42c8a09884c2305ce101b1f3438e077d282495mbligh	}
623fe42c8a09884c2305ce101b1f3438e077d282495mbligh	free(stat);
624fe42c8a09884c2305ce101b1f3438e077d282495mbligh outpar:
625fe42c8a09884c2305ce101b1f3438e077d282495mbligh	free(par);
626fe42c8a09884c2305ce101b1f3438e077d282495mbligh out:
627fe42c8a09884c2305ce101b1f3438e077d282495mbligh	/* Be a nice program, cleanup */
628fe42c8a09884c2305ce101b1f3438e077d282495mbligh	restorekernvars();
629fe42c8a09884c2305ce101b1f3438e077d282495mbligh
630fe42c8a09884c2305ce101b1f3438e077d282495mbligh	exit(ret);
631fe42c8a09884c2305ce101b1f3438e077d282495mbligh}
632