mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-14 12:23:58 +00:00
Add a new thread state "spinning" to schedgraph and add tracepoints at the
start and stop of spinning waits in lock primitives.
This commit is contained in:
parent
9799411bf7
commit
2cba8dd301
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=274092
|
@ -582,6 +582,9 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
|
||||||
CTR3(KTR_LOCK,
|
CTR3(KTR_LOCK,
|
||||||
"%s: spinning on %p held by %p",
|
"%s: spinning on %p held by %p",
|
||||||
__func__, lk, owner);
|
__func__, lk, owner);
|
||||||
|
KTR_STATE1(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(td), "spinning",
|
||||||
|
"lockname:\"%s\"", lk->lock_object.lo_name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are holding also an interlock drop it
|
* If we are holding also an interlock drop it
|
||||||
|
@ -597,11 +600,16 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
|
||||||
while (LK_HOLDER(lk->lk_lock) ==
|
while (LK_HOLDER(lk->lk_lock) ==
|
||||||
(uintptr_t)owner && TD_IS_RUNNING(owner))
|
(uintptr_t)owner && TD_IS_RUNNING(owner))
|
||||||
cpu_spinwait();
|
cpu_spinwait();
|
||||||
|
KTR_STATE0(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(td), "running");
|
||||||
GIANT_RESTORE();
|
GIANT_RESTORE();
|
||||||
continue;
|
continue;
|
||||||
} else if (LK_CAN_ADAPT(lk, flags) &&
|
} else if (LK_CAN_ADAPT(lk, flags) &&
|
||||||
(x & LK_SHARE) != 0 && LK_SHARERS(x) &&
|
(x & LK_SHARE) != 0 && LK_SHARERS(x) &&
|
||||||
spintries < alk_retries) {
|
spintries < alk_retries) {
|
||||||
|
KTR_STATE1(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(td), "spinning",
|
||||||
|
"lockname:\"%s\"", lk->lock_object.lo_name);
|
||||||
if (flags & LK_INTERLOCK) {
|
if (flags & LK_INTERLOCK) {
|
||||||
class->lc_unlock(ilk);
|
class->lc_unlock(ilk);
|
||||||
flags &= ~LK_INTERLOCK;
|
flags &= ~LK_INTERLOCK;
|
||||||
|
@ -619,6 +627,8 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
|
||||||
break;
|
break;
|
||||||
cpu_spinwait();
|
cpu_spinwait();
|
||||||
}
|
}
|
||||||
|
KTR_STATE0(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(td), "running");
|
||||||
GIANT_RESTORE();
|
GIANT_RESTORE();
|
||||||
if (i != alk_loops)
|
if (i != alk_loops)
|
||||||
continue;
|
continue;
|
||||||
|
@ -814,6 +824,9 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
|
||||||
CTR3(KTR_LOCK,
|
CTR3(KTR_LOCK,
|
||||||
"%s: spinning on %p held by %p",
|
"%s: spinning on %p held by %p",
|
||||||
__func__, lk, owner);
|
__func__, lk, owner);
|
||||||
|
KTR_STATE1(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(td), "spinning",
|
||||||
|
"lockname:\"%s\"", lk->lock_object.lo_name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we are holding also an interlock drop it
|
* If we are holding also an interlock drop it
|
||||||
|
@ -829,6 +842,8 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
|
||||||
while (LK_HOLDER(lk->lk_lock) ==
|
while (LK_HOLDER(lk->lk_lock) ==
|
||||||
(uintptr_t)owner && TD_IS_RUNNING(owner))
|
(uintptr_t)owner && TD_IS_RUNNING(owner))
|
||||||
cpu_spinwait();
|
cpu_spinwait();
|
||||||
|
KTR_STATE0(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(td), "running");
|
||||||
GIANT_RESTORE();
|
GIANT_RESTORE();
|
||||||
continue;
|
continue;
|
||||||
} else if (LK_CAN_ADAPT(lk, flags) &&
|
} else if (LK_CAN_ADAPT(lk, flags) &&
|
||||||
|
@ -838,6 +853,9 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
|
||||||
!atomic_cmpset_ptr(&lk->lk_lock, x,
|
!atomic_cmpset_ptr(&lk->lk_lock, x,
|
||||||
x | LK_EXCLUSIVE_SPINNERS))
|
x | LK_EXCLUSIVE_SPINNERS))
|
||||||
continue;
|
continue;
|
||||||
|
KTR_STATE1(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(td), "spinning",
|
||||||
|
"lockname:\"%s\"", lk->lock_object.lo_name);
|
||||||
if (flags & LK_INTERLOCK) {
|
if (flags & LK_INTERLOCK) {
|
||||||
class->lc_unlock(ilk);
|
class->lc_unlock(ilk);
|
||||||
flags &= ~LK_INTERLOCK;
|
flags &= ~LK_INTERLOCK;
|
||||||
|
@ -854,6 +872,8 @@ __lockmgr_args(struct lock *lk, u_int flags, struct lock_object *ilk,
|
||||||
break;
|
break;
|
||||||
cpu_spinwait();
|
cpu_spinwait();
|
||||||
}
|
}
|
||||||
|
KTR_STATE0(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(td), "running");
|
||||||
GIANT_RESTORE();
|
GIANT_RESTORE();
|
||||||
if (i != alk_loops)
|
if (i != alk_loops)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -433,6 +433,10 @@ __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t tid, int opts,
|
||||||
CTR3(KTR_LOCK,
|
CTR3(KTR_LOCK,
|
||||||
"%s: spinning on %p held by %p",
|
"%s: spinning on %p held by %p",
|
||||||
__func__, m, owner);
|
__func__, m, owner);
|
||||||
|
KTR_STATE1(KTR_SCHED, "thread",
|
||||||
|
sched_tdname((struct thread *)tid),
|
||||||
|
"spinning", "lockname:\"%s\"",
|
||||||
|
m->lock_object.lo_name);
|
||||||
while (mtx_owner(m) == owner &&
|
while (mtx_owner(m) == owner &&
|
||||||
TD_IS_RUNNING(owner)) {
|
TD_IS_RUNNING(owner)) {
|
||||||
cpu_spinwait();
|
cpu_spinwait();
|
||||||
|
@ -440,6 +444,9 @@ __mtx_lock_sleep(volatile uintptr_t *c, uintptr_t tid, int opts,
|
||||||
spin_cnt++;
|
spin_cnt++;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
KTR_STATE0(KTR_SCHED, "thread",
|
||||||
|
sched_tdname((struct thread *)tid),
|
||||||
|
"running");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -576,6 +583,8 @@ _mtx_lock_spin_cookie(volatile uintptr_t *c, uintptr_t tid, int opts,
|
||||||
|
|
||||||
if (LOCK_LOG_TEST(&m->lock_object, opts))
|
if (LOCK_LOG_TEST(&m->lock_object, opts))
|
||||||
CTR1(KTR_LOCK, "_mtx_lock_spin: %p spinning", m);
|
CTR1(KTR_LOCK, "_mtx_lock_spin: %p spinning", m);
|
||||||
|
KTR_STATE1(KTR_SCHED, "thread", sched_tdname((struct thread *)tid),
|
||||||
|
"spinning", "lockname:\"%s\"", m->lock_object.lo_name);
|
||||||
|
|
||||||
#ifdef HWPMC_HOOKS
|
#ifdef HWPMC_HOOKS
|
||||||
PMC_SOFT_CALL( , , lock, failed);
|
PMC_SOFT_CALL( , , lock, failed);
|
||||||
|
@ -601,6 +610,8 @@ _mtx_lock_spin_cookie(volatile uintptr_t *c, uintptr_t tid, int opts,
|
||||||
|
|
||||||
if (LOCK_LOG_TEST(&m->lock_object, opts))
|
if (LOCK_LOG_TEST(&m->lock_object, opts))
|
||||||
CTR1(KTR_LOCK, "_mtx_lock_spin: %p spin done", m);
|
CTR1(KTR_LOCK, "_mtx_lock_spin: %p spin done", m);
|
||||||
|
KTR_STATE0(KTR_SCHED, "thread", sched_tdname((struct thread *)tid),
|
||||||
|
"running");
|
||||||
|
|
||||||
LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_MTX_SPIN_LOCK_ACQUIRE, m,
|
LOCKSTAT_PROFILE_OBTAIN_LOCK_SUCCESS(LS_MTX_SPIN_LOCK_ACQUIRE, m,
|
||||||
contested, waittime, (file), (line));
|
contested, waittime, (file), (line));
|
||||||
|
|
|
@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
|
||||||
#include <sys/mutex.h>
|
#include <sys/mutex.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
#include <sys/rwlock.h>
|
#include <sys/rwlock.h>
|
||||||
|
#include <sys/sched.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/turnstile.h>
|
#include <sys/turnstile.h>
|
||||||
|
@ -420,6 +421,9 @@ __rw_rlock(volatile uintptr_t *c, const char *file, int line)
|
||||||
CTR3(KTR_LOCK,
|
CTR3(KTR_LOCK,
|
||||||
"%s: spinning on %p held by %p",
|
"%s: spinning on %p held by %p",
|
||||||
__func__, rw, owner);
|
__func__, rw, owner);
|
||||||
|
KTR_STATE1(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(curthread), "spinning",
|
||||||
|
"lockname:\"%s\"", rw->lock_object.lo_name);
|
||||||
while ((struct thread*)RW_OWNER(rw->rw_lock) ==
|
while ((struct thread*)RW_OWNER(rw->rw_lock) ==
|
||||||
owner && TD_IS_RUNNING(owner)) {
|
owner && TD_IS_RUNNING(owner)) {
|
||||||
cpu_spinwait();
|
cpu_spinwait();
|
||||||
|
@ -427,10 +431,15 @@ __rw_rlock(volatile uintptr_t *c, const char *file, int line)
|
||||||
spin_cnt++;
|
spin_cnt++;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
KTR_STATE0(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(curthread), "running");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (spintries < rowner_retries) {
|
} else if (spintries < rowner_retries) {
|
||||||
spintries++;
|
spintries++;
|
||||||
|
KTR_STATE1(KTR_SCHED, "thread", sched_tdname(curthread),
|
||||||
|
"spinning", "lockname:\"%s\"",
|
||||||
|
rw->lock_object.lo_name);
|
||||||
for (i = 0; i < rowner_loops; i++) {
|
for (i = 0; i < rowner_loops; i++) {
|
||||||
v = rw->rw_lock;
|
v = rw->rw_lock;
|
||||||
if ((v & RW_LOCK_READ) == 0 || RW_CAN_READ(v))
|
if ((v & RW_LOCK_READ) == 0 || RW_CAN_READ(v))
|
||||||
|
@ -440,6 +449,8 @@ __rw_rlock(volatile uintptr_t *c, const char *file, int line)
|
||||||
#ifdef KDTRACE_HOOKS
|
#ifdef KDTRACE_HOOKS
|
||||||
spin_cnt += rowner_loops - i;
|
spin_cnt += rowner_loops - i;
|
||||||
#endif
|
#endif
|
||||||
|
KTR_STATE0(KTR_SCHED, "thread", sched_tdname(curthread),
|
||||||
|
"running");
|
||||||
if (i != rowner_loops)
|
if (i != rowner_loops)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -759,6 +770,9 @@ __rw_wlock_hard(volatile uintptr_t *c, uintptr_t tid, const char *file,
|
||||||
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
if (LOCK_LOG_TEST(&rw->lock_object, 0))
|
||||||
CTR3(KTR_LOCK, "%s: spinning on %p held by %p",
|
CTR3(KTR_LOCK, "%s: spinning on %p held by %p",
|
||||||
__func__, rw, owner);
|
__func__, rw, owner);
|
||||||
|
KTR_STATE1(KTR_SCHED, "thread", sched_tdname(curthread),
|
||||||
|
"spinning", "lockname:\"%s\"",
|
||||||
|
rw->lock_object.lo_name);
|
||||||
while ((struct thread*)RW_OWNER(rw->rw_lock) == owner &&
|
while ((struct thread*)RW_OWNER(rw->rw_lock) == owner &&
|
||||||
TD_IS_RUNNING(owner)) {
|
TD_IS_RUNNING(owner)) {
|
||||||
cpu_spinwait();
|
cpu_spinwait();
|
||||||
|
@ -766,6 +780,8 @@ __rw_wlock_hard(volatile uintptr_t *c, uintptr_t tid, const char *file,
|
||||||
spin_cnt++;
|
spin_cnt++;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
KTR_STATE0(KTR_SCHED, "thread", sched_tdname(curthread),
|
||||||
|
"running");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((v & RW_LOCK_READ) && RW_READERS(v) &&
|
if ((v & RW_LOCK_READ) && RW_READERS(v) &&
|
||||||
|
@ -777,11 +793,16 @@ __rw_wlock_hard(volatile uintptr_t *c, uintptr_t tid, const char *file,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spintries++;
|
spintries++;
|
||||||
|
KTR_STATE1(KTR_SCHED, "thread", sched_tdname(curthread),
|
||||||
|
"spinning", "lockname:\"%s\"",
|
||||||
|
rw->lock_object.lo_name);
|
||||||
for (i = 0; i < rowner_loops; i++) {
|
for (i = 0; i < rowner_loops; i++) {
|
||||||
if ((rw->rw_lock & RW_LOCK_WRITE_SPINNER) == 0)
|
if ((rw->rw_lock & RW_LOCK_WRITE_SPINNER) == 0)
|
||||||
break;
|
break;
|
||||||
cpu_spinwait();
|
cpu_spinwait();
|
||||||
}
|
}
|
||||||
|
KTR_STATE0(KTR_SCHED, "thread", sched_tdname(curthread),
|
||||||
|
"running");
|
||||||
#ifdef KDTRACE_HOOKS
|
#ifdef KDTRACE_HOOKS
|
||||||
spin_cnt += rowner_loops - i;
|
spin_cnt += rowner_loops - i;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
|
||||||
#include <sys/lock.h>
|
#include <sys/lock.h>
|
||||||
#include <sys/mutex.h>
|
#include <sys/mutex.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
|
#include <sys/sched.h>
|
||||||
#include <sys/sleepqueue.h>
|
#include <sys/sleepqueue.h>
|
||||||
#include <sys/sx.h>
|
#include <sys/sx.h>
|
||||||
#include <sys/sysctl.h>
|
#include <sys/sysctl.h>
|
||||||
|
@ -555,6 +556,10 @@ _sx_xlock_hard(struct sx *sx, uintptr_t tid, int opts, const char *file,
|
||||||
CTR3(KTR_LOCK,
|
CTR3(KTR_LOCK,
|
||||||
"%s: spinning on %p held by %p",
|
"%s: spinning on %p held by %p",
|
||||||
__func__, sx, owner);
|
__func__, sx, owner);
|
||||||
|
KTR_STATE1(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(curthread), "spinning",
|
||||||
|
"lockname:\"%s\"",
|
||||||
|
sx->lock_object.lo_name);
|
||||||
GIANT_SAVE();
|
GIANT_SAVE();
|
||||||
while (SX_OWNER(sx->sx_lock) == x &&
|
while (SX_OWNER(sx->sx_lock) == x &&
|
||||||
TD_IS_RUNNING(owner)) {
|
TD_IS_RUNNING(owner)) {
|
||||||
|
@ -563,9 +568,14 @@ _sx_xlock_hard(struct sx *sx, uintptr_t tid, int opts, const char *file,
|
||||||
spin_cnt++;
|
spin_cnt++;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
KTR_STATE0(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(curthread), "running");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (SX_SHARERS(x) && spintries < asx_retries) {
|
} else if (SX_SHARERS(x) && spintries < asx_retries) {
|
||||||
|
KTR_STATE1(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(curthread), "spinning",
|
||||||
|
"lockname:\"%s\"", sx->lock_object.lo_name);
|
||||||
GIANT_SAVE();
|
GIANT_SAVE();
|
||||||
spintries++;
|
spintries++;
|
||||||
for (i = 0; i < asx_loops; i++) {
|
for (i = 0; i < asx_loops; i++) {
|
||||||
|
@ -582,6 +592,8 @@ _sx_xlock_hard(struct sx *sx, uintptr_t tid, int opts, const char *file,
|
||||||
spin_cnt++;
|
spin_cnt++;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
KTR_STATE0(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(curthread), "running");
|
||||||
if (i != asx_loops)
|
if (i != asx_loops)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -844,6 +856,9 @@ _sx_slock_hard(struct sx *sx, int opts, const char *file, int line)
|
||||||
CTR3(KTR_LOCK,
|
CTR3(KTR_LOCK,
|
||||||
"%s: spinning on %p held by %p",
|
"%s: spinning on %p held by %p",
|
||||||
__func__, sx, owner);
|
__func__, sx, owner);
|
||||||
|
KTR_STATE1(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(curthread), "spinning",
|
||||||
|
"lockname:\"%s\"", sx->lock_object.lo_name);
|
||||||
GIANT_SAVE();
|
GIANT_SAVE();
|
||||||
while (SX_OWNER(sx->sx_lock) == x &&
|
while (SX_OWNER(sx->sx_lock) == x &&
|
||||||
TD_IS_RUNNING(owner)) {
|
TD_IS_RUNNING(owner)) {
|
||||||
|
@ -852,6 +867,8 @@ _sx_slock_hard(struct sx *sx, int opts, const char *file, int line)
|
||||||
#endif
|
#endif
|
||||||
cpu_spinwait();
|
cpu_spinwait();
|
||||||
}
|
}
|
||||||
|
KTR_STATE0(KTR_SCHED, "thread",
|
||||||
|
sched_tdname(curthread), "running");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,7 @@
|
||||||
("count", "red"),
|
("count", "red"),
|
||||||
("running", "green"),
|
("running", "green"),
|
||||||
("idle", "grey"),
|
("idle", "grey"),
|
||||||
|
("spinning", "red"),
|
||||||
("yielding", "yellow"),
|
("yielding", "yellow"),
|
||||||
("swapped", "violet"),
|
("swapped", "violet"),
|
||||||
("suspended", "purple"),
|
("suspended", "purple"),
|
||||||
|
|
Loading…
Reference in a new issue