- fix a LOR between process lock and pmc thread mutex
- fix a system deadlock on process exit when the sample buffer is full (pmclog_loop blocked in fo_write) and pmcstat exit. Reviewed by: jkoshy MFC after: 3 weeks
This commit is contained in:
parent
31e119ed7d
commit
5eaf27d8ff
@ -240,6 +240,7 @@ pmclog_loop(void *arg)
|
|||||||
int error;
|
int error;
|
||||||
struct pmc_owner *po;
|
struct pmc_owner *po;
|
||||||
struct pmclog_buffer *lb;
|
struct pmclog_buffer *lb;
|
||||||
|
struct proc *p;
|
||||||
struct ucred *ownercred;
|
struct ucred *ownercred;
|
||||||
struct ucred *mycred;
|
struct ucred *mycred;
|
||||||
struct thread *td;
|
struct thread *td;
|
||||||
@ -248,12 +249,13 @@ pmclog_loop(void *arg)
|
|||||||
size_t nbytes;
|
size_t nbytes;
|
||||||
|
|
||||||
po = (struct pmc_owner *) arg;
|
po = (struct pmc_owner *) arg;
|
||||||
|
p = po->po_owner;
|
||||||
td = curthread;
|
td = curthread;
|
||||||
mycred = td->td_ucred;
|
mycred = td->td_ucred;
|
||||||
|
|
||||||
PROC_LOCK(po->po_owner);
|
PROC_LOCK(p);
|
||||||
ownercred = crhold(po->po_owner->p_ucred);
|
ownercred = crhold(p->p_ucred);
|
||||||
PROC_UNLOCK(po->po_owner);
|
PROC_UNLOCK(p);
|
||||||
|
|
||||||
PMCDBG(LOG,INI,1, "po=%p kt=%p", po, po->po_kthread);
|
PMCDBG(LOG,INI,1, "po=%p kt=%p", po, po->po_kthread);
|
||||||
KASSERT(po->po_kthread == curthread->td_proc,
|
KASSERT(po->po_kthread == curthread->td_proc,
|
||||||
@ -324,16 +326,16 @@ pmclog_loop(void *arg)
|
|||||||
error = fo_write(po->po_file, &auio, ownercred, 0, td);
|
error = fo_write(po->po_file, &auio, ownercred, 0, td);
|
||||||
td->td_ucred = mycred;
|
td->td_ucred = mycred;
|
||||||
|
|
||||||
mtx_lock(&pmc_kthread_mtx);
|
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
/* XXX some errors are recoverable */
|
/* XXX some errors are recoverable */
|
||||||
/* XXX also check for SIGPIPE if a socket */
|
/* XXX also check for SIGPIPE if a socket */
|
||||||
|
|
||||||
/* send a SIGIO to the owner and exit */
|
/* send a SIGIO to the owner and exit */
|
||||||
PROC_LOCK(po->po_owner);
|
PROC_LOCK(p);
|
||||||
psignal(po->po_owner, SIGIO);
|
psignal(p, SIGIO);
|
||||||
PROC_UNLOCK(po->po_owner);
|
PROC_UNLOCK(p);
|
||||||
|
|
||||||
|
mtx_lock(&pmc_kthread_mtx);
|
||||||
|
|
||||||
po->po_error = error; /* save for flush log */
|
po->po_error = error; /* save for flush log */
|
||||||
|
|
||||||
@ -342,6 +344,8 @@ pmclog_loop(void *arg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mtx_lock(&pmc_kthread_mtx);
|
||||||
|
|
||||||
/* put the used buffer back into the global pool */
|
/* put the used buffer back into the global pool */
|
||||||
PMCLOG_INIT_BUFFER_DESCRIPTOR(lb);
|
PMCLOG_INIT_BUFFER_DESCRIPTOR(lb);
|
||||||
|
|
||||||
@ -525,15 +529,20 @@ static void
|
|||||||
pmclog_stop_kthread(struct pmc_owner *po)
|
pmclog_stop_kthread(struct pmc_owner *po)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Unset flag, wakeup the helper thread,
|
* Close the file to force the thread out of fo_write,
|
||||||
|
* unset flag, wakeup the helper thread,
|
||||||
* wait for it to exit
|
* wait for it to exit
|
||||||
*/
|
*/
|
||||||
|
|
||||||
mtx_assert(&pmc_kthread_mtx, MA_OWNED);
|
if (po->po_file != NULL)
|
||||||
|
fo_close(po->po_file, curthread);
|
||||||
|
|
||||||
|
mtx_lock(&pmc_kthread_mtx);
|
||||||
po->po_flags &= ~PMC_PO_OWNS_LOGFILE;
|
po->po_flags &= ~PMC_PO_OWNS_LOGFILE;
|
||||||
wakeup_one(po);
|
wakeup_one(po);
|
||||||
if (po->po_kthread)
|
if (po->po_kthread)
|
||||||
msleep(po->po_kthread, &pmc_kthread_mtx, PPAUSE, "pmckstp", 0);
|
msleep(po->po_kthread, &pmc_kthread_mtx, PPAUSE, "pmckstp", 0);
|
||||||
|
mtx_unlock(&pmc_kthread_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -602,10 +611,8 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
|
|||||||
|
|
||||||
error:
|
error:
|
||||||
/* shutdown the thread */
|
/* shutdown the thread */
|
||||||
mtx_lock(&pmc_kthread_mtx);
|
|
||||||
if (po->po_kthread)
|
if (po->po_kthread)
|
||||||
pmclog_stop_kthread(po);
|
pmclog_stop_kthread(po);
|
||||||
mtx_unlock(&pmc_kthread_mtx);
|
|
||||||
|
|
||||||
KASSERT(po->po_kthread == NULL, ("[pmclog,%d] po=%p kthread not "
|
KASSERT(po->po_kthread == NULL, ("[pmclog,%d] po=%p kthread not "
|
||||||
"stopped", __LINE__, po));
|
"stopped", __LINE__, po));
|
||||||
@ -641,10 +648,8 @@ pmclog_deconfigure_log(struct pmc_owner *po)
|
|||||||
("[pmclog,%d] po=%p no log file", __LINE__, po));
|
("[pmclog,%d] po=%p no log file", __LINE__, po));
|
||||||
|
|
||||||
/* stop the kthread, this will reset the 'OWNS_LOGFILE' flag */
|
/* stop the kthread, this will reset the 'OWNS_LOGFILE' flag */
|
||||||
mtx_lock(&pmc_kthread_mtx);
|
|
||||||
if (po->po_kthread)
|
if (po->po_kthread)
|
||||||
pmclog_stop_kthread(po);
|
pmclog_stop_kthread(po);
|
||||||
mtx_unlock(&pmc_kthread_mtx);
|
|
||||||
|
|
||||||
KASSERT(po->po_kthread == NULL,
|
KASSERT(po->po_kthread == NULL,
|
||||||
("[pmclog,%d] po=%p kthread not stopped", __LINE__, po));
|
("[pmclog,%d] po=%p kthread not stopped", __LINE__, po));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user