ref: 6ceadb8908e5e58d17df2efb508055b15ed2b66e
parent: 1a4cb7e2d48c66566ab9fe5fa5d9246073630768
	author: cinap_lenrek <cinap_lenrek@felloff.net>
	date: Tue Dec  4 20:43:19 EST 2018
	
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.
--- a/sys/src/9/port/devproc.c
+++ b/sys/src/9/port/devproc.c
@@ -1,6 +1,5 @@
#include "u.h"
#include <trace.h>
-#include "tos.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
@@ -167,22 +166,6 @@
static int tproduced, tconsumed;
void (*proctrace)(Proc*, int, vlong);
-static void
-profclock(Ureg *ur, Timer *)
-{- Tos *tos;
-
- if(up == nil || up->state != Running)
- return;
-
- /* user profiling clock */
-	if(userureg(ur)){- tos = (Tos*)(USTKTOP-sizeof(Tos));
- tos->clock += TK2MS(1);
- segclock(ur->pc);
- }
-}
-
static int lenwatchpt(Proc *);
static int
@@ -304,7 +287,6 @@
 {if(conf.nproc >= (1<<(16-QSHIFT))-1)
 		print("warning: too many procs for devproc\n");- addclock0link((void (*)(void))profclock, 113); /* Relative prime to HZ */
}
static Chan*
@@ -1454,7 +1436,8 @@
procctlreq(Proc *p, char *va, int n)
 {Segment *s;
- int npc, pri;
+ uintptr npc;
+ int pri;
Cmdbuf *cb;
Cmdtab *ct;
vlong time;
@@ -1520,14 +1503,20 @@
break;
case CMprofile:
s = p->seg[TSEG];
- if(s == nil || (s->type&SG_TYPE) != SG_TEXT)
- error(Ebadctl);
- if(s->profile != nil)
- free(s->profile);
+ if(s == nil || (s->type&SG_TYPE) != SG_TEXT) /* won't expand */
+ error(Egreg);
+ eqlock(s);
npc = (s->top-s->base)>>LRESPROF;
- s->profile = malloc(npc*sizeof(*s->profile));
- if(s->profile == nil)
- error(Enomem);
+		if(s->profile == nil){+ s->profile = malloc(npc*sizeof(*s->profile));
+			if(s->profile == nil){+ qunlock(s);
+ error(Enomem);
+ }
+		} else {+ memset(s->profile, 0, npc*sizeof(*s->profile));
+ }
+ qunlock(s);
break;
case CMstart:
if(p->state != Stopped)
--- a/sys/src/9/port/portclock.c
+++ b/sys/src/9/port/portclock.c
@@ -5,6 +5,7 @@
#include "fns.h"
#include "io.h"
#include "ureg.h"
+#include "tos.h"
struct Timers
 {@@ -167,8 +168,16 @@
if(m->machno == 0)
checkalarms();
- if(up && up->state == Running)
+	if(up && up->state == Running){+		if(userureg(ur)){+ /* user profiling clock */
+ Tos *tos = (Tos*)(USTKTOP-sizeof(Tos));
+ tos->clock += TK2MS(1);
+ segclock(ur->pc);
+ }
+
hzsched(); /* in proc.c */
+ }
}
void
--- a/sys/src/9/port/portmkfile
+++ b/sys/src/9/port/portmkfile
@@ -87,7 +87,7 @@
thwack.$O: ../port/thwack.h
unthwack.$O: ../port/thwack.h
devsdp.$O: ../port/thwack.h
-devproc.$O sysproc.$O: /sys/include/tos.h
+portclock.$O sysproc.$O: /sys/include/tos.h
devproc.$O edf.$O proc.$O: /sys/include/trace.h
auth.$O devcons.$O: /sys/include/authsrv.h
devcap.$O: /sys/include/libsec.h
--
⑨