A little infrastructure, preceding some upcoming changes
to the profiling and statistics code. Submitted by: DavidXu@ Reviewed by: peter@
This commit is contained in:
parent
8480e03dd7
commit
a282253a29
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=110530
@ -313,6 +313,10 @@ startprofclock(p)
|
|||||||
* cover psdiv, etc. as well.
|
* cover psdiv, etc. as well.
|
||||||
*/
|
*/
|
||||||
mtx_lock_spin(&sched_lock);
|
mtx_lock_spin(&sched_lock);
|
||||||
|
if (p->p_sflag & PS_STOPPROF) {
|
||||||
|
mtx_unlock_spin(&sched_lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if ((p->p_sflag & PS_PROFIL) == 0) {
|
if ((p->p_sflag & PS_PROFIL) == 0) {
|
||||||
p->p_sflag |= PS_PROFIL;
|
p->p_sflag |= PS_PROFIL;
|
||||||
if (++profprocs == 1)
|
if (++profprocs == 1)
|
||||||
@ -329,9 +333,18 @@ stopprofclock(p)
|
|||||||
register struct proc *p;
|
register struct proc *p;
|
||||||
{
|
{
|
||||||
|
|
||||||
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||||
|
retry:
|
||||||
mtx_lock_spin(&sched_lock);
|
mtx_lock_spin(&sched_lock);
|
||||||
if (p->p_sflag & PS_PROFIL) {
|
if (p->p_sflag & PS_PROFIL) {
|
||||||
p->p_sflag &= ~PS_PROFIL;
|
if (p->p_profthreads) {
|
||||||
|
p->p_sflag |= PS_STOPPROF;
|
||||||
|
mtx_unlock_spin(&sched_lock);
|
||||||
|
msleep(&p->p_profthreads, &p->p_mtx, PPAUSE,
|
||||||
|
"stopprof", NULL);
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
p->p_sflag &= ~(PS_PROFIL|PS_STOPPROF);
|
||||||
if (--profprocs == 0)
|
if (--profprocs == 0)
|
||||||
cpu_stopprofclock();
|
cpu_stopprofclock();
|
||||||
}
|
}
|
||||||
@ -400,7 +413,7 @@ statclock(frame)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sched_clock(ke->ke_thread);
|
sched_clock(td);
|
||||||
|
|
||||||
/* Update resource usage integrals and maximums. */
|
/* Update resource usage integrals and maximums. */
|
||||||
if ((pstats = p->p_stats) != NULL &&
|
if ((pstats = p->p_stats) != NULL &&
|
||||||
@ -430,9 +443,12 @@ profclock(frame)
|
|||||||
/*
|
/*
|
||||||
* Came from user mode; CPU was in user state.
|
* Came from user mode; CPU was in user state.
|
||||||
* If this process is being profiled, record the tick.
|
* If this process is being profiled, record the tick.
|
||||||
|
* if there is no related user location yet, don't
|
||||||
|
* bother trying to count it.
|
||||||
*/
|
*/
|
||||||
td = curthread;
|
td = curthread;
|
||||||
if (td->td_proc->p_sflag & PS_PROFIL)
|
if ((td->td_proc->p_sflag & PS_PROFIL) &&
|
||||||
|
!(td->td_flags & TDF_UPCALLING))
|
||||||
addupc_intr(td->td_kse, CLKF_PC(frame), 1);
|
addupc_intr(td->td_kse, CLKF_PC(frame), 1);
|
||||||
}
|
}
|
||||||
#ifdef GPROF
|
#ifdef GPROF
|
||||||
|
@ -238,7 +238,6 @@ exit1(td, rv)
|
|||||||
TAILQ_FOREACH(ep, &exit_list, next)
|
TAILQ_FOREACH(ep, &exit_list, next)
|
||||||
(*ep->function)(p);
|
(*ep->function)(p);
|
||||||
|
|
||||||
stopprofclock(p);
|
|
||||||
|
|
||||||
MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
|
MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage),
|
||||||
M_ZOMBIE, 0);
|
M_ZOMBIE, 0);
|
||||||
@ -247,6 +246,7 @@ exit1(td, rv)
|
|||||||
* P_PPWAIT is set; we will wakeup the parent below.
|
* P_PPWAIT is set; we will wakeup the parent below.
|
||||||
*/
|
*/
|
||||||
PROC_LOCK(p);
|
PROC_LOCK(p);
|
||||||
|
stopprofclock(p);
|
||||||
p->p_flag &= ~(P_TRACED | P_PPWAIT);
|
p->p_flag &= ~(P_TRACED | P_PPWAIT);
|
||||||
SIGEMPTYSET(p->p_siglist);
|
SIGEMPTYSET(p->p_siglist);
|
||||||
PROC_UNLOCK(p);
|
PROC_UNLOCK(p);
|
||||||
|
@ -358,7 +358,9 @@ sysctl_kern_prof(SYSCTL_HANDLER_ARGS)
|
|||||||
return (0);
|
return (0);
|
||||||
if (state == GMON_PROF_OFF) {
|
if (state == GMON_PROF_OFF) {
|
||||||
gp->state = state;
|
gp->state = state;
|
||||||
|
PROC_LOCK(&proc0);
|
||||||
stopprofclock(&proc0);
|
stopprofclock(&proc0);
|
||||||
|
PROC_UNLOCK(&proc0);
|
||||||
stopguprof(gp);
|
stopguprof(gp);
|
||||||
} else if (state == GMON_PROF_ON) {
|
} else if (state == GMON_PROF_ON) {
|
||||||
gp->state = GMON_PROF_OFF;
|
gp->state = GMON_PROF_OFF;
|
||||||
@ -369,7 +371,9 @@ sysctl_kern_prof(SYSCTL_HANDLER_ARGS)
|
|||||||
#ifdef GUPROF
|
#ifdef GUPROF
|
||||||
} else if (state == GMON_PROF_HIRES) {
|
} else if (state == GMON_PROF_HIRES) {
|
||||||
gp->state = GMON_PROF_OFF;
|
gp->state = GMON_PROF_OFF;
|
||||||
|
PROC_LOCK(&proc0);
|
||||||
stopprofclock(&proc0);
|
stopprofclock(&proc0);
|
||||||
|
PROC_UNLOCK(&proc0);
|
||||||
startguprof(gp);
|
startguprof(gp);
|
||||||
gp->state = state;
|
gp->state = state;
|
||||||
#endif
|
#endif
|
||||||
@ -419,7 +423,7 @@ profil(td, uap)
|
|||||||
struct thread *td;
|
struct thread *td;
|
||||||
register struct profil_args *uap;
|
register struct profil_args *uap;
|
||||||
{
|
{
|
||||||
register struct uprof *upp;
|
struct uprof *upp;
|
||||||
int s;
|
int s;
|
||||||
int error = 0;
|
int error = 0;
|
||||||
|
|
||||||
@ -430,7 +434,9 @@ profil(td, uap)
|
|||||||
goto done2;
|
goto done2;
|
||||||
}
|
}
|
||||||
if (uap->scale == 0) {
|
if (uap->scale == 0) {
|
||||||
|
PROC_LOCK(td->td_proc);
|
||||||
stopprofclock(td->td_proc);
|
stopprofclock(td->td_proc);
|
||||||
|
PROC_UNLOCK(td->td_proc);
|
||||||
goto done2;
|
goto done2;
|
||||||
}
|
}
|
||||||
upp = &td->td_proc->p_stats->p_prof;
|
upp = &td->td_proc->p_stats->p_prof;
|
||||||
@ -472,15 +478,12 @@ profil(td, uap)
|
|||||||
* inaccurate.
|
* inaccurate.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
addupc_intr(ke, pc, ticks)
|
addupc_intr(struct kse *ke, uintptr_t pc, u_int ticks)
|
||||||
register struct kse *ke;
|
|
||||||
register uintptr_t pc;
|
|
||||||
u_int ticks;
|
|
||||||
{
|
{
|
||||||
register struct uprof *prof;
|
struct uprof *prof;
|
||||||
register caddr_t addr;
|
caddr_t addr;
|
||||||
register u_int i;
|
u_int i;
|
||||||
register int v;
|
int v;
|
||||||
|
|
||||||
if (ticks == 0)
|
if (ticks == 0)
|
||||||
return;
|
return;
|
||||||
@ -502,34 +505,56 @@ addupc_intr(ke, pc, ticks)
|
|||||||
/*
|
/*
|
||||||
* Much like before, but we can afford to take faults here. If the
|
* Much like before, but we can afford to take faults here. If the
|
||||||
* update fails, we simply turn off profiling.
|
* update fails, we simply turn off profiling.
|
||||||
|
* XXXKSE, don't use kse unless we got sched lock.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
addupc_task(ke, pc, ticks)
|
addupc_task(struct kse *ke, uintptr_t pc, u_int ticks)
|
||||||
register struct kse *ke;
|
|
||||||
register uintptr_t pc;
|
|
||||||
u_int ticks;
|
|
||||||
{
|
{
|
||||||
struct proc *p = ke->ke_proc;
|
struct proc *p = ke->ke_proc;
|
||||||
register struct uprof *prof;
|
struct uprof *prof;
|
||||||
register caddr_t addr;
|
caddr_t addr;
|
||||||
register u_int i;
|
u_int i;
|
||||||
u_short v;
|
u_short v;
|
||||||
|
int stop = 0;
|
||||||
|
|
||||||
if (ticks == 0)
|
if (ticks == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
PROC_LOCK(p);
|
||||||
|
mtx_lock_spin(&sched_lock);
|
||||||
|
if (!(p->p_sflag & PS_PROFIL)) {
|
||||||
|
mtx_unlock_spin(&sched_lock);
|
||||||
|
PROC_UNLOCK(p);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p->p_profthreads++;
|
||||||
|
mtx_unlock_spin(&sched_lock);
|
||||||
|
PROC_UNLOCK(p);
|
||||||
prof = &p->p_stats->p_prof;
|
prof = &p->p_stats->p_prof;
|
||||||
if (pc < prof->pr_off ||
|
if (pc < prof->pr_off ||
|
||||||
(i = PC_TO_INDEX(pc, prof)) >= prof->pr_size)
|
(i = PC_TO_INDEX(pc, prof)) >= prof->pr_size) {
|
||||||
return;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
addr = prof->pr_base + i;
|
addr = prof->pr_base + i;
|
||||||
if (copyin(addr, &v, sizeof(v)) == 0) {
|
if (copyin(addr, &v, sizeof(v)) == 0) {
|
||||||
v += ticks;
|
v += ticks;
|
||||||
if (copyout(&v, addr, sizeof(v)) == 0)
|
if (copyout(&v, addr, sizeof(v)) == 0)
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
stopprofclock(p);
|
stop = 1;
|
||||||
|
|
||||||
|
out:
|
||||||
|
PROC_LOCK(p);
|
||||||
|
if (--p->p_profthreads == 0) {
|
||||||
|
if (p->p_sflag & PS_STOPPROF) {
|
||||||
|
wakeup(&p->p_profthreads);
|
||||||
|
stop = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stop)
|
||||||
|
stopprofclock(p);
|
||||||
|
PROC_UNLOCK(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__i386__) && __GNUC__ >= 2
|
#if defined(__i386__) && __GNUC__ >= 2
|
||||||
|
@ -569,12 +569,13 @@ struct proc {
|
|||||||
u_int p_swtime; /* (j) Time swapped in or out. */
|
u_int p_swtime; /* (j) Time swapped in or out. */
|
||||||
struct itimerval p_realtimer; /* (h?/k?) Alarm timer. */
|
struct itimerval p_realtimer; /* (h?/k?) Alarm timer. */
|
||||||
struct bintime p_runtime; /* (j) Real time. */
|
struct bintime p_runtime; /* (j) Real time. */
|
||||||
|
int p_profthreads; /* (c) Num threads in addupc_task */
|
||||||
int p_traceflag; /* (o) Kernel trace points. */
|
int p_traceflag; /* (o) Kernel trace points. */
|
||||||
struct vnode *p_tracep; /* (c + o) Trace to vnode. */
|
struct vnode *p_tracep; /* (c + o) Trace to vnode. */
|
||||||
sigset_t p_siglist; /* (c) Sigs arrived, not delivered. */
|
sigset_t p_siglist; /* (c) Sigs arrived, not delivered. */
|
||||||
struct vnode *p_textvp; /* (b) Vnode of executable. */
|
struct vnode *p_textvp; /* (b) Vnode of executable. */
|
||||||
char p_lock; /* (c) Proclock (prevent swap) count. */
|
char p_lock; /* (c) Proclock (prevent swap) count. */
|
||||||
struct klist p_klist; /* (c) Knotes attached to this proc. */
|
struct klist p_klist; /* (c) Knotes attached to this proc. */
|
||||||
struct sigiolst p_sigiolst; /* (c) List of sigio sources. */
|
struct sigiolst p_sigiolst; /* (c) List of sigio sources. */
|
||||||
int p_sigparent; /* (c) Signal to parent on exit. */
|
int p_sigparent; /* (c) Signal to parent on exit. */
|
||||||
sigset_t p_oldsigmask; /* (c) Saved mask from pre sigpause. */
|
sigset_t p_oldsigmask; /* (c) Saved mask from pre sigpause. */
|
||||||
@ -669,6 +670,7 @@ struct proc {
|
|||||||
#define PS_INMEM 0x00001 /* Loaded into memory. */
|
#define PS_INMEM 0x00001 /* Loaded into memory. */
|
||||||
#define PS_XCPU 0x00002 /* Exceeded CPU limit. */
|
#define PS_XCPU 0x00002 /* Exceeded CPU limit. */
|
||||||
#define PS_PROFIL 0x00004 /* Has started profiling. */
|
#define PS_PROFIL 0x00004 /* Has started profiling. */
|
||||||
|
#define PS_STOPPROF 0x00008 /* Has thread in requesting to stop prof */
|
||||||
#define PS_ALRMPEND 0x00020 /* Pending SIGVTALRM needs to be posted. */
|
#define PS_ALRMPEND 0x00020 /* Pending SIGVTALRM needs to be posted. */
|
||||||
#define PS_PROFPEND 0x00040 /* Pending SIGPROF needs to be posted. */
|
#define PS_PROFPEND 0x00040 /* Pending SIGPROF needs to be posted. */
|
||||||
#define PS_SWAPINREQ 0x00100 /* Swapin request due to wakeup. */
|
#define PS_SWAPINREQ 0x00100 /* Swapin request due to wakeup. */
|
||||||
|
Loading…
Reference in New Issue
Block a user