summaryrefslogtreecommitdiffstats
path: root/sys/dev/hwpmc
diff options
context:
space:
mode:
authorfabient <fabient@FreeBSD.org>2011-10-18 15:25:43 +0000
committerfabient <fabient@FreeBSD.org>2011-10-18 15:25:43 +0000
commitc0da433b0a908c85fe0547ba8054795948e39d30 (patch)
tree3965b86bd8e0e5d008fd4219e7d38fa2351bfcac /sys/dev/hwpmc
parent9e1982ba8eaabe131f148406f3f2819d8e0e1563 (diff)
downloadFreeBSD-src-c0da433b0a908c85fe0547ba8054795948e39d30.zip
FreeBSD-src-c0da433b0a908c85fe0547ba8054795948e39d30.tar.gz
Add a flush of the current PMC log buffer before displaying the next top.
As the underlying block is 4KB if the PMC throughput is low the measurement will be reported on the next tick. pmcstat(8) use the modified flush API to reclaim current buffer before displaying next top. MFC after: 1 month
Diffstat (limited to 'sys/dev/hwpmc')
-rw-r--r--sys/dev/hwpmc/hwpmc_logging.c57
-rw-r--r--sys/dev/hwpmc/hwpmc_mod.c22
2 files changed, 61 insertions, 18 deletions
diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c
index c0f8b0d..5f5cd90 100644
--- a/sys/dev/hwpmc/hwpmc_logging.c
+++ b/sys/dev/hwpmc/hwpmc_logging.c
@@ -238,7 +238,7 @@ pmclog_get_buffer(struct pmc_owner *po)
static void
pmclog_loop(void *arg)
{
- int error, last_buffer;
+ int error;
struct pmc_owner *po;
struct pmclog_buffer *lb;
struct proc *p;
@@ -253,7 +253,6 @@ 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);
@@ -286,14 +285,22 @@ pmclog_loop(void *arg)
if ((lb = TAILQ_FIRST(&po->po_logbuffers)) == NULL) {
mtx_unlock_spin(&po->po_mtx);
+ if (po->po_flags & PMC_PO_SHUTDOWN) {
+ mtx_unlock(&pmc_kthread_mtx);
+ /*
+ * Close the file to get PMCLOG_EOF
+ * error in pmclog(3).
+ */
+ fo_close(po->po_file, curthread);
+ mtx_lock(&pmc_kthread_mtx);
+ }
+
(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);
}
@@ -336,14 +343,6 @@ 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 */
@@ -693,6 +692,7 @@ int
pmclog_flush(struct pmc_owner *po)
{
int error;
+ struct pmclog_buffer *lb;
PMCDBG(LOG,FLS,1, "po=%p", po);
@@ -715,11 +715,38 @@ pmclog_flush(struct pmc_owner *po)
}
/*
- * Schedule the current buffer if any.
+ * Schedule the current buffer if any and not empty.
+ */
+ mtx_lock_spin(&po->po_mtx);
+ lb = po->po_curbuf;
+ if (lb && lb->plb_ptr != lb->plb_base) {
+ pmclog_schedule_io(po);
+ } else
+ error = ENOBUFS;
+ mtx_unlock_spin(&po->po_mtx);
+
+ error:
+ mtx_unlock(&pmc_kthread_mtx);
+
+ return (error);
+}
+
+int
+pmclog_close(struct pmc_owner *po)
+{
+
+ PMCDBG(LOG,CLO,1, "po=%p", po);
+
+ mtx_lock(&pmc_kthread_mtx);
+
+ /*
+ * Schedule the current buffer.
*/
mtx_lock_spin(&po->po_mtx);
if (po->po_curbuf)
pmclog_schedule_io(po);
+ else
+ wakeup_one(po);
mtx_unlock_spin(&po->po_mtx);
/*
@@ -728,13 +755,11 @@ pmclog_flush(struct pmc_owner *po)
*/
po->po_flags |= PMC_PO_SHUTDOWN;
- error:
mtx_unlock(&pmc_kthread_mtx);
- return (error);
+ return (0);
}
-
void
pmclog_process_callchain(struct pmc *pm, struct pmc_sample *ps)
{
diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c
index fc82908..7ca7a47 100644
--- a/sys/dev/hwpmc/hwpmc_mod.c
+++ b/sys/dev/hwpmc/hwpmc_mod.c
@@ -2891,7 +2891,7 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
error = pmclog_configure_log(md, po, cl.pm_logfd);
} else if (po->po_flags & PMC_PO_OWNS_LOGFILE) {
pmclog_process_closelog(po);
- error = pmclog_flush(po);
+ error = pmclog_close(po);
if (error == 0) {
LIST_FOREACH(pm, &po->po_pmcs, pm_next)
if (pm->pm_flags & PMC_F_NEEDS_LOGFILE &&
@@ -2907,7 +2907,6 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
}
break;
-
/*
* Flush a log file.
*/
@@ -2928,6 +2927,25 @@ pmc_syscall_handler(struct thread *td, void *syscall_args)
break;
/*
+ * Close a log file.
+ */
+
+ case PMC_OP_CLOSELOG:
+ {
+ struct pmc_owner *po;
+
+ sx_assert(&pmc_sx, SX_XLOCKED);
+
+ if ((po = pmc_find_owner_descriptor(td->td_proc)) == NULL) {
+ error = EINVAL;
+ break;
+ }
+
+ error = pmclog_close(po);
+ }
+ break;
+
+ /*
* Retrieve hardware configuration.
*/
OpenPOWER on IntegriCloud