changelog shortlog tags branches files raw gz bz2 help

Mercurial > hg > plan9front / changeset: kernel: fix tprof on multiprocessor

changeset 6937: 62ba89f5ffb8
parent 6936: 9419715d8845
child 6938: 2109eab7793b
author: cinap_lenrek@felloff.net
date: Wed, 05 Dec 2018 01:43:19 +0100
files: sys/src/9/port/devproc.c sys/src/9/port/portclock.c sys/src/9/port/portmkfile
description: kernel: fix tprof on multiprocessor

segclock() has to be called from hzclock(), otherwise
only processes running on cpu0 would catche the interrupt
and the time delta would be wrong.

lock the segment when allocating Seg->profile as
profile ctl might be issued from multiple processes.
Proc->debug qlock is not sufficient.

Seg->profile can never be freed or reallocated once
set as the timer interrupt accesses it without any
locking.
     1.1--- a/sys/src/9/port/devproc.c
     1.2+++ b/sys/src/9/port/devproc.c
     1.3@@ -1,6 +1,5 @@
     1.4 #include	"u.h"
     1.5 #include	<trace.h>
     1.6-#include	"tos.h"
     1.7 #include	"../port/lib.h"
     1.8 #include	"mem.h"
     1.9 #include	"dat.h"
    1.10@@ -167,22 +166,6 @@ static int topens;
    1.11 static int tproduced, tconsumed;
    1.12 void (*proctrace)(Proc*, int, vlong);
    1.13 
    1.14-static void
    1.15-profclock(Ureg *ur, Timer *)
    1.16-{
    1.17-	Tos *tos;
    1.18-
    1.19-	if(up == nil || up->state != Running)
    1.20-		return;
    1.21-
    1.22-	/* user profiling clock */
    1.23-	if(userureg(ur)){
    1.24-		tos = (Tos*)(USTKTOP-sizeof(Tos));
    1.25-		tos->clock += TK2MS(1);
    1.26-		segclock(ur->pc);
    1.27-	}
    1.28-}
    1.29-
    1.30 static int lenwatchpt(Proc *);
    1.31 
    1.32 static int
    1.33@@ -304,7 +287,6 @@ procinit(void)
    1.34 {
    1.35 	if(conf.nproc >= (1<<(16-QSHIFT))-1)
    1.36 		print("warning: too many procs for devproc\n");
    1.37-	addclock0link((void (*)(void))profclock, 113);	/* Relative prime to HZ */
    1.38 }
    1.39 
    1.40 static Chan*
    1.41@@ -1454,7 +1436,8 @@ void
    1.42 procctlreq(Proc *p, char *va, int n)
    1.43 {
    1.44 	Segment *s;
    1.45-	int npc, pri;
    1.46+	uintptr npc;
    1.47+	int pri;
    1.48 	Cmdbuf *cb;
    1.49 	Cmdtab *ct;
    1.50 	vlong time;
    1.51@@ -1520,14 +1503,20 @@ procctlreq(Proc *p, char *va, int n)
    1.52 		break;
    1.53 	case CMprofile:
    1.54 		s = p->seg[TSEG];
    1.55-		if(s == nil || (s->type&SG_TYPE) != SG_TEXT)
    1.56-			error(Ebadctl);
    1.57-		if(s->profile != nil)
    1.58-			free(s->profile);
    1.59+		if(s == nil || (s->type&SG_TYPE) != SG_TEXT)	/* won't expand */
    1.60+			error(Egreg);
    1.61+		eqlock(s);
    1.62 		npc = (s->top-s->base)>>LRESPROF;
    1.63-		s->profile = malloc(npc*sizeof(*s->profile));
    1.64-		if(s->profile == nil)
    1.65-			error(Enomem);
    1.66+		if(s->profile == nil){
    1.67+			s->profile = malloc(npc*sizeof(*s->profile));
    1.68+			if(s->profile == nil){
    1.69+				qunlock(s);
    1.70+				error(Enomem);
    1.71+			}
    1.72+		} else {
    1.73+			memset(s->profile, 0, npc*sizeof(*s->profile));
    1.74+		}
    1.75+		qunlock(s);
    1.76 		break;
    1.77 	case CMstart:
    1.78 		if(p->state != Stopped)
     2.1--- a/sys/src/9/port/portclock.c
     2.2+++ b/sys/src/9/port/portclock.c
     2.3@@ -5,6 +5,7 @@
     2.4 #include "fns.h"
     2.5 #include "io.h"
     2.6 #include "ureg.h"
     2.7+#include "tos.h"
     2.8 
     2.9 struct Timers
    2.10 {
    2.11@@ -167,8 +168,16 @@ hzclock(Ureg *ur)
    2.12 	if(m->machno == 0)
    2.13 		checkalarms();
    2.14 
    2.15-	if(up && up->state == Running)
    2.16+	if(up && up->state == Running){
    2.17+		if(userureg(ur)){
    2.18+			/* user profiling clock */
    2.19+			Tos *tos = (Tos*)(USTKTOP-sizeof(Tos));
    2.20+			tos->clock += TK2MS(1);
    2.21+			segclock(ur->pc);
    2.22+		}
    2.23+
    2.24 		hzsched();	/* in proc.c */
    2.25+	}
    2.26 }
    2.27 
    2.28 void
     3.1--- a/sys/src/9/port/portmkfile
     3.2+++ b/sys/src/9/port/portmkfile
     3.3@@ -87,7 +87,7 @@ screen.$O:	screen.h /sys/include/draw.h 
     3.4 thwack.$O:	../port/thwack.h
     3.5 unthwack.$O:	../port/thwack.h
     3.6 devsdp.$O:	../port/thwack.h
     3.7-devproc.$O sysproc.$O:	/sys/include/tos.h
     3.8+portclock.$O sysproc.$O:	/sys/include/tos.h
     3.9 devproc.$O edf.$O proc.$O:	/sys/include/trace.h
    3.10 auth.$O devcons.$O:	/sys/include/authsrv.h
    3.11 devcap.$O:	/sys/include/libsec.h