summaryrefslogtreecommitdiffstats
path: root/sys/dev/hwpmc
diff options
context:
space:
mode:
authorfabient <fabient@FreeBSD.org>2010-03-08 19:58:00 +0000
committerfabient <fabient@FreeBSD.org>2010-03-08 19:58:00 +0000
commita8460cce17ebabfbca0131c6e1a00738d1277dc7 (patch)
tree0cc70dab8769706eb374fbf5208b3ab358ac46c6 /sys/dev/hwpmc
parent2adbaaffe49e189520bb04b4737cc5658451b610 (diff)
downloadFreeBSD-src-a8460cce17ebabfbca0131c6e1a00738d1277dc7.zip
FreeBSD-src-a8460cce17ebabfbca0131c6e1a00738d1277dc7.tar.gz
Change the way shutdown is handled for log file.
pmc_flush_logfile is now non-blocking and just ask the kernel to shutdown the file. From that point, no more data is accepted by the log thread and when the last buffer is flushed the file is closed. This will remove a deadlock between pmcstat asking for flush while it cannot flush the pipe itself. MFC after: 3 days
Diffstat (limited to 'sys/dev/hwpmc')
-rw-r--r--sys/dev/hwpmc/hwpmc_logging.c48
1 files changed, 27 insertions, 21 deletions
diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c
index a36a8dc..055433d 100644
--- a/sys/dev/hwpmc/hwpmc_logging.c
+++ b/sys/dev/hwpmc/hwpmc_logging.c
@@ -237,7 +237,7 @@ pmclog_get_buffer(struct pmc_owner *po)
static void
pmclog_loop(void *arg)
{
- int error;
+ int error, last_buffer;
struct pmc_owner *po;
struct pmclog_buffer *lb;
struct proc *p;
@@ -252,6 +252,7 @@ pmclog_loop(void *arg)
p = po->po_owner;
td = curthread;
mycred = td->td_ucred;
+ last_buffer = 0;
PROC_LOCK(p);
ownercred = crhold(p->p_ucred);
@@ -284,27 +285,20 @@ pmclog_loop(void *arg)
if ((lb = TAILQ_FIRST(&po->po_logbuffers)) == NULL) {
mtx_unlock_spin(&po->po_mtx);
- /*
- * Wakeup the thread waiting for the
- * PMC_OP_FLUSHLOG request to
- * complete.
- */
- if (po->po_flags & PMC_PO_IN_FLUSH) {
- po->po_flags &= ~PMC_PO_IN_FLUSH;
- wakeup_one(po->po_kthread);
- }
-
(void) msleep(po, &pmc_kthread_mtx, PWAIT,
"pmcloop", 0);
continue;
}
TAILQ_REMOVE(&po->po_logbuffers, lb, plb_next);
+ if (po->po_flags & PMC_PO_SHUTDOWN)
+ last_buffer = TAILQ_EMPTY(&po->po_logbuffers);
mtx_unlock_spin(&po->po_mtx);
}
mtx_unlock(&pmc_kthread_mtx);
+sigpipe_retry:
/* process the request */
PMCDBG(LOG,WRI,2, "po=%p base=%p ptr=%p", po,
lb->plb_base, lb->plb_ptr);
@@ -328,7 +322,8 @@ pmclog_loop(void *arg)
if (error) {
/* XXX some errors are recoverable */
- /* XXX also check for SIGPIPE if a socket */
+ if (error == EPIPE)
+ goto sigpipe_retry;
/* send a SIGIO to the owner and exit */
PROC_LOCK(p);
@@ -344,6 +339,14 @@ pmclog_loop(void *arg)
break;
}
+ if (last_buffer) {
+ /*
+ * Close the file to get PMCLOG_EOF error
+ * in pmclog(3).
+ */
+ fo_close(po->po_file, curthread);
+ }
+
mtx_lock(&pmc_kthread_mtx);
/* put the used buffer back into the global pool */
@@ -425,6 +428,12 @@ pmclog_reserve(struct pmc_owner *po, int length)
mtx_lock_spin(&po->po_mtx);
+ /* No more data when shutdown in progress. */
+ if (po->po_flags & PMC_PO_SHUTDOWN) {
+ mtx_unlock_spin(&po->po_mtx);
+ return (NULL);
+ }
+
if (po->po_curbuf == NULL)
if (pmclog_get_buffer(po) != 0) {
mtx_unlock_spin(&po->po_mtx);
@@ -686,7 +695,7 @@ pmclog_deconfigure_log(struct pmc_owner *po)
int
pmclog_flush(struct pmc_owner *po)
{
- int error, has_pending_buffers;
+ int error;
PMCDBG(LOG,FLS,1, "po=%p", po);
@@ -714,16 +723,13 @@ pmclog_flush(struct pmc_owner *po)
mtx_lock_spin(&po->po_mtx);
if (po->po_curbuf)
pmclog_schedule_io(po);
- has_pending_buffers = !TAILQ_EMPTY(&po->po_logbuffers);
mtx_unlock_spin(&po->po_mtx);
- if (has_pending_buffers) {
- po->po_flags |= PMC_PO_IN_FLUSH; /* ask for a wakeup */
- error = msleep(po->po_kthread, &pmc_kthread_mtx, PWAIT,
- "pmcflush", 0);
- if (error == 0)
- error = po->po_error;
- }
+ /*
+ * Initiate shutdown: no new data queued,
+ * thread will close file on last block.
+ */
+ po->po_flags |= PMC_PO_SHUTDOWN;
error:
mtx_unlock(&pmc_kthread_mtx);
OpenPOWER on IntegriCloud