shithub: riscv

Download patch

ref: 4f0bfe0fb8dc608a94fe429c5ddb12e58997e1ce
parent: ac3147a9c58f339f9b978ab087464912c16bc8f8
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Mar 30 05:17:46 EDT 2019

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.

--- a/sys/include/dtracy.h
+++ b/sys/include/dtracy.h
@@ -241,7 +241,7 @@
 DTProbe *dtpnew(char *, DTProvider *, void *aux);
 int dtpmatch(char *, DTProbe ***);
 int dtplist(DTProbe ***);
-void dtptrigger(DTProbe *, int, DTTrigInfo *);
+void dtptrigger(DTProbe *, DTTrigInfo *);
 
 /* expression functions */
 int dteverify(DTExpr *);
@@ -285,7 +285,7 @@
 void *dtrealloc(void *, ulong);
 void dtfree(void *);
 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 dtcoherence(void); /* memory barrier */
 uvlong dtgetvar(int); /* return the value of a variable */
--- a/sys/src/9/port/devdtracy.c
+++ b/sys/src/9/port/devdtracy.c
@@ -512,10 +512,18 @@
 	return v;
 }
 
-void
+int
 dtmachlock(int i)
 {
+	while(i < 0) {
+		i = dtmachlock(m->machno);
+		if(i == m->machno)
+			return i;
+		dtmachunlock(i);
+		i = -1;
+	}
 	ilock(&machlocks[i]);
+	return i;
 }
 
 void
--- a/sys/src/9/port/dtracysys.c
+++ b/sys/src/9/port/dtracysys.c
@@ -20,10 +20,10 @@
 	uintptr rc;\
 	DTTrigInfo info;\
 	memset(&info, 0, sizeof(info));\
-	dtptrigger(dtpsysentry[y], m->machno, &info);\
+	dtptrigger(dtpsysentry[y], &info);\
 	rc = z(va);\
 	info.arg[9] = (uvlong) rc;\
-	dtptrigger(dtpsysreturn[y], m->machno, &info);\
+	dtptrigger(dtpsysreturn[y], &info);\
 	return rc;\
 }
 #define WRAP1(x,y,z,type0)\
@@ -33,10 +33,10 @@
 	DTTrigInfo info;\
 	memset(&info, 0, sizeof(info));\
 	info.arg[0] = (uvlong) va_arg(vb, type0);\
-	dtptrigger(dtpsysentry[y], m->machno, &info);\
+	dtptrigger(dtpsysentry[y], &info);\
 	rc = z(va);\
 	info.arg[9] = (uvlong) rc;\
-	dtptrigger(dtpsysreturn[y], m->machno, &info);\
+	dtptrigger(dtpsysreturn[y], &info);\
 	return rc;\
 }
 #define WRAP2(x,y,z,type0,type1)\
@@ -47,10 +47,10 @@
 	memset(&info, 0, sizeof(info));\
 	info.arg[0] = (uvlong) va_arg(vb, type0);\
 	info.arg[1] = (uvlong) va_arg(vb, type1);\
-	dtptrigger(dtpsysentry[y], m->machno, &info);\
+	dtptrigger(dtpsysentry[y], &info);\
 	rc = z(va);\
 	info.arg[9] = (uvlong) rc;\
-	dtptrigger(dtpsysreturn[y], m->machno, &info);\
+	dtptrigger(dtpsysreturn[y], &info);\
 	return rc;\
 }
 #define WRAP3(x,y,z,type0,type1,type2)\
@@ -62,10 +62,10 @@
 	info.arg[0] = (uvlong) va_arg(vb, type0);\
 	info.arg[1] = (uvlong) va_arg(vb, type1);\
 	info.arg[2] = (uvlong) va_arg(vb, type2);\
-	dtptrigger(dtpsysentry[y], m->machno, &info);\
+	dtptrigger(dtpsysentry[y], &info);\
 	rc = z(va);\
 	info.arg[9] = (uvlong) rc;\
-	dtptrigger(dtpsysreturn[y], m->machno, &info);\
+	dtptrigger(dtpsysreturn[y], &info);\
 	return rc;\
 }
 #define WRAP4(x,y,z,type0,type1,type2,type3)\
@@ -78,10 +78,10 @@
 	info.arg[1] = (uvlong) va_arg(vb, type1);\
 	info.arg[2] = (uvlong) va_arg(vb, type2);\
 	info.arg[3] = (uvlong) va_arg(vb, type3);\
-	dtptrigger(dtpsysentry[y], m->machno, &info);\
+	dtptrigger(dtpsysentry[y], &info);\
 	rc = z(va);\
 	info.arg[9] = (uvlong) rc;\
-	dtptrigger(dtpsysreturn[y], m->machno, &info);\
+	dtptrigger(dtpsysreturn[y], &info);\
 	return rc;\
 }
 /*TODO*/
@@ -96,10 +96,10 @@
 	info.arg[2] = (uvlong) va_arg(vb, type2);\
 	info.arg[3] = (uvlong) va_arg(vb, type3);\
 	info.arg[4] = (uvlong) va_arg(vb, type4);\
-	dtptrigger(dtpsysentry[y], m->machno, &info);\
+	dtptrigger(dtpsysentry[y], &info);\
 	rc = z(va);\
 	info.arg[9] = (uvlong) rc;\
-	dtptrigger(dtpsysreturn[y], m->machno, &info);\
+	dtptrigger(dtpsysreturn[y], &info);\
 	return rc;\
 }
 
--- a/sys/src/9/port/dtracytimer.c
+++ b/sys/src/9/port/dtracytimer.c
@@ -17,7 +17,7 @@
 	memset(&info, 0, sizeof(info));
 	for(;;){
 		tsleep(&up->sleep, return0, nil, 1000);
-		dtptrigger(timerprobe, m->machno, &info);
+		dtptrigger(timerprobe, &info);
 	}
 }
 
--- a/sys/src/9/port/portmkfile
+++ b/sys/src/9/port/portmkfile
@@ -80,6 +80,7 @@
 netif.$O:	../port/netif.h
 devuart.$O:	../port/netif.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
 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
--- a/sys/src/libdtracy/prog.c
+++ b/sys/src/libdtracy/prog.c
@@ -336,13 +336,12 @@
 }
 
 void
-dtptrigger(DTProbe *p, int machno, DTTrigInfo *info)
+dtptrigger(DTProbe *p, DTTrigInfo *info)
 {
 	DTEnab *e;
 	
 	info->ts = dttime();
-	dtmachlock(machno);
-	info->machno = machno;
+	info->machno = dtmachlock(-1);
 	for(e = p->enablist.probnext; e != &p->enablist; e = e->probnext)
 		if(e->gr->chan->state == DTCGO){
 			info->ch = e->gr->chan;
@@ -350,5 +349,5 @@
 			if(dtgexec(e->gr, info) < 0)
 				e->gr->chan->state = DTCFAULT;
 		}
-	dtmachunlock(machno);
+	dtmachunlock(info->machno);
 }