1/*
2 * gcc -Wall -Werror -O3 -static -o ctx ctx.c
3 */
4
5#define errx(x,y...) { fprintf(stderr, y); fprintf(stderr, "\n"); exit(x); }
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <unistd.h>
10#include <sys/time.h>
11#include <signal.h>
12#if defined (LWP)
13#include <sys/ucontext.h>
14#include <sys/lwp.h>
15#endif
16
17#define ITERATIONS	8192
18#define PASSES		50
19
20int fd0[2], fd1[2];
21unsigned long elapsed_times[ITERATIONS];
22unsigned long overhead;
23pid_t childpid;
24
25static void
26usage(void)
27{
28	printf("ctx [-hl]\n");
29	exit(1);
30}
31
32static void
33child(void)
34{
35	int ch;
36
37	ch = 0;
38	if (write(fd1[1], &ch, 1) != 1)
39		errx(1, "child write failed");
40	while (1) {
41		if (read(fd0[0], &ch, 1) != 1)
42			errx(1, "child read failed");
43		if (write(fd1[1], &ch, 1) != 1)
44			errx(1, "child write failed");
45	}
46}
47
48static void
49dump_results(void)
50{
51	unsigned long min_time, max_time, sum;
52	int i;
53
54	min_time = elapsed_times[0];
55	max_time = elapsed_times[0];
56	sum = 0;
57	for (i=1; i<ITERATIONS; i++) {
58		if (elapsed_times[i] < min_time)
59			min_time = elapsed_times[i];
60		if (elapsed_times[i] > max_time)
61			max_time = elapsed_times[i];
62		sum += elapsed_times[i] - overhead;
63	}
64	min_time -= overhead;
65	max_time -= overhead;
66
67	printf("min latency: %f\n", (double)min_time / PASSES);
68	printf("max latency: %f\n", (double)max_time / PASSES);
69	printf("mean latency: %f\n", (double)sum / ITERATIONS / PASSES);
70}
71
72int
73main(int argc, char *argv[])
74{
75	int i, ch, count;
76	struct timeval before, after;
77	unsigned long elapsed;
78	int use_lwps = 0;
79
80	memset(elapsed_times, 0, ITERATIONS);
81
82	while ((ch = getopt(argc, argv, "hl")) != -1) {
83		switch (ch) {
84		case 'l':
85#if defined(LWP)
86			use_lwps = 1;
87#else
88			errx(1, "not supported");
89#endif
90			break;
91		case 'h':
92			usage();
93		}
94	}
95	argc -= optind;
96	argv += optind;
97
98	sleep(1);
99
100	if (pipe(fd0) != 0)
101		errx(1, "Unable to create pipe");
102	if (pipe(fd1) != 0)
103		errx(1, "Unable to create pipe");
104
105	/*
106	 * Determine overhead
107	 */
108	for (count=0; count<2; count++) {
109		gettimeofday(&before, NULL);
110		for (i=0; i<2*(PASSES/2); i++) {
111			ch = 0;
112			write(fd0[1], &ch, 1);
113			read(fd0[0], &ch, 1);
114		}
115		gettimeofday(&after, NULL);
116		overhead = 1000000 * (after.tv_sec - before.tv_sec);
117		overhead += after.tv_usec - before.tv_usec;
118	}
119
120	if (use_lwps) {
121#if defined(LWP)
122		ucontext_t u;
123		ucontext_t *contextp;
124		int stacksize = 65536;
125		void *stackbase;
126		lwpid_t l;
127		int error;
128
129		getcontext(&u);
130		contextp = (ucontext_t *)malloc(sizeof(ucontext_t));
131		stackbase = malloc(stacksize);
132		sigprocmask(SIG_SETMASK, NULL, &contextp->uc_sigmask);
133		_lwp_makecontext(contextp, child, NULL, NULL,
134			stackbase, stacksize);
135		error = _lwp_create(contextp, 0, &l);
136		if (error)
137			errx(1, "error _lwp_create");
138#endif
139	} else {
140		switch (childpid = fork()) {
141		case 0:		/* child */
142			child();
143		case -1:	/* error */
144			errx(1, "error forking");
145			break;
146		}
147	}
148
149	ch = 0;
150	if (read(fd1[0], &ch, 1) != 1)
151		errx(1, "parent read failed");
152	for (count=0; count<ITERATIONS; count++) {
153		gettimeofday(&before, NULL);
154		for (i=0; i<PASSES/2; i++) {
155			ch = 0;
156			if (write(fd0[1], &ch, 1) != 1)
157				errx(1, "parent write failed");
158			if (read(fd1[0], &ch, 1) != 1)
159				errx(1, "parent read failed");
160		}
161		gettimeofday(&after, NULL);
162		elapsed = 1000000 * (after.tv_sec - before.tv_sec);
163		elapsed += after.tv_usec - before.tv_usec;
164		elapsed_times[count] = elapsed;
165	}
166
167	if (!use_lwps)
168		kill(childpid, SIGTERM);
169	dump_results();
170
171	return (0);
172}
173
174
175/*
176 * PMAX_SA:
177 *
178 * min latency: 93.100000
179 * max latency: 150.700000
180 * mean latency: 100.857581
181 *
182 * PMAX_CHOOSEPROC:
183 *
184 * min latency: 49.350000
185 * max latency: 76.750000
186 * mean latency: 54.141626
187 *
188 * PMAX_OLD:
189 *
190 * min latency: 54.750000
191 * max latency: 76.050000
192 * mean latency: 60.088654
193 *
194 * HP300_SA:
195 *
196 * min latency: 352.560000
197 * max latency: 402.960000
198 * mean latency: 367.836250
199 *
200 * HP300_CHOOSEPROC:
201 *
202 * min latency: 129.200000
203 * max latency: 187.040000
204 * mean latency: 142.528223
205 *
206 * HP300_OLD:
207 *
208 * min latency: 357.360000
209 * max latency: 414.400000
210 * mean latency: 372.436104
211 *
212 */
213