- Move clock synchronization into a seperate clock lock so the global
scheduler lock is not involved. sched_lock still protects the sched_clock call. Another patch will remedy this. Contributed by: Attilio Rao <attilio@FreeBSD.org> Tested by: kris, jeff
This commit is contained in:
parent
0ad5e7f326
commit
8b98fec903
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=169803
@ -83,6 +83,9 @@ SYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL)
|
|||||||
/* Some of these don't belong here, but it's easiest to concentrate them. */
|
/* Some of these don't belong here, but it's easiest to concentrate them. */
|
||||||
long cp_time[CPUSTATES];
|
long cp_time[CPUSTATES];
|
||||||
|
|
||||||
|
/* Spin-lock protecting profiling statistics. */
|
||||||
|
struct mtx time_lock;
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sysctl_kern_cp_time(SYSCTL_HANDLER_ARGS)
|
sysctl_kern_cp_time(SYSCTL_HANDLER_ARGS)
|
||||||
{
|
{
|
||||||
@ -172,6 +175,7 @@ initclocks(dummy)
|
|||||||
* code do its bit.
|
* code do its bit.
|
||||||
*/
|
*/
|
||||||
cpu_initclocks();
|
cpu_initclocks();
|
||||||
|
mtx_init(&time_lock, "time lock", NULL, MTX_SPIN);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute profhz/stathz, and fix profhz if needed.
|
* Compute profhz/stathz, and fix profhz if needed.
|
||||||
@ -349,20 +353,15 @@ startprofclock(p)
|
|||||||
register struct proc *p;
|
register struct proc *p;
|
||||||
{
|
{
|
||||||
|
|
||||||
/*
|
|
||||||
* XXX; Right now sched_lock protects statclock(), but perhaps
|
|
||||||
* it should be protected later on by a time_lock, which would
|
|
||||||
* cover psdiv, etc. as well.
|
|
||||||
*/
|
|
||||||
PROC_LOCK_ASSERT(p, MA_OWNED);
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
||||||
if (p->p_flag & P_STOPPROF)
|
if (p->p_flag & P_STOPPROF)
|
||||||
return;
|
return;
|
||||||
if ((p->p_flag & P_PROFIL) == 0) {
|
if ((p->p_flag & P_PROFIL) == 0) {
|
||||||
mtx_lock_spin(&sched_lock);
|
|
||||||
p->p_flag |= P_PROFIL;
|
p->p_flag |= P_PROFIL;
|
||||||
|
mtx_lock_spin(&time_lock);
|
||||||
if (++profprocs == 1)
|
if (++profprocs == 1)
|
||||||
cpu_startprofclock();
|
cpu_startprofclock();
|
||||||
mtx_unlock_spin(&sched_lock);
|
mtx_unlock_spin(&time_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,11 +384,11 @@ stopprofclock(p)
|
|||||||
}
|
}
|
||||||
if ((p->p_flag & P_PROFIL) == 0)
|
if ((p->p_flag & P_PROFIL) == 0)
|
||||||
return;
|
return;
|
||||||
mtx_lock_spin(&sched_lock);
|
|
||||||
p->p_flag &= ~P_PROFIL;
|
p->p_flag &= ~P_PROFIL;
|
||||||
|
mtx_lock_spin(&time_lock);
|
||||||
if (--profprocs == 0)
|
if (--profprocs == 0)
|
||||||
cpu_stopprofclock();
|
cpu_stopprofclock();
|
||||||
mtx_unlock_spin(&sched_lock);
|
mtx_unlock_spin(&time_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,7 +411,6 @@ statclock(int usermode)
|
|||||||
td = curthread;
|
td = curthread;
|
||||||
p = td->td_proc;
|
p = td->td_proc;
|
||||||
|
|
||||||
mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
|
|
||||||
if (usermode) {
|
if (usermode) {
|
||||||
/*
|
/*
|
||||||
* Charge the time as appropriate.
|
* Charge the time as appropriate.
|
||||||
@ -422,6 +420,7 @@ statclock(int usermode)
|
|||||||
thread_statclock(1);
|
thread_statclock(1);
|
||||||
#endif
|
#endif
|
||||||
td->td_uticks++;
|
td->td_uticks++;
|
||||||
|
mtx_lock_spin_flags(&time_lock, MTX_QUIET);
|
||||||
if (p->p_nice > NZERO)
|
if (p->p_nice > NZERO)
|
||||||
cp_time[CP_NICE]++;
|
cp_time[CP_NICE]++;
|
||||||
else
|
else
|
||||||
@ -442,6 +441,7 @@ statclock(int usermode)
|
|||||||
if ((td->td_pflags & TDP_ITHREAD) ||
|
if ((td->td_pflags & TDP_ITHREAD) ||
|
||||||
td->td_intr_nesting_level >= 2) {
|
td->td_intr_nesting_level >= 2) {
|
||||||
td->td_iticks++;
|
td->td_iticks++;
|
||||||
|
mtx_lock_spin_flags(&time_lock, MTX_QUIET);
|
||||||
cp_time[CP_INTR]++;
|
cp_time[CP_INTR]++;
|
||||||
} else {
|
} else {
|
||||||
#ifdef KSE
|
#ifdef KSE
|
||||||
@ -450,15 +450,18 @@ statclock(int usermode)
|
|||||||
#endif
|
#endif
|
||||||
td->td_pticks++;
|
td->td_pticks++;
|
||||||
td->td_sticks++;
|
td->td_sticks++;
|
||||||
|
mtx_lock_spin_flags(&time_lock, MTX_QUIET);
|
||||||
if (!TD_IS_IDLETHREAD(td))
|
if (!TD_IS_IDLETHREAD(td))
|
||||||
cp_time[CP_SYS]++;
|
cp_time[CP_SYS]++;
|
||||||
else
|
else
|
||||||
cp_time[CP_IDLE]++;
|
cp_time[CP_IDLE]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mtx_unlock_spin_flags(&time_lock, MTX_QUIET);
|
||||||
CTR4(KTR_SCHED, "statclock: %p(%s) prio %d stathz %d",
|
CTR4(KTR_SCHED, "statclock: %p(%s) prio %d stathz %d",
|
||||||
td, td->td_proc->p_comm, td->td_priority, (stathz)?stathz:hz);
|
td, td->td_proc->p_comm, td->td_priority, (stathz)?stathz:hz);
|
||||||
|
|
||||||
|
mtx_lock_spin_flags(&sched_lock, MTX_QUIET);
|
||||||
sched_clock(td);
|
sched_clock(td);
|
||||||
|
|
||||||
/* Update resource usage integrals and maximums. */
|
/* Update resource usage integrals and maximums. */
|
||||||
|
@ -423,12 +423,12 @@ profil(td, uap)
|
|||||||
}
|
}
|
||||||
PROC_LOCK(p);
|
PROC_LOCK(p);
|
||||||
upp = &td->td_proc->p_stats->p_prof;
|
upp = &td->td_proc->p_stats->p_prof;
|
||||||
mtx_lock_spin(&sched_lock);
|
mtx_lock_spin(&time_lock);
|
||||||
upp->pr_off = uap->offset;
|
upp->pr_off = uap->offset;
|
||||||
upp->pr_scale = uap->scale;
|
upp->pr_scale = uap->scale;
|
||||||
upp->pr_base = uap->samples;
|
upp->pr_base = uap->samples;
|
||||||
upp->pr_size = uap->size;
|
upp->pr_size = uap->size;
|
||||||
mtx_unlock_spin(&sched_lock);
|
mtx_unlock_spin(&time_lock);
|
||||||
startprofclock(p);
|
startprofclock(p);
|
||||||
PROC_UNLOCK(p);
|
PROC_UNLOCK(p);
|
||||||
|
|
||||||
@ -468,15 +468,15 @@ addupc_intr(struct thread *td, uintfptr_t pc, u_int ticks)
|
|||||||
if (ticks == 0)
|
if (ticks == 0)
|
||||||
return;
|
return;
|
||||||
prof = &td->td_proc->p_stats->p_prof;
|
prof = &td->td_proc->p_stats->p_prof;
|
||||||
mtx_lock_spin(&sched_lock);
|
mtx_lock_spin(&time_lock);
|
||||||
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) {
|
||||||
mtx_unlock_spin(&sched_lock);
|
mtx_unlock_spin(&time_lock);
|
||||||
return; /* out of range; ignore */
|
return; /* out of range; ignore */
|
||||||
}
|
}
|
||||||
|
|
||||||
addr = prof->pr_base + i;
|
addr = prof->pr_base + i;
|
||||||
mtx_unlock_spin(&sched_lock);
|
mtx_unlock_spin(&time_lock);
|
||||||
if ((v = fuswintr(addr)) == -1 || suswintr(addr, v + ticks) == -1) {
|
if ((v = fuswintr(addr)) == -1 || suswintr(addr, v + ticks) == -1) {
|
||||||
td->td_profil_addr = pc;
|
td->td_profil_addr = pc;
|
||||||
td->td_profil_ticks = ticks;
|
td->td_profil_ticks = ticks;
|
||||||
|
@ -410,6 +410,7 @@ static struct witness_order_list_entry order_lists[] = {
|
|||||||
{ "callout", &lock_class_mtx_spin },
|
{ "callout", &lock_class_mtx_spin },
|
||||||
{ "entropy harvest mutex", &lock_class_mtx_spin },
|
{ "entropy harvest mutex", &lock_class_mtx_spin },
|
||||||
{ "syscons video lock", &lock_class_mtx_spin },
|
{ "syscons video lock", &lock_class_mtx_spin },
|
||||||
|
{ "time lock", &lock_class_mtx_spin },
|
||||||
/*
|
/*
|
||||||
* leaf locks
|
* leaf locks
|
||||||
*/
|
*/
|
||||||
|
@ -71,6 +71,8 @@ extern int bootverbose; /* nonzero to print verbose messages */
|
|||||||
|
|
||||||
extern int maxusers; /* system tune hint */
|
extern int maxusers; /* system tune hint */
|
||||||
|
|
||||||
|
extern struct mtx time_lock; /* time lock for profiling */
|
||||||
|
|
||||||
#ifdef INVARIANTS /* The option is always available */
|
#ifdef INVARIANTS /* The option is always available */
|
||||||
#define KASSERT(exp,msg) do { \
|
#define KASSERT(exp,msg) do { \
|
||||||
if (__predict_false(!(exp))) \
|
if (__predict_false(!(exp))) \
|
||||||
|
Loading…
Reference in New Issue
Block a user