Some small fixes to CPU accounting for threads:
- Only initialize the per-cpu switchticks and switchtime in sched_throw() for the very first context switch on APs during boot. This avoids a small gap between the middle of thread_exit() and sched_throw() where time is not accounted to any thread. - In thread_exit(), update the timestamp bookkeeping to track the changes to mi_switch() introduced by td_rux so that the code once again matches the comment claiming it is mimicing mi_switch(). Specifically, only update the per-thread stats directly and depend on ruxagg() to update p_rux rather than adjusting p_rux directly. While here, move the timestamp bookkeeping as late in the function as possible. Reviewed by: bde, kib MFC after: 1 week
This commit is contained in:
parent
48a1e3f624
commit
7e3a96ea37
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=229429
@ -381,7 +381,7 @@ thread_free(struct thread *td)
|
||||
void
|
||||
thread_exit(void)
|
||||
{
|
||||
uint64_t new_switchtime;
|
||||
uint64_t runtime, new_switchtime;
|
||||
struct thread *td;
|
||||
struct thread *td2;
|
||||
struct proc *p;
|
||||
@ -410,15 +410,6 @@ thread_exit(void)
|
||||
*/
|
||||
cpu_thread_exit(td); /* XXXSMP */
|
||||
|
||||
/* Do the same timestamp bookkeeping that mi_switch() would do. */
|
||||
new_switchtime = cpu_ticks();
|
||||
p->p_rux.rux_runtime += (new_switchtime - PCPU_GET(switchtime));
|
||||
PCPU_SET(switchtime, new_switchtime);
|
||||
PCPU_SET(switchticks, ticks);
|
||||
PCPU_INC(cnt.v_swtch);
|
||||
/* Save our resource usage in our process. */
|
||||
td->td_ru.ru_nvcsw++;
|
||||
rucollect(&p->p_ru, &td->td_ru);
|
||||
/*
|
||||
* The last thread is left attached to the process
|
||||
* So that the whole bundle gets recycled. Skip
|
||||
@ -467,7 +458,21 @@ thread_exit(void)
|
||||
PMC_SWITCH_CONTEXT(td, PMC_FN_CSW_OUT);
|
||||
#endif
|
||||
PROC_UNLOCK(p);
|
||||
|
||||
/* Do the same timestamp bookkeeping that mi_switch() would do. */
|
||||
new_switchtime = cpu_ticks();
|
||||
runtime = new_switchtime - PCPU_GET(switchtime);
|
||||
td->td_runtime += runtime;
|
||||
td->td_incruntime += runtime;
|
||||
PCPU_SET(switchtime, new_switchtime);
|
||||
PCPU_SET(switchticks, ticks);
|
||||
PCPU_INC(cnt.v_swtch);
|
||||
|
||||
/* Save our resource usage in our process. */
|
||||
td->td_ru.ru_nvcsw++;
|
||||
ruxagg(p, td);
|
||||
rucollect(&p->p_ru, &td->td_ru);
|
||||
|
||||
thread_lock(td);
|
||||
PROC_SUNLOCK(p);
|
||||
td->td_state = TDS_INACTIVE;
|
||||
|
@ -1572,14 +1572,14 @@ sched_throw(struct thread *td)
|
||||
if (td == NULL) {
|
||||
mtx_lock_spin(&sched_lock);
|
||||
spinlock_exit();
|
||||
PCPU_SET(switchtime, cpu_ticks());
|
||||
PCPU_SET(switchticks, ticks);
|
||||
} else {
|
||||
lock_profile_release_lock(&sched_lock.lock_object);
|
||||
MPASS(td->td_lock == &sched_lock);
|
||||
}
|
||||
mtx_assert(&sched_lock, MA_OWNED);
|
||||
KASSERT(curthread->td_md.md_spinlock_count == 1, ("invalid count"));
|
||||
PCPU_SET(switchtime, cpu_ticks());
|
||||
PCPU_SET(switchticks, ticks);
|
||||
cpu_throw(td, choosethread()); /* doesn't return */
|
||||
}
|
||||
|
||||
|
@ -2587,6 +2587,8 @@ sched_throw(struct thread *td)
|
||||
/* Correct spinlock nesting and acquire the correct lock. */
|
||||
TDQ_LOCK(tdq);
|
||||
spinlock_exit();
|
||||
PCPU_SET(switchtime, cpu_ticks());
|
||||
PCPU_SET(switchticks, ticks);
|
||||
} else {
|
||||
MPASS(td->td_lock == TDQ_LOCKPTR(tdq));
|
||||
tdq_load_rem(tdq, td);
|
||||
@ -2595,8 +2597,6 @@ sched_throw(struct thread *td)
|
||||
KASSERT(curthread->td_md.md_spinlock_count == 1, ("invalid count"));
|
||||
newtd = choosethread();
|
||||
TDQ_LOCKPTR(tdq)->mtx_lock = (uintptr_t)newtd;
|
||||
PCPU_SET(switchtime, cpu_ticks());
|
||||
PCPU_SET(switchticks, ticks);
|
||||
cpu_throw(td, newtd); /* doesn't return */
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user