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.
This commit is contained in:
cinap_lenrek 2018-12-05 01:43:19 +01:00
parent 79bfff6437
commit d15aca0532
3 changed files with 26 additions and 28 deletions

View file

@ -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 topens;
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 @@ procinit(void)
{
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 @@ void
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 @@ procctlreq(Proc *p, char *va, int n)
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)

View file

@ -5,6 +5,7 @@
#include "fns.h"
#include "io.h"
#include "ureg.h"
#include "tos.h"
struct Timers
{
@ -167,8 +168,16 @@ hzclock(Ureg *ur)
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

View file

@ -87,7 +87,7 @@ screen.$O: screen.h /sys/include/draw.h /sys/include/memdraw.h /sys/include/curs
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