Fixup r240246: hwpmc needs to retain the pinning until ASTs are not

executed. This means past the point where userret() is generally
executed.

Skip the td_pinned check if a callchain tracing is currently happening
and add a more robust check to pmc_capture_user_callchain() in order to
catch td_pinned leak past ast() in hwpmc case.

Reported and tested by:	fabient
MFC after:	1 week
X-MFC:	r240246
This commit is contained in:
attilio 2012-10-30 15:10:50 +00:00
parent a93bdbb610
commit 279b97daea
2 changed files with 7 additions and 2 deletions

View File

@ -4248,7 +4248,7 @@ pmc_capture_user_callchain(int cpu, int ring, struct trapframe *tf)
("[pmc,%d] cpu %d didn't find a sample to collect", __LINE__,
cpu));
KASSERT(td->td_pinned > 0,
KASSERT(td->td_pinned == 1,
("[pmc,%d] invalid td_pinned value", __LINE__));
sched_unpin(); /* Can migrate safely now. */

View File

@ -145,6 +145,11 @@ userret(struct thread *td, struct trapframe *frame)
/*
* Check for misbehavior.
*
* In case there is a callchain tracing ongoing because of
* hwpmc(4), skip the scheduler pinning check.
* hwpmc(4) subsystem, infact, will collect callchain informations
* at ast() checkpoint, which is past userret().
*/
WITNESS_WARN(WARN_PANIC, NULL, "userret: returning");
KASSERT(td->td_critnest == 0,
@ -155,7 +160,7 @@ userret(struct thread *td, struct trapframe *frame)
("userret: Returning with pagefaults disabled"));
KASSERT((td->td_pflags & TDP_NOSLEEPING) == 0,
("userret: Returning with sleep disabled"));
KASSERT(td->td_pinned == 0,
KASSERT(td->td_pinned == 0 || (td->td_pflags & TDP_CALLCHAIN) != 0,
("userret: Returning with with pinned thread"));
KASSERT(td->td_vp_reserv == 0,
("userret: Returning while holding vnode reservation"));