A little infrastructure, preceding some upcoming changes

to the profiling and statistics code.

Submitted by:	DavidXu@
Reviewed by:	peter@
This commit is contained in:
Julian Elischer 2003-02-08 02:58:16 +00:00
parent 8480e03dd7
commit a282253a29
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=110530
4 changed files with 69 additions and 26 deletions

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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. */