xref: /inferno-os/os/mpc/devbench.c (revision 6e425a9de8c003b5a733621a6b6730ec3cc902b8)
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 #include "../port/error.h"
8 
9 typedef struct Psync Psync;
10 
11 enum {
12 	Maxprocs=2,
13 };
14 
15 struct Psync {
16 	Rendez	r;
17 	int	flag;
18 };
19 static Psync timesync[Maxprocs];
20 static Ref nactive;
21 static Ref nbusy;
22 
23 static int
24 timev(void *a)
25 {
26 	return *(int*)a;
27 }
28 
29 static void
30 timesched0(void *ap)
31 {
32 	long tot, t, i, lim, low, max;
33 	Psync *ps;
34 
35 	ps = ap;
36 	sleep(&ps->r, timev, &ps->flag);
37 	setpri(PriRealtime);
38 	incref(&nbusy);
39 	while(nbusy.ref < nactive.ref)
40 		sched();
41 	lim = 1000;
42 	low = 64000000;
43 	max = 0;
44 	tot = 0;
45 	for(i=0; i<lim; i++){
46 if(i<8)print("%lud\n", up->pid);
47 		do{
48 			t = gettbl();
49 			sched();
50 			t = gettbl()-t;
51 		}while(t < 0);
52 		if(t < low)
53 			low = t;
54 		if(t > max)
55 			max = t;
56 		tot += t;
57 	}
58 	print("%lud %lud %lud %lud %lud\n", up->pid, lim, tot, low, max);
59 	decref(&nactive);
60 	pexit("", 0);
61 }
62 
63 static void
64 timesched(void)
65 {
66 	int i, np;
67 
68 	for(np=1; np<=Maxprocs; np++){
69 		nactive.ref = np;
70 		print("%d procs\n", np);
71 		setpri(PriRealtime);
72 		for(i=0; i<np; i++)
73 			kproc("timesched", timesched0, &timesync[i], 0);
74 		for(i=0; i<np; i++){
75 			timesync[i].flag = 1;
76 			wakeup(&timesync[i].r);
77 		}
78 		setpri(PriNormal);
79 		while(nactive.ref>0)
80 			sched();
81 	}
82 }
83 
84 typedef struct Ictr Ictr;
85 struct Ictr {
86 	ulong	base;
87 	ulong	sleep;
88 	ulong	spllo;
89 	ulong	intr;
90 	ulong	isave;
91 	ulong	arrive;
92 	ulong	wakeup;
93 	ulong	awake;
94 };
95 static Ictr counters[100], *curct;
96 static int intrwant;
97 static Rendez vous;
98 int	spltbl;	/* set by spllo */
99 int	intrtbl;	/* set by intrvec() */
100 int	isavetbl;	/* set by intrvec() */
101 
102 static void
103 intrwake(Ureg*, void*)
104 {
105 	m->iomem->tgcr &= ~1;	/* reset the timer */
106 	curct->spllo = spltbl;
107 	curct->intr = intrtbl;
108 	curct->isave = isavetbl;
109 	curct->arrive = gettbl();
110 	intrwant = 0;
111 	wakeup(&vous);
112 	curct->wakeup = gettbl();
113 }
114 
115 /*
116  * sleep calls intrtest with splhi (under lock):
117  * provoke the interrupt now, so that it is guaranteed
118  * not to happen until sleep has queued the process,
119  * forcing wakeup to do something.
120  */
121 static int
122 intrtest(void*)
123 {
124 	m->iomem->tgcr |= 1;		/* enable timer: allow interrupt */
125 	curct->sleep = gettbl();
126 	return intrwant==0;
127 }
128 
129 static void
130 intrtime(void)
131 {
132 	IMM *io;
133 	Ictr *ic;
134 	long t;
135 	int i;
136 
137 	sched();
138 	curct = counters;
139 	io = ioplock();
140 	io->tgcr &= ~3;
141 	iopunlock();
142 	intrenable(VectorCPIC+0x19, intrwake, nil, BUSUNKNOWN, "bench");
143 	for(i=0; i<nelem(counters); i++){
144 		curct = &counters[i];
145 		//puttbl(0);
146 		intrwant = 1;
147 		io = m->iomem;	/* don't lock, to save time */
148 		io->tmr1 = (0<<8)|TimerORI|TimerSclk;
149 		io->trr1 = 1;
150 		curct->base = gettbl();
151 		sleep(&vous, intrtest, nil);
152 		curct->awake = gettbl();
153 		sched();	/* just to slow it down between trials */
154 	}
155 	m->iomem->tmr1 = 0;
156 	print("interrupt\n");
157 	for(i=0; i<20; i++){
158 		ic = &counters[i];
159 		t = ic->awake - ic->base;
160 		ic->awake -= ic->wakeup;
161 		ic->wakeup -= ic->arrive;
162 		ic->arrive -= ic->isave;
163 		ic->isave -= ic->intr;
164 		ic->intr -= ic->spllo;
165 		ic->spllo -= ic->sleep;
166 		ic->sleep -= ic->base;
167 		print("%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t%ld\t%ld\n", ic->sleep, ic->spllo, ic->intr, ic->isave, ic->arrive, ic->wakeup, ic->awake, t);
168 	}
169 }
170 
171 static Chan*
172 benchattach(char *spec)
173 {
174 	timesched();
175 	intrtime();
176 	USED(spec);
177 	error(Eperm);
178 	return nil;
179 }
180 
181 static Walkqid*
182 benchwalk(Chan*, Chan*, char**, int)
183 {
184 	error(Enonexist);
185 	return 0;
186 }
187 
188 static Chan*
189 benchopen(Chan*, int)
190 {
191 	error(Eperm);
192 	return nil;
193 }
194 
195 static int
196 benchstat(Chan*, uchar*, int)
197 {
198 	error(Eperm);
199 	return 0;
200 }
201 
202 static void
203 benchclose(Chan*)
204 {
205 }
206 
207 static long
208 benchread(Chan *c, void *buf, long n, vlong offset)
209 {
210 	USED(c, buf, n, offset);
211 	error(Eperm);
212 	return 0;
213 }
214 
215 static long
216 benchwrite(Chan *c, void *buf, long n, vlong offset)
217 {
218 	USED(c, buf, n, offset);
219 	error(Eperm);
220 	return 0;
221 }
222 
223 
224 Dev	benchdevtab = {
225 	'x',
226 	"bench",
227 
228 	devreset,
229 	devinit,
230 	devshutdown,
231 	benchattach,
232 	benchwalk,
233 	benchstat,
234 	benchopen,
235 	devcreate,
236 	benchclose,
237 	benchread,
238 	devbread,
239 	benchwrite,
240 	devbwrite,
241 	devremove,
242 	devwstat,
243 };
244