dtracy: avoid dmachlock() race

between being commited to a machno and having acquired the lock, the
scheduler could come in an schedule us on a different processor. the
solution is to have dtmachlock() take a special -1 argument to mean
"current mach" and return the actual mach number after the lock has
been acquired and interrupts being disabled.
This commit is contained in:
cinap_lenrek 2019-03-30 09:17:46 +01:00
parent ac3147a9c5
commit 4f0bfe0fb8
6 changed files with 28 additions and 20 deletions

View file

@ -241,7 +241,7 @@ void dtsync(void);
DTProbe *dtpnew(char *, DTProvider *, void *aux); DTProbe *dtpnew(char *, DTProvider *, void *aux);
int dtpmatch(char *, DTProbe ***); int dtpmatch(char *, DTProbe ***);
int dtplist(DTProbe ***); int dtplist(DTProbe ***);
void dtptrigger(DTProbe *, int, DTTrigInfo *); void dtptrigger(DTProbe *, DTTrigInfo *);
/* expression functions */ /* expression functions */
int dteverify(DTExpr *); int dteverify(DTExpr *);
@ -285,7 +285,7 @@ uvlong dttime(void); /* return current timestamp */
void *dtrealloc(void *, ulong); void *dtrealloc(void *, ulong);
void dtfree(void *); void dtfree(void *);
void *dtmalloc(ulong); void *dtmalloc(ulong);
void dtmachlock(int); /* lock the per-cpu lock */ int dtmachlock(int); /* lock the per-cpu lock */
void dtmachunlock(int); /* unlock the per-cpu lock */ void dtmachunlock(int); /* unlock the per-cpu lock */
void dtcoherence(void); /* memory barrier */ void dtcoherence(void); /* memory barrier */
uvlong dtgetvar(int); /* return the value of a variable */ uvlong dtgetvar(int); /* return the value of a variable */

View file

@ -512,10 +512,18 @@ dtrealloc(void *v, ulong n)
return v; return v;
} }
void int
dtmachlock(int i) dtmachlock(int i)
{ {
while(i < 0) {
i = dtmachlock(m->machno);
if(i == m->machno)
return i;
dtmachunlock(i);
i = -1;
}
ilock(&machlocks[i]); ilock(&machlocks[i]);
return i;
} }
void void

View file

@ -20,10 +20,10 @@ extern Syscall *systab[];
uintptr rc;\ uintptr rc;\
DTTrigInfo info;\ DTTrigInfo info;\
memset(&info, 0, sizeof(info));\ memset(&info, 0, sizeof(info));\
dtptrigger(dtpsysentry[y], m->machno, &info);\ dtptrigger(dtpsysentry[y], &info);\
rc = z(va);\ rc = z(va);\
info.arg[9] = (uvlong) rc;\ info.arg[9] = (uvlong) rc;\
dtptrigger(dtpsysreturn[y], m->machno, &info);\ dtptrigger(dtpsysreturn[y], &info);\
return rc;\ return rc;\
} }
#define WRAP1(x,y,z,type0)\ #define WRAP1(x,y,z,type0)\
@ -33,10 +33,10 @@ extern Syscall *systab[];
DTTrigInfo info;\ DTTrigInfo info;\
memset(&info, 0, sizeof(info));\ memset(&info, 0, sizeof(info));\
info.arg[0] = (uvlong) va_arg(vb, type0);\ info.arg[0] = (uvlong) va_arg(vb, type0);\
dtptrigger(dtpsysentry[y], m->machno, &info);\ dtptrigger(dtpsysentry[y], &info);\
rc = z(va);\ rc = z(va);\
info.arg[9] = (uvlong) rc;\ info.arg[9] = (uvlong) rc;\
dtptrigger(dtpsysreturn[y], m->machno, &info);\ dtptrigger(dtpsysreturn[y], &info);\
return rc;\ return rc;\
} }
#define WRAP2(x,y,z,type0,type1)\ #define WRAP2(x,y,z,type0,type1)\
@ -47,10 +47,10 @@ extern Syscall *systab[];
memset(&info, 0, sizeof(info));\ memset(&info, 0, sizeof(info));\
info.arg[0] = (uvlong) va_arg(vb, type0);\ info.arg[0] = (uvlong) va_arg(vb, type0);\
info.arg[1] = (uvlong) va_arg(vb, type1);\ info.arg[1] = (uvlong) va_arg(vb, type1);\
dtptrigger(dtpsysentry[y], m->machno, &info);\ dtptrigger(dtpsysentry[y], &info);\
rc = z(va);\ rc = z(va);\
info.arg[9] = (uvlong) rc;\ info.arg[9] = (uvlong) rc;\
dtptrigger(dtpsysreturn[y], m->machno, &info);\ dtptrigger(dtpsysreturn[y], &info);\
return rc;\ return rc;\
} }
#define WRAP3(x,y,z,type0,type1,type2)\ #define WRAP3(x,y,z,type0,type1,type2)\
@ -62,10 +62,10 @@ extern Syscall *systab[];
info.arg[0] = (uvlong) va_arg(vb, type0);\ info.arg[0] = (uvlong) va_arg(vb, type0);\
info.arg[1] = (uvlong) va_arg(vb, type1);\ info.arg[1] = (uvlong) va_arg(vb, type1);\
info.arg[2] = (uvlong) va_arg(vb, type2);\ info.arg[2] = (uvlong) va_arg(vb, type2);\
dtptrigger(dtpsysentry[y], m->machno, &info);\ dtptrigger(dtpsysentry[y], &info);\
rc = z(va);\ rc = z(va);\
info.arg[9] = (uvlong) rc;\ info.arg[9] = (uvlong) rc;\
dtptrigger(dtpsysreturn[y], m->machno, &info);\ dtptrigger(dtpsysreturn[y], &info);\
return rc;\ return rc;\
} }
#define WRAP4(x,y,z,type0,type1,type2,type3)\ #define WRAP4(x,y,z,type0,type1,type2,type3)\
@ -78,10 +78,10 @@ extern Syscall *systab[];
info.arg[1] = (uvlong) va_arg(vb, type1);\ info.arg[1] = (uvlong) va_arg(vb, type1);\
info.arg[2] = (uvlong) va_arg(vb, type2);\ info.arg[2] = (uvlong) va_arg(vb, type2);\
info.arg[3] = (uvlong) va_arg(vb, type3);\ info.arg[3] = (uvlong) va_arg(vb, type3);\
dtptrigger(dtpsysentry[y], m->machno, &info);\ dtptrigger(dtpsysentry[y], &info);\
rc = z(va);\ rc = z(va);\
info.arg[9] = (uvlong) rc;\ info.arg[9] = (uvlong) rc;\
dtptrigger(dtpsysreturn[y], m->machno, &info);\ dtptrigger(dtpsysreturn[y], &info);\
return rc;\ return rc;\
} }
/*TODO*/ /*TODO*/
@ -96,10 +96,10 @@ extern Syscall *systab[];
info.arg[2] = (uvlong) va_arg(vb, type2);\ info.arg[2] = (uvlong) va_arg(vb, type2);\
info.arg[3] = (uvlong) va_arg(vb, type3);\ info.arg[3] = (uvlong) va_arg(vb, type3);\
info.arg[4] = (uvlong) va_arg(vb, type4);\ info.arg[4] = (uvlong) va_arg(vb, type4);\
dtptrigger(dtpsysentry[y], m->machno, &info);\ dtptrigger(dtpsysentry[y], &info);\
rc = z(va);\ rc = z(va);\
info.arg[9] = (uvlong) rc;\ info.arg[9] = (uvlong) rc;\
dtptrigger(dtpsysreturn[y], m->machno, &info);\ dtptrigger(dtpsysreturn[y], &info);\
return rc;\ return rc;\
} }

View file

@ -17,7 +17,7 @@ dtracytimer(void *)
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
for(;;){ for(;;){
tsleep(&up->sleep, return0, nil, 1000); tsleep(&up->sleep, return0, nil, 1000);
dtptrigger(timerprobe, m->machno, &info); dtptrigger(timerprobe, &info);
} }
} }

View file

@ -80,6 +80,7 @@ devpipe.$O: ../port/netif.h
netif.$O: ../port/netif.h netif.$O: ../port/netif.h
devuart.$O: ../port/netif.h devuart.$O: ../port/netif.h
devbridge.$O: ../port/netif.h ../ip/ip.h ../ip/ipv6.h devbridge.$O: ../port/netif.h ../ip/ip.h ../ip/ipv6.h
devdtracy.$O dtracysys.$O dtracytimer.$O: /sys/include/dtracy.h
devdraw.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/memlayer.h /sys/include/cursor.h devdraw.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/memlayer.h /sys/include/cursor.h
devmouse.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/cursor.h devmouse.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/cursor.h
swcursor.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/cursor.h swcursor.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/cursor.h

View file

@ -336,13 +336,12 @@ dtgexec(DTActGr *g, DTTrigInfo *info)
} }
void void
dtptrigger(DTProbe *p, int machno, DTTrigInfo *info) dtptrigger(DTProbe *p, DTTrigInfo *info)
{ {
DTEnab *e; DTEnab *e;
info->ts = dttime(); info->ts = dttime();
dtmachlock(machno); info->machno = dtmachlock(-1);
info->machno = machno;
for(e = p->enablist.probnext; e != &p->enablist; e = e->probnext) for(e = p->enablist.probnext; e != &p->enablist; e = e->probnext)
if(e->gr->chan->state == DTCGO){ if(e->gr->chan->state == DTCGO){
info->ch = e->gr->chan; info->ch = e->gr->chan;
@ -350,5 +349,5 @@ dtptrigger(DTProbe *p, int machno, DTTrigInfo *info)
if(dtgexec(e->gr, info) < 0) if(dtgexec(e->gr, info) < 0)
e->gr->chan->state = DTCFAULT; e->gr->chan->state = DTCFAULT;
} }
dtmachunlock(machno); dtmachunlock(info->machno);
} }