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:
parent
79bfff6437
commit
d15aca0532
3 changed files with 26 additions and 28 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue