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