1*9ef1f84bSDavid du Colombier #include "u.h"
2*9ef1f84bSDavid du Colombier #include "../port/lib.h"
3*9ef1f84bSDavid du Colombier #include "mem.h"
4*9ef1f84bSDavid du Colombier #include "dat.h"
5*9ef1f84bSDavid du Colombier #include "fns.h"
6*9ef1f84bSDavid du Colombier #include "../port/error.h"
7*9ef1f84bSDavid du Colombier
8*9ef1f84bSDavid du Colombier #include "probe.h"
9*9ef1f84bSDavid du Colombier
10*9ef1f84bSDavid du Colombier enum {
11*9ef1f84bSDavid du Colombier Qdir,
12*9ef1f84bSDavid du Colombier Qctl,
13*9ef1f84bSDavid du Colombier Qdata,
14*9ef1f84bSDavid du Colombier };
15*9ef1f84bSDavid du Colombier
16*9ef1f84bSDavid du Colombier enum {
17*9ef1f84bSDavid du Colombier ProbeEntry = 1,
18*9ef1f84bSDavid du Colombier ProbeExit
19*9ef1f84bSDavid du Colombier };
20*9ef1f84bSDavid du Colombier
21*9ef1f84bSDavid du Colombier /* fix me make this programmable */
22*9ef1f84bSDavid du Colombier enum {
23*9ef1f84bSDavid du Colombier defaultlogsize = 1024,
24*9ef1f84bSDavid du Colombier printsize = 64,
25*9ef1f84bSDavid du Colombier };
26*9ef1f84bSDavid du Colombier
27*9ef1f84bSDavid du Colombier typedef struct Probelog Probelog;
28*9ef1f84bSDavid du Colombier struct Probelog {
29*9ef1f84bSDavid du Colombier uvlong ticks;
30*9ef1f84bSDavid du Colombier /* yeah, waste a whole int on something stupid but ... */
31*9ef1f84bSDavid du Colombier int info;
32*9ef1f84bSDavid du Colombier ulong pc;
33*9ef1f84bSDavid du Colombier /* these are different depending on type */
34*9ef1f84bSDavid du Colombier long dat[4];
35*9ef1f84bSDavid du Colombier };
36*9ef1f84bSDavid du Colombier
37*9ef1f84bSDavid du Colombier static Rendez probesleep;
38*9ef1f84bSDavid du Colombier static QLock probeslk;
39*9ef1f84bSDavid du Colombier static Probe *probes;
40*9ef1f84bSDavid du Colombier static Lock loglk;
41*9ef1f84bSDavid du Colombier static Probelog *probelog = nil;
42*9ef1f84bSDavid du Colombier /* probe indices. These are just unsigned longs. You mask them
43*9ef1f84bSDavid du Colombier * to get an index. This makes fifo empty/full etc. trivial.
44*9ef1f84bSDavid du Colombier */
45*9ef1f84bSDavid du Colombier static ulong pw = 0, pr = 0;
46*9ef1f84bSDavid du Colombier static int probesactive = 0;
47*9ef1f84bSDavid du Colombier static unsigned long logsize = defaultlogsize, logmask = defaultlogsize - 1;
48*9ef1f84bSDavid du Colombier
49*9ef1f84bSDavid du Colombier static char eventname[] = {
50*9ef1f84bSDavid du Colombier [ProbeEntry] = 'E',
51*9ef1f84bSDavid du Colombier [ProbeExit] = 'X'
52*9ef1f84bSDavid du Colombier };
53*9ef1f84bSDavid du Colombier
54*9ef1f84bSDavid du Colombier static Dirtab probedir[]={
55*9ef1f84bSDavid du Colombier ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
56*9ef1f84bSDavid du Colombier "probectl", {Qctl}, 0, 0664,
57*9ef1f84bSDavid du Colombier "probe", {Qdata}, 0, 0440,
58*9ef1f84bSDavid du Colombier };
59*9ef1f84bSDavid du Colombier
60*9ef1f84bSDavid du Colombier char hex[] = {
61*9ef1f84bSDavid du Colombier '0',
62*9ef1f84bSDavid du Colombier '1',
63*9ef1f84bSDavid du Colombier '2',
64*9ef1f84bSDavid du Colombier '3',
65*9ef1f84bSDavid du Colombier '4',
66*9ef1f84bSDavid du Colombier '5',
67*9ef1f84bSDavid du Colombier '6',
68*9ef1f84bSDavid du Colombier '7',
69*9ef1f84bSDavid du Colombier '8',
70*9ef1f84bSDavid du Colombier '9',
71*9ef1f84bSDavid du Colombier 'A',
72*9ef1f84bSDavid du Colombier 'B',
73*9ef1f84bSDavid du Colombier 'C',
74*9ef1f84bSDavid du Colombier 'D',
75*9ef1f84bSDavid du Colombier 'E',
76*9ef1f84bSDavid du Colombier 'F',
77*9ef1f84bSDavid du Colombier };
78*9ef1f84bSDavid du Colombier
79*9ef1f84bSDavid du Colombier /* big-endian ... */
80*9ef1f84bSDavid du Colombier void
hex32(ulong l,char * c)81*9ef1f84bSDavid du Colombier hex32(ulong l, char *c)
82*9ef1f84bSDavid du Colombier {
83*9ef1f84bSDavid du Colombier int i;
84*9ef1f84bSDavid du Colombier for(i = 8; i; i--){
85*9ef1f84bSDavid du Colombier c[i-1] = hex[l&0xf];
86*9ef1f84bSDavid du Colombier l >>= 4;
87*9ef1f84bSDavid du Colombier }
88*9ef1f84bSDavid du Colombier }
89*9ef1f84bSDavid du Colombier
90*9ef1f84bSDavid du Colombier void
hex64(uvlong l,char * c)91*9ef1f84bSDavid du Colombier hex64(uvlong l, char *c)
92*9ef1f84bSDavid du Colombier {
93*9ef1f84bSDavid du Colombier hex32(l>>32, c);
94*9ef1f84bSDavid du Colombier hex32(l, &c[8]);
95*9ef1f84bSDavid du Colombier }
96*9ef1f84bSDavid du Colombier static int
lognonempty(void *)97*9ef1f84bSDavid du Colombier lognonempty(void *)
98*9ef1f84bSDavid du Colombier {
99*9ef1f84bSDavid du Colombier return pw - pr;
100*9ef1f84bSDavid du Colombier }
101*9ef1f84bSDavid du Colombier
102*9ef1f84bSDavid du Colombier static int
logfull(void)103*9ef1f84bSDavid du Colombier logfull(void)
104*9ef1f84bSDavid du Colombier {
105*9ef1f84bSDavid du Colombier return (pw - pr) >= logsize;
106*9ef1f84bSDavid du Colombier }
107*9ef1f84bSDavid du Colombier
108*9ef1f84bSDavid du Colombier static ulong
idx(ulong f)109*9ef1f84bSDavid du Colombier idx(ulong f)
110*9ef1f84bSDavid du Colombier {
111*9ef1f84bSDavid du Colombier return f & logmask;
112*9ef1f84bSDavid du Colombier }
113*9ef1f84bSDavid du Colombier
114*9ef1f84bSDavid du Colombier /* can return NULL, meaning, no record for you */
115*9ef1f84bSDavid du Colombier static struct Probelog *
newpl(void)116*9ef1f84bSDavid du Colombier newpl(void)
117*9ef1f84bSDavid du Colombier {
118*9ef1f84bSDavid du Colombier ulong index;
119*9ef1f84bSDavid du Colombier
120*9ef1f84bSDavid du Colombier if (logfull()){
121*9ef1f84bSDavid du Colombier wakeup(&probesleep);
122*9ef1f84bSDavid du Colombier return nil;
123*9ef1f84bSDavid du Colombier }
124*9ef1f84bSDavid du Colombier
125*9ef1f84bSDavid du Colombier ilock(&loglk);
126*9ef1f84bSDavid du Colombier index = pw++;
127*9ef1f84bSDavid du Colombier iunlock(&loglk);
128*9ef1f84bSDavid du Colombier
129*9ef1f84bSDavid du Colombier return &probelog[idx(index)];
130*9ef1f84bSDavid du Colombier
131*9ef1f84bSDavid du Colombier }
132*9ef1f84bSDavid du Colombier
133*9ef1f84bSDavid du Colombier static void
probeentry(Probe * p)134*9ef1f84bSDavid du Colombier probeentry(Probe *p)
135*9ef1f84bSDavid du Colombier {
136*9ef1f84bSDavid du Colombier struct Probelog *pl;
137*9ef1f84bSDavid du Colombier //print("probeentry %p p %p func %p argp %p\n", &p, p, p->func, p->argp);
138*9ef1f84bSDavid du Colombier pl = newpl();
139*9ef1f84bSDavid du Colombier if (! pl)
140*9ef1f84bSDavid du Colombier return;
141*9ef1f84bSDavid du Colombier cycles(&pl->ticks);
142*9ef1f84bSDavid du Colombier pl->pc = (ulong)p->func;
143*9ef1f84bSDavid du Colombier pl->dat[0] = p->argp[0];
144*9ef1f84bSDavid du Colombier pl->dat[1] = p->argp[1];
145*9ef1f84bSDavid du Colombier pl->dat[2] = p->argp[2];
146*9ef1f84bSDavid du Colombier pl->dat[3] = p->argp[3];
147*9ef1f84bSDavid du Colombier pl->info = ProbeEntry;
148*9ef1f84bSDavid du Colombier }
149*9ef1f84bSDavid du Colombier
150*9ef1f84bSDavid du Colombier static void
probeexit(Probe * p)151*9ef1f84bSDavid du Colombier probeexit(Probe *p)
152*9ef1f84bSDavid du Colombier {
153*9ef1f84bSDavid du Colombier //print("probeexit %p p %p func %p argp %p\n", &p, p, p->func, p->argp);
154*9ef1f84bSDavid du Colombier struct Probelog *pl;
155*9ef1f84bSDavid du Colombier pl = newpl();
156*9ef1f84bSDavid du Colombier if (! pl)
157*9ef1f84bSDavid du Colombier return;
158*9ef1f84bSDavid du Colombier cycles(&pl->ticks);
159*9ef1f84bSDavid du Colombier pl->pc = (ulong)p->func;
160*9ef1f84bSDavid du Colombier pl->dat[0] = p->rval;
161*9ef1f84bSDavid du Colombier pl->info = ProbeExit;
162*9ef1f84bSDavid du Colombier }
163*9ef1f84bSDavid du Colombier
164*9ef1f84bSDavid du Colombier static Chan*
probeattach(char * spec)165*9ef1f84bSDavid du Colombier probeattach(char *spec)
166*9ef1f84bSDavid du Colombier {
167*9ef1f84bSDavid du Colombier return devattach('+', spec);
168*9ef1f84bSDavid du Colombier }
169*9ef1f84bSDavid du Colombier
170*9ef1f84bSDavid du Colombier static Walkqid*
probewalk(Chan * c,Chan * nc,char ** name,int nname)171*9ef1f84bSDavid du Colombier probewalk(Chan *c, Chan *nc, char **name, int nname)
172*9ef1f84bSDavid du Colombier {
173*9ef1f84bSDavid du Colombier return devwalk(c, nc, name, nname, probedir, nelem(probedir), devgen);
174*9ef1f84bSDavid du Colombier }
175*9ef1f84bSDavid du Colombier
176*9ef1f84bSDavid du Colombier static long
probestat(Chan * c,uchar * db,long n)177*9ef1f84bSDavid du Colombier probestat(Chan *c, uchar *db, long n)
178*9ef1f84bSDavid du Colombier {
179*9ef1f84bSDavid du Colombier return devstat(c, db, n, probedir, nelem(probedir), devgen);
180*9ef1f84bSDavid du Colombier }
181*9ef1f84bSDavid du Colombier
182*9ef1f84bSDavid du Colombier static Chan*
probeopen(Chan * c,int omode)183*9ef1f84bSDavid du Colombier probeopen(Chan *c, int omode)
184*9ef1f84bSDavid du Colombier {
185*9ef1f84bSDavid du Colombier /* if there is no probelog, allocate one. Open always fails
186*9ef1f84bSDavid du Colombier * if the basic alloc fails. You can resize it later.
187*9ef1f84bSDavid du Colombier */
188*9ef1f84bSDavid du Colombier if (! probelog)
189*9ef1f84bSDavid du Colombier probelog = malloc(sizeof(*probelog)*logsize);
190*9ef1f84bSDavid du Colombier /* I guess malloc doesn't toss an error */
191*9ef1f84bSDavid du Colombier if (! probelog)
192*9ef1f84bSDavid du Colombier error("probelog malloc failed");
193*9ef1f84bSDavid du Colombier
194*9ef1f84bSDavid du Colombier c = devopen(c, omode, probedir, nelem(probedir), devgen);
195*9ef1f84bSDavid du Colombier return c;
196*9ef1f84bSDavid du Colombier }
197*9ef1f84bSDavid du Colombier
198*9ef1f84bSDavid du Colombier static void
probeclose(Chan *)199*9ef1f84bSDavid du Colombier probeclose(Chan *)
200*9ef1f84bSDavid du Colombier {
201*9ef1f84bSDavid du Colombier }
202*9ef1f84bSDavid du Colombier
203*9ef1f84bSDavid du Colombier static long
proberead(Chan * c,void * a,long n,vlong offset)204*9ef1f84bSDavid du Colombier proberead(Chan *c, void *a, long n, vlong offset)
205*9ef1f84bSDavid du Colombier {
206*9ef1f84bSDavid du Colombier char *buf;
207*9ef1f84bSDavid du Colombier char *cp = a;
208*9ef1f84bSDavid du Colombier struct Probelog *pl;
209*9ef1f84bSDavid du Colombier Probe *p;
210*9ef1f84bSDavid du Colombier int i;
211*9ef1f84bSDavid du Colombier static QLock gate;
212*9ef1f84bSDavid du Colombier if(c->qid.type == QTDIR)
213*9ef1f84bSDavid du Colombier return devdirread(c, a, n, probedir, nelem(probedir), devgen);
214*9ef1f84bSDavid du Colombier switch((ulong)c->qid.path){
215*9ef1f84bSDavid du Colombier default:
216*9ef1f84bSDavid du Colombier error("proberead: bad qid");
217*9ef1f84bSDavid du Colombier case Qctl:
218*9ef1f84bSDavid du Colombier buf = malloc(READSTR);
219*9ef1f84bSDavid du Colombier i = 0;
220*9ef1f84bSDavid du Colombier qlock(&probeslk);
221*9ef1f84bSDavid du Colombier i += snprint(buf + i, READSTR - i, "logsize %lud\n", logsize);
222*9ef1f84bSDavid du Colombier for(p = probes; p != nil; p = p->next)
223*9ef1f84bSDavid du Colombier i += snprint(buf + i, READSTR - i, "probe %p new %s\n",
224*9ef1f84bSDavid du Colombier p->func, p->name);
225*9ef1f84bSDavid du Colombier
226*9ef1f84bSDavid du Colombier for(p = probes; p != nil; p = p->next)
227*9ef1f84bSDavid du Colombier if (p->enabled)
228*9ef1f84bSDavid du Colombier i += snprint(buf + i, READSTR - i, "probe %s on\n",
229*9ef1f84bSDavid du Colombier p->name);
230*9ef1f84bSDavid du Colombier i += snprint(buf + i, READSTR - i, "#probehits %lud, in queue %lud\n",
231*9ef1f84bSDavid du Colombier pw, pw-pr);
232*9ef1f84bSDavid du Colombier snprint(buf + i, READSTR - i, "#probelog %p\n", probelog);
233*9ef1f84bSDavid du Colombier qunlock(&probeslk);
234*9ef1f84bSDavid du Colombier n = readstr(offset, a, n, buf);
235*9ef1f84bSDavid du Colombier free(buf);
236*9ef1f84bSDavid du Colombier break;
237*9ef1f84bSDavid du Colombier case Qdata:
238*9ef1f84bSDavid du Colombier qlock(&gate);
239*9ef1f84bSDavid du Colombier if(waserror()){
240*9ef1f84bSDavid du Colombier qunlock(&gate);
241*9ef1f84bSDavid du Colombier nexterror();
242*9ef1f84bSDavid du Colombier }
243*9ef1f84bSDavid du Colombier while(!lognonempty(nil))
244*9ef1f84bSDavid du Colombier tsleep(&probesleep, lognonempty, nil, 5000);
245*9ef1f84bSDavid du Colombier i = 0;
246*9ef1f84bSDavid du Colombier while(lognonempty((void *)0)){
247*9ef1f84bSDavid du Colombier int j;
248*9ef1f84bSDavid du Colombier pl = probelog + idx(pr);
249*9ef1f84bSDavid du Colombier
250*9ef1f84bSDavid du Colombier if ((i + printsize) >= n)
251*9ef1f84bSDavid du Colombier break;
252*9ef1f84bSDavid du Colombier /* simple format */
253*9ef1f84bSDavid du Colombier cp[0] = eventname[pl->info];
254*9ef1f84bSDavid du Colombier cp ++;
255*9ef1f84bSDavid du Colombier *cp++ = ' ';
256*9ef1f84bSDavid du Colombier hex32(pl->pc, cp);
257*9ef1f84bSDavid du Colombier cp[8] = ' ';
258*9ef1f84bSDavid du Colombier cp += 9;
259*9ef1f84bSDavid du Colombier hex64(pl->ticks, cp);
260*9ef1f84bSDavid du Colombier cp[16] = ' ';
261*9ef1f84bSDavid du Colombier cp += 17;
262*9ef1f84bSDavid du Colombier for(j = 0; j < 4; j++){
263*9ef1f84bSDavid du Colombier hex32(pl->dat[j], cp);
264*9ef1f84bSDavid du Colombier cp[8] = ' ';
265*9ef1f84bSDavid du Colombier cp += 9;
266*9ef1f84bSDavid du Colombier }
267*9ef1f84bSDavid du Colombier /* adjust for extra skip above */
268*9ef1f84bSDavid du Colombier cp--;
269*9ef1f84bSDavid du Colombier *cp++ = '\n';
270*9ef1f84bSDavid du Colombier pr++;
271*9ef1f84bSDavid du Colombier i += printsize;
272*9ef1f84bSDavid du Colombier }
273*9ef1f84bSDavid du Colombier poperror();
274*9ef1f84bSDavid du Colombier qunlock(&gate);
275*9ef1f84bSDavid du Colombier n = i;
276*9ef1f84bSDavid du Colombier break;
277*9ef1f84bSDavid du Colombier }
278*9ef1f84bSDavid du Colombier return n;
279*9ef1f84bSDavid du Colombier }
280*9ef1f84bSDavid du Colombier
281*9ef1f84bSDavid du Colombier static long
probewrite(Chan * c,void * a,long n,vlong)282*9ef1f84bSDavid du Colombier probewrite(Chan *c, void *a, long n, vlong)
283*9ef1f84bSDavid du Colombier {
284*9ef1f84bSDavid du Colombier char *tok[5];
285*9ef1f84bSDavid du Colombier char *ep, *s = nil;
286*9ef1f84bSDavid du Colombier Probe *p, **pp;
287*9ef1f84bSDavid du Colombier int ntok;
288*9ef1f84bSDavid du Colombier
289*9ef1f84bSDavid du Colombier qlock(&probeslk);
290*9ef1f84bSDavid du Colombier if(waserror()){
291*9ef1f84bSDavid du Colombier qunlock(&probeslk);
292*9ef1f84bSDavid du Colombier if(s != nil) free(s);
293*9ef1f84bSDavid du Colombier nexterror();
294*9ef1f84bSDavid du Colombier }
295*9ef1f84bSDavid du Colombier switch((ulong)c->qid.path){
296*9ef1f84bSDavid du Colombier default:
297*9ef1f84bSDavid du Colombier error("proberead: bad qid");
298*9ef1f84bSDavid du Colombier case Qctl:
299*9ef1f84bSDavid du Colombier s = malloc(n + 1);
300*9ef1f84bSDavid du Colombier memmove(s, a, n);
301*9ef1f84bSDavid du Colombier s[n] = 0;
302*9ef1f84bSDavid du Colombier ntok = tokenize(s, tok, nelem(tok));
303*9ef1f84bSDavid du Colombier if(!strcmp(tok[0], "probe")){ /* 'probe' ktextaddr 'on'|'off'|'mk'|'del' [name] */
304*9ef1f84bSDavid du Colombier if(ntok < 3)
305*9ef1f84bSDavid du Colombier error("devprobe: usage: 'probe' [ktextaddr|name] 'on'|'off'|'mk'|'del' [name]");
306*9ef1f84bSDavid du Colombier for(pp = &probes; *pp != nil; pp = &(*pp)->next)
307*9ef1f84bSDavid du Colombier if(!strcmp(tok[1], (*pp)->name))
308*9ef1f84bSDavid du Colombier break;
309*9ef1f84bSDavid du Colombier p = *pp;
310*9ef1f84bSDavid du Colombier if(!strcmp(tok[2], "new")){
311*9ef1f84bSDavid du Colombier ulong addr;
312*9ef1f84bSDavid du Colombier void *func;
313*9ef1f84bSDavid du Colombier addr = strtoul(tok[1], &ep, 0);
314*9ef1f84bSDavid du Colombier func = (void*)addr;
315*9ef1f84bSDavid du Colombier if(*ep)
316*9ef1f84bSDavid du Colombier error("devprobe: address not in recognized format");
317*9ef1f84bSDavid du Colombier // if(addr < ((ulong) start) || addr > ((ulong) end))
318*9ef1f84bSDavid du Colombier // error("devprobe: address out of bounds");
319*9ef1f84bSDavid du Colombier if(p != nil)
320*9ef1f84bSDavid du Colombier error("devprobe: %#p already has probe");
321*9ef1f84bSDavid du Colombier p = mkprobe(func, probeentry, probeexit);
322*9ef1f84bSDavid du Colombier p->next = probes;
323*9ef1f84bSDavid du Colombier if(ntok < 4)
324*9ef1f84bSDavid du Colombier snprint(p->name, sizeof p->name, "%p", func);
325*9ef1f84bSDavid du Colombier else
326*9ef1f84bSDavid du Colombier strncpy(p->name, tok[3], sizeof p->name);
327*9ef1f84bSDavid du Colombier probes = p;
328*9ef1f84bSDavid du Colombier } else if(!strcmp(tok[2], "on")){
329*9ef1f84bSDavid du Colombier if(p == nil)
330*9ef1f84bSDavid du Colombier error("devprobe: probe not found");
331*9ef1f84bSDavid du Colombier if(!p->enabled)
332*9ef1f84bSDavid du Colombier probeinstall(p);
333*9ef1f84bSDavid du Colombier print("probeinstall in devprobe\n");
334*9ef1f84bSDavid du Colombier probesactive++;
335*9ef1f84bSDavid du Colombier } else if(!strcmp(tok[2], "off")){
336*9ef1f84bSDavid du Colombier if(p == nil)
337*9ef1f84bSDavid du Colombier error("devprobe: probe not found");
338*9ef1f84bSDavid du Colombier if(p->enabled)
339*9ef1f84bSDavid du Colombier probeuninstall(p);
340*9ef1f84bSDavid du Colombier probesactive--;
341*9ef1f84bSDavid du Colombier } else if(!strcmp(tok[2], "del")){
342*9ef1f84bSDavid du Colombier if(p == nil)
343*9ef1f84bSDavid du Colombier error("devprobe: probe not found");
344*9ef1f84bSDavid du Colombier if(p->enabled)
345*9ef1f84bSDavid du Colombier probeuninstall(p);
346*9ef1f84bSDavid du Colombier probesactive--;
347*9ef1f84bSDavid du Colombier *pp = p->next;
348*9ef1f84bSDavid du Colombier freeprobe(p);
349*9ef1f84bSDavid du Colombier } else if(!strcmp(tok[2], "mv")){
350*9ef1f84bSDavid du Colombier if(p == nil)
351*9ef1f84bSDavid du Colombier error("devprobe: probe not found");
352*9ef1f84bSDavid du Colombier if(ntok < 4)
353*9ef1f84bSDavid du Colombier error("devprobe: rename without new name?");
354*9ef1f84bSDavid du Colombier strncpy(p->name, tok[3], sizeof p->name);
355*9ef1f84bSDavid du Colombier }
356*9ef1f84bSDavid du Colombier } else if(!strcmp(tok[0], "size")){
357*9ef1f84bSDavid du Colombier int l, size;
358*9ef1f84bSDavid du Colombier struct Probelog *newprobelog;
359*9ef1f84bSDavid du Colombier l = strtoul(tok[1], &ep, 0);
360*9ef1f84bSDavid du Colombier if(*ep)
361*9ef1f84bSDavid du Colombier error("devprobe: size not in recognized format");
362*9ef1f84bSDavid du Colombier size = 1 << l;
363*9ef1f84bSDavid du Colombier /* sort of foolish. Alloc new probe first, then free old. */
364*9ef1f84bSDavid du Colombier /* and too bad if there are unread probes */
365*9ef1f84bSDavid du Colombier newprobelog = malloc(sizeof(*newprobelog)*size);
366*9ef1f84bSDavid du Colombier /* does malloc throw waserror? I don't know */
367*9ef1f84bSDavid du Colombier free(probelog);
368*9ef1f84bSDavid du Colombier probelog = newprobelog;
369*9ef1f84bSDavid du Colombier logsize = size;
370*9ef1f84bSDavid du Colombier pr = pw = 0;
371*9ef1f84bSDavid du Colombier } else {
372*9ef1f84bSDavid du Colombier error("devprobe: usage: 'probe' [ktextaddr|name] 'on'|'off'|'mk'|'del' [name] or: 'size' buffersize (power of 2)");
373*9ef1f84bSDavid du Colombier }
374*9ef1f84bSDavid du Colombier free(s);
375*9ef1f84bSDavid du Colombier break;
376*9ef1f84bSDavid du Colombier }
377*9ef1f84bSDavid du Colombier poperror();
378*9ef1f84bSDavid du Colombier qunlock(&probeslk);
379*9ef1f84bSDavid du Colombier return n;
380*9ef1f84bSDavid du Colombier }
381*9ef1f84bSDavid du Colombier
382*9ef1f84bSDavid du Colombier Dev probedevtab = {
383*9ef1f84bSDavid du Colombier '+',
384*9ef1f84bSDavid du Colombier "probe",
385*9ef1f84bSDavid du Colombier devreset,
386*9ef1f84bSDavid du Colombier devinit,
387*9ef1f84bSDavid du Colombier devshutdown,
388*9ef1f84bSDavid du Colombier probeattach,
389*9ef1f84bSDavid du Colombier probewalk,
390*9ef1f84bSDavid du Colombier probestat,
391*9ef1f84bSDavid du Colombier probeopen,
392*9ef1f84bSDavid du Colombier devcreate,
393*9ef1f84bSDavid du Colombier probeclose,
394*9ef1f84bSDavid du Colombier proberead,
395*9ef1f84bSDavid du Colombier devbread,
396*9ef1f84bSDavid du Colombier probewrite,
397*9ef1f84bSDavid du Colombier devbwrite,
398*9ef1f84bSDavid du Colombier devremove,
399*9ef1f84bSDavid du Colombier devwstat,
400*9ef1f84bSDavid du Colombier };
401