Author: mmacy
Date: Wed Jun  6 02:48:09 2018
New Revision: 334701
URL: https://svnweb.freebsd.org/changeset/base/334701

Log:
  hwpmc: add summary command and further metadata extensions
  
  metadata changes:
  - log pmc sample rate with pmcallocate
  - log proc flags with thread / process logging
    to identify user vs kernel threads
  
  fixes:
  - use log cpuid to translate event id to event name
  
  Implement rudimentary summary command to track sample
  counts by thread and process name within a pmc log.
  
  % make -j4 buildkernel >& /dev/null &
  % sudo pmcstat -S unhalted_core_cycles -S llc-misses -O foo sleep 15
  % pmc summary foo
  cpu_clk_unhalted.thread_p_any:
          idle: 138108207162
          clang-6.0: 105336158004
          sh: 72340108510
          make: 8642012963
          kernel: 7754011631
  longest_lat_cache.miss:
          clang-6.0: 87502625
          sh: 40901227
          make: 5500165
          kernel: 3300099
          awk: 2000060
  
  %  pmc summary -f ~/foo
  idx: 278 name: cpu_clk_unhalted.thread_p_any rate: 2000003
  idle: 69054
  clang-6.0: 52668
  sh: 36170
  make: 4321
  kernel: 3877
  hwpmc: proc(7445): 3319
  awk: 1289
  xargs: 357
  rand_harvestq: 181
  mtree: 102
  intr: 53
  zfskern: 31
  usb: 7
  pagedaemon: 4
  ntpd: 3
  syslogd: 1
  acpi_thermal: 1
  logger: 1
  syncer: 1
  snmptrapd: 1
  sleep: 1
  idx: 17 name: longest_lat_cache.miss rate: 100003
  clang-6.0: 875
  sh: 409
  make: 55
  kernel: 33
  awk: 20
  hwpmc: proc(7445): 14
  xargs: 9
  idle: 8
  intr: 3
  zfskern: 2

Added:
  head/usr.sbin/pmc/cmd_pmc_summary.cc   (contents, props changed)
Modified:
  head/lib/libpmc/libpmc.c
  head/lib/libpmc/libpmc_pmu_util.c   (contents, props changed)
  head/lib/libpmc/pmc.h
  head/lib/libpmc/pmclog.c
  head/lib/libpmc/pmclog.h
  head/share/examples/hwpmc/overhead.c
  head/sys/dev/hwpmc/hwpmc_logging.c
  head/sys/dev/hwpmc/hwpmc_mod.c
  head/sys/sys/pmc.h
  head/sys/sys/pmclog.h
  head/usr.sbin/pmc/Makefile   (contents, props changed)
  head/usr.sbin/pmc/cmd_pmc.h   (contents, props changed)
  head/usr.sbin/pmc/cmd_pmc_filter.cc
  head/usr.sbin/pmc/cmd_pmc_stat.c   (contents, props changed)
  head/usr.sbin/pmc/pmc.c   (contents, props changed)
  head/usr.sbin/pmcstat/pmcstat.c

Modified: head/lib/libpmc/libpmc.c
==============================================================================
--- head/lib/libpmc/libpmc.c    Wed Jun  6 01:51:05 2018        (r334700)
+++ head/lib/libpmc/libpmc.c    Wed Jun  6 02:48:09 2018        (r334701)
@@ -1007,7 +1007,8 @@ pmc_mdep_is_compatible_class(enum pmc_class pc)
 
 int
 pmc_allocate(const char *ctrspec, enum pmc_mode mode,
-    uint32_t flags, int cpu, pmc_id_t *pmcid)
+    uint32_t flags, int cpu, pmc_id_t *pmcid,
+    uint64_t count)
 {
        size_t n;
        int retval;
@@ -1030,6 +1031,7 @@ pmc_allocate(const char *ctrspec, enum pmc_mode mode,
        pmc_config.pm_cpu   = cpu;
        pmc_config.pm_mode  = mode;
        pmc_config.pm_flags = flags;
+       pmc_config.pm_count = count;
        if (PMC_IS_SAMPLING_MODE(mode))
                pmc_config.pm_caps |= PMC_CAP_INTERRUPT;
        /*

Modified: head/lib/libpmc/libpmc_pmu_util.c
==============================================================================
--- head/lib/libpmc/libpmc_pmu_util.c   Wed Jun  6 01:51:05 2018        
(r334700)
+++ head/lib/libpmc/libpmc_pmu_util.c   Wed Jun  6 02:48:09 2018        
(r334701)
@@ -162,13 +162,13 @@ pmc_pmu_idx_get_by_event(const char *cpuid, const char
 }
 
 const char *
-pmc_pmu_event_get_by_idx(int idx)
+pmc_pmu_event_get_by_idx(const char *cpuid, int idx)
 {
        const struct pmu_events_map *pme;
        const struct pmu_event *pe;
        int i;
 
-       if ((pme = pmu_events_map_get(NULL)) == NULL)
+       if ((pme = pmu_events_map_get(cpuid)) == NULL)
                return (NULL);
        for (i = 0, pe = pme->table; (pe->name || pe->desc || pe->event) && i < 
idx; pe++, i++);
        return (pe->name);
@@ -470,7 +470,7 @@ pmc_pmu_pmcallocate(const char *e __unused, struct pmc
 }
 
 const char *
-pmc_pmu_event_get_by_idx(int idx __unused)
+pmc_pmu_event_get_by_idx(const char *c __unused, int idx __unused)
 {
        return (NULL);
 }

Modified: head/lib/libpmc/pmc.h
==============================================================================
--- head/lib/libpmc/pmc.h       Wed Jun  6 01:51:05 2018        (r334700)
+++ head/lib/libpmc/pmc.h       Wed Jun  6 02:48:09 2018        (r334701)
@@ -75,7 +75,7 @@ struct pmc_pmcinfo {
 
 __BEGIN_DECLS
 int    pmc_allocate(const char *_ctrspec, enum pmc_mode _mode, uint32_t _flags,
-    int _cpu, pmc_id_t *_pmcid);
+    int _cpu, pmc_id_t *_pmcid, uint64_t count);
 int    pmc_attach(pmc_id_t _pmcid, pid_t _pid);
 int    pmc_capabilities(pmc_id_t _pmc, uint32_t *_caps);
 int    pmc_configure_logfile(int _fd);
@@ -120,7 +120,7 @@ void pmc_pmu_print_counter_desc_long(const char *);
 void pmc_pmu_print_counter_full(const char *);
 uint64_t pmc_pmu_sample_rate_get(const char *);
 int pmc_pmu_pmcallocate(const char *, struct pmc_op_pmcallocate *);
-const char *pmc_pmu_event_get_by_idx(int idx);
+const char *pmc_pmu_event_get_by_idx(const char *, int idx);
 int pmc_pmu_idx_get_by_event(const char*, const char *);
 int pmc_pmu_stat_mode(const char ***);
 __END_DECLS

Modified: head/lib/libpmc/pmclog.c
==============================================================================
--- head/lib/libpmc/pmclog.c    Wed Jun  6 01:51:05 2018        (r334700)
+++ head/lib/libpmc/pmclog.c    Wed Jun  6 02:48:09 2018        (r334701)
@@ -328,6 +328,7 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
                PMCLOG_READ32(le,ev->pl_u.pl_i.pl_arch);
                PMCLOG_READSTRING(le, ev->pl_u.pl_i.pl_cpuid, PMC_CPUID_LEN);
                memcpy(ev->pl_u.pl_i.pl_cpuid, le, PMC_CPUID_LEN);
+               ps->ps_cpuid = strdup(ev->pl_u.pl_i.pl_cpuid);
                ps->ps_version = ev->pl_u.pl_i.pl_version;
                ps->ps_arch = ev->pl_u.pl_i.pl_arch;
                ps->ps_initialized = 1;
@@ -347,8 +348,8 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
                PMCLOG_READ32(le,ev->pl_u.pl_a.pl_pmcid);
                PMCLOG_READ32(le,ev->pl_u.pl_a.pl_event);
                PMCLOG_READ32(le,ev->pl_u.pl_a.pl_flags);
-               PMCLOG_READ32(le,noop);
-               ev->pl_u.pl_a.pl_evname = 
pmc_pmu_event_get_by_idx(ev->pl_u.pl_a.pl_event);
+               PMCLOG_READ64(le,ev->pl_u.pl_a.pl_rate);
+               ev->pl_u.pl_a.pl_evname = 
pmc_pmu_event_get_by_idx(ps->ps_cpuid, ev->pl_u.pl_a.pl_event);
                if (ev->pl_u.pl_a.pl_evname != NULL)
                        break;
                else if ((ev->pl_u.pl_a.pl_evname =
@@ -407,7 +408,7 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
        case PMCLOG_TYPE_THR_CREATE:
                PMCLOG_READ32(le,ev->pl_u.pl_tc.pl_tid);
                PMCLOG_READ32(le,ev->pl_u.pl_tc.pl_pid);
-               PMCLOG_READ32(le,noop);
+               PMCLOG_READ32(le,ev->pl_u.pl_tc.pl_flags);
                memcpy(ev->pl_u.pl_tc.pl_tdname, le, MAXCOMLEN+1);
                break;
        case PMCLOG_TYPE_THR_EXIT:
@@ -415,6 +416,8 @@ pmclog_get_event(void *cookie, char **data, ssize_t *l
                break;
        case PMCLOG_TYPE_PROC_CREATE:
                PMCLOG_READ32(le,ev->pl_u.pl_pc.pl_pid);
+               PMCLOG_READ32(le,ev->pl_u.pl_pc.pl_flags);
+               PMCLOG_READ32(le,noop);
                memcpy(ev->pl_u.pl_pc.pl_pcomm, le, MAXCOMLEN+1);
                break;
        default:        /* unknown record type */
@@ -553,6 +556,7 @@ pmclog_open(int fd)
        ps->ps_count = 0;
        ps->ps_offset = (off_t) 0;
        bzero(&ps->ps_saved, sizeof(ps->ps_saved));
+       ps->ps_cpuid = NULL;
        ps->ps_svcount = 0;
        ps->ps_fd    = fd;
        ps->ps_data  = NULL;

Modified: head/lib/libpmc/pmclog.h
==============================================================================
--- head/lib/libpmc/pmclog.h    Wed Jun  6 01:51:05 2018        (r334700)
+++ head/lib/libpmc/pmclog.h    Wed Jun  6 02:48:09 2018        (r334701)
@@ -89,15 +89,16 @@ struct pmclog_ev_pcsample {
 };
 
 struct pmclog_ev_pmcallocate {
-       uint32_t        pl_event;
        const char *    pl_evname;
+       uint64_t        pl_rate;
+       uint32_t        pl_event;
        uint32_t        pl_flags;
        pmc_id_t        pl_pmcid;
 };
 
 struct pmclog_ev_pmcallocatedyn {
-       uint32_t        pl_event;
        char            pl_evname[PMC_NAME_MAX];
+       uint32_t        pl_event;
        uint32_t        pl_flags;
        pmc_id_t        pl_pmcid;
 };
@@ -122,6 +123,7 @@ struct pmclog_ev_proccsw {
 
 struct pmclog_ev_proccreate {
        pid_t           pl_pid;
+       uint32_t        pl_flags;
        char            pl_pcomm[MAXCOMLEN+1];
 };
 
@@ -150,6 +152,7 @@ struct pmclog_ev_sysexit {
 struct pmclog_ev_threadcreate {
        pid_t           pl_tid;
        pid_t           pl_pid;
+       uint32_t        pl_flags;
        char            pl_tdname[MAXCOMLEN+1];
 };
 
@@ -211,6 +214,7 @@ struct pmclog_parse_state {
        int                     ps_fd;          /* active fd or -1 */
        char                    *ps_buffer;     /* scratch buffer if fd != -1 */
        char                    *ps_data;       /* current parse pointer */
+       char                    *ps_cpuid;      /* log cpuid */
        size_t                  ps_len;         /* length of buffered data */
 };
 

Modified: head/share/examples/hwpmc/overhead.c
==============================================================================
--- head/share/examples/hwpmc/overhead.c        Wed Jun  6 01:51:05 2018        
(r334700)
+++ head/share/examples/hwpmc/overhead.c        Wed Jun  6 02:48:09 2018        
(r334701)
@@ -65,7 +65,7 @@ main(int argc, char **argv)
        if (pmc_init() != 0)
                err(EX_OSERR, "hwpmc(4) not loaded, kldload or update your 
kernel");
 
-       if (pmc_allocate(counter_name, PMC_MODE_SC, 0, 0, &pmcid) < 0)
+       if (pmc_allocate(counter_name, PMC_MODE_SC, 0, 0, &pmcid, 64*1024) < 0)
                err(EX_OSERR, "failed to allocate %s as a system counter in 
counting mode",
                    counter_name);
 

Modified: head/sys/dev/hwpmc/hwpmc_logging.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_logging.c  Wed Jun  6 01:51:05 2018        
(r334700)
+++ head/sys/dev/hwpmc/hwpmc_logging.c  Wed Jun  6 02:48:09 2018        
(r334701)
@@ -194,7 +194,7 @@ CTASSERT(sizeof(struct pmclog_map_in) == PATH_MAX +
 CTASSERT(offsetof(struct pmclog_map_in,pl_pathname) ==
     4*4 + sizeof(uintfptr_t));
 CTASSERT(sizeof(struct pmclog_map_out) == 4*4 + 2*sizeof(uintfptr_t));
-CTASSERT(sizeof(struct pmclog_pmcallocate) == 6*4);
+CTASSERT(sizeof(struct pmclog_pmcallocate) == 8*4);
 CTASSERT(sizeof(struct pmclog_pmcattach) == 6*4 + PATH_MAX);
 CTASSERT(offsetof(struct pmclog_pmcattach,pl_pathname) == 6*4);
 CTASSERT(sizeof(struct pmclog_pmcdetach) == 6*4);
@@ -991,6 +991,7 @@ pmclog_process_pmcallocate(struct pmc *pm)
                PMCLOG_EMIT32(pm->pm_id);
                PMCLOG_EMIT32(pm->pm_event);
                PMCLOG_EMIT32(pm->pm_flags);
+               PMCLOG_EMIT64(pm->pm_sc.pm_reloadcount);
                ps = pmc_soft_ev_acquire(pm->pm_event);
                if (ps != NULL)
                        PMCLOG_EMITSTRING(ps->ps_ev.pm_ev_name,PMC_NAME_MAX);
@@ -1004,6 +1005,7 @@ pmclog_process_pmcallocate(struct pmc *pm)
                PMCLOG_EMIT32(pm->pm_id);
                PMCLOG_EMIT32(pm->pm_event);
                PMCLOG_EMIT32(pm->pm_flags);
+               PMCLOG_EMIT64(pm->pm_sc.pm_reloadcount);
                PMCLOG_DESPATCH_SYNC(po);
        }
 }
@@ -1050,11 +1052,15 @@ pmclog_process_proccreate(struct pmc_owner *po, struct
        if (sync) {
                PMCLOG_RESERVE(po, PROC_CREATE, sizeof(struct 
pmclog_proccreate));
                PMCLOG_EMIT32(p->p_pid);
+               PMCLOG_EMIT32(p->p_flag);
+               PMCLOG_EMIT32(0);
                PMCLOG_EMITSTRING(p->p_comm, MAXCOMLEN+1);
                PMCLOG_DESPATCH_SYNC(po);
        } else {
                PMCLOG_RESERVE(po, PROC_CREATE, sizeof(struct 
pmclog_proccreate));
                PMCLOG_EMIT32(p->p_pid);
+               PMCLOG_EMIT32(p->p_flag);
+               PMCLOG_EMIT32(0);
                PMCLOG_EMITSTRING(p->p_comm, MAXCOMLEN+1);
                PMCLOG_DESPATCH(po);
        }
@@ -1163,14 +1169,14 @@ pmclog_process_threadcreate(struct pmc_owner *po, stru
                PMCLOG_RESERVE(po, THR_CREATE, sizeof(struct 
pmclog_threadcreate));
                PMCLOG_EMIT32(td->td_tid);
                PMCLOG_EMIT32(p->p_pid);
-               PMCLOG_EMIT32(0);
+               PMCLOG_EMIT32(p->p_flag);
                PMCLOG_EMITSTRING(td->td_name, MAXCOMLEN+1);
                PMCLOG_DESPATCH_SYNC(po);
        } else {
                PMCLOG_RESERVE(po, THR_CREATE, sizeof(struct 
pmclog_threadcreate));
                PMCLOG_EMIT32(td->td_tid);
                PMCLOG_EMIT32(p->p_pid);
-               PMCLOG_EMIT32(0);
+               PMCLOG_EMIT32(p->p_flag);
                PMCLOG_EMITSTRING(td->td_name, MAXCOMLEN+1);
                PMCLOG_DESPATCH(po);
        }

Modified: head/sys/dev/hwpmc/hwpmc_mod.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_mod.c      Wed Jun  6 01:51:05 2018        
(r334700)
+++ head/sys/dev/hwpmc/hwpmc_mod.c      Wed Jun  6 02:48:09 2018        
(r334701)
@@ -3925,6 +3925,12 @@ pmc_syscall_handler(struct thread *td, void *syscall_a
                pmc->pm_caps  = caps;
                pmc->pm_flags = pa.pm_flags;
 
+               /* XXX set lower bound on sampling for process counters */
+               if (PMC_IS_SAMPLING_MODE(mode))
+                       pmc->pm_sc.pm_reloadcount = pa.pm_count;
+               else
+                       pmc->pm_sc.pm_initial = pa.pm_count;
+
                /* switch thread to CPU 'cpu' */
                pmc_save_cpu_binding(&pb);
 

Modified: head/sys/sys/pmc.h
==============================================================================
--- head/sys/sys/pmc.h  Wed Jun  6 01:51:05 2018        (r334700)
+++ head/sys/sys/pmc.h  Wed Jun  6 02:48:09 2018        (r334701)
@@ -61,8 +61,8 @@
  *
  * The patch version is incremented for every bug fix.
  */
-#define        PMC_VERSION_MAJOR       0x06
-#define        PMC_VERSION_MINOR       0x02
+#define        PMC_VERSION_MAJOR       0x07
+#define        PMC_VERSION_MINOR       0x03
 #define        PMC_VERSION_PATCH       0x0000
 
 #define        PMC_VERSION             (PMC_VERSION_MAJOR << 24 |              
\
@@ -439,6 +439,7 @@ struct pmc_op_pmcallocate {
        uint32_t        pm_flags;       /* additional modifiers PMC_F_* */
        enum pmc_mode   pm_mode;        /* desired mode */
        pmc_id_t        pm_pmcid;       /* [return] process pmc id */
+       pmc_value_t     pm_count;       /* initial/sample count */
 
        union pmc_md_op_pmcallocate pm_md; /* MD layer extensions */
 };

Modified: head/sys/sys/pmclog.h
==============================================================================
--- head/sys/sys/pmclog.h       Wed Jun  6 01:51:05 2018        (r334700)
+++ head/sys/sys/pmclog.h       Wed Jun  6 02:48:09 2018        (r334701)
@@ -162,6 +162,7 @@ struct pmclog_pmcallocate {
        uint32_t                pl_pmcid;
        uint32_t                pl_event;
        uint32_t                pl_flags;
+       uint64_t                pl_rate;
 } __packed;
 
 struct pmclog_pmcattach {
@@ -190,6 +191,8 @@ struct pmclog_proccsw {
 struct pmclog_proccreate {
        PMCLOG_ENTRY_HEADER
        uint32_t                pl_pid;
+       uint32_t                pl_flags;
+       uint32_t                pl_pad;
        uint64_t                pl_pcomm[MAXCOMLEN+1];  /* keep 8 byte aligned 
*/
 } __packed;
 
@@ -226,7 +229,7 @@ struct pmclog_threadcreate {
        PMCLOG_ENTRY_HEADER
        uint32_t                pl_tid;
        uint32_t                pl_pid;
-       uint32_t                pl_pad;
+       uint32_t                pl_flags;
        uint64_t                pl_tdname[MAXCOMLEN+1]; /* keep 8 byte aligned 
*/
 } __packed;
 

Modified: head/usr.sbin/pmc/Makefile
==============================================================================
--- head/usr.sbin/pmc/Makefile  Wed Jun  6 01:51:05 2018        (r334700)
+++ head/usr.sbin/pmc/Makefile  Wed Jun  6 02:48:09 2018        (r334701)
@@ -5,11 +5,12 @@
 .include <src.opts.mk>
 PROG_CXX=      pmc
 MAN=   
-CXXFLAGS+= -O0
+CXXFLAGS+=
 
 LIBADD=        kvm pmc m ncursesw pmcstat elf
 
 SRCS=  pmc.c pmc_util.c cmd_pmc_stat.c \
-       cmd_pmc_list.c cmd_pmc_filter.cc
+       cmd_pmc_list.c cmd_pmc_filter.cc \
+       cmd_pmc_summary.cc
 
 .include <bsd.prog.mk>

Modified: head/usr.sbin/pmc/cmd_pmc.h
==============================================================================
--- head/usr.sbin/pmc/cmd_pmc.h Wed Jun  6 01:51:05 2018        (r334700)
+++ head/usr.sbin/pmc/cmd_pmc.h Wed Jun  6 02:48:09 2018        (r334701)
@@ -47,6 +47,7 @@ extern "C" {
        int     cmd_pmc_filter(int, char **);
        int     cmd_pmc_stat_system(int, char **);
        int     cmd_pmc_list_events(int, char **);
+       int     cmd_pmc_summary(int, char **);
 #if defined(__cplusplus)
 };
 #endif

Modified: head/usr.sbin/pmc/cmd_pmc_filter.cc
==============================================================================
--- head/usr.sbin/pmc/cmd_pmc_filter.cc Wed Jun  6 01:51:05 2018        
(r334700)
+++ head/usr.sbin/pmc/cmd_pmc_filter.cc Wed Jun  6 02:48:09 2018        
(r334701)
@@ -70,13 +70,12 @@ __FBSDID("$FreeBSD$");
 
 #include <iostream>
 #include <string>
-#if _LIBCPP_STD_VER >= 11
 #include <unordered_map>
+
 using  std::unordered_map;
-#else
-#include <tr1/unordered_map>
-using  std::tr1::unordered_map;
-#endif
+typedef unordered_map <int, std::string> idmap;
+typedef std::pair <int, std::string> identry;
+
 #define LIST_MAX 64
 static struct option longopts[] = {
        {"lwps", required_argument, NULL, 't'},
@@ -158,10 +157,6 @@ struct pmcid_ent {
         (PMCLOG_TYPE_ ## T << 16)   |                                  \
         ((L) & 0xFFFF))
 
-
-typedef unordered_map < int ,std::string > idmap;
-typedef std::pair < int ,std::string > identry;
-
 static bool
 pmc_find_name(idmap & map, uint32_t id, char *list[LIST_MAX], int count)
 {
@@ -234,9 +229,9 @@ pmc_filter_handler(uint32_t *lwplist, int lwpcount, ui
        copies = 0;
        while (pmclog_read(ps, &ev) == 0) {
                if (ev.pl_type == PMCLOG_TYPE_THR_CREATE)
-                       tidmap.insert(identry(ev.pl_u.pl_tc.pl_tid, 
ev.pl_u.pl_tc.pl_tdname));
+                       tidmap[ev.pl_u.pl_tc.pl_tid] = ev.pl_u.pl_tc.pl_tdname;
                if (ev.pl_type == PMCLOG_TYPE_PROC_CREATE)
-                       pidmap.insert(identry(ev.pl_u.pl_pc.pl_pid, 
ev.pl_u.pl_pc.pl_pcomm));
+                       pidmap[ev.pl_u.pl_pc.pl_pid] = ev.pl_u.pl_pc.pl_pcomm;
                if (ev.pl_type != PMCLOG_TYPE_CALLCHAIN) {
                        if (write(outfd, ev.pl_data, ev.pl_len) != 
(ssize_t)ev.pl_len)
                                errx(EX_OSERR, "ERROR: failed output write");

Modified: head/usr.sbin/pmc/cmd_pmc_stat.c
==============================================================================
--- head/usr.sbin/pmc/cmd_pmc_stat.c    Wed Jun  6 01:51:05 2018        
(r334700)
+++ head/usr.sbin/pmc/cmd_pmc_stat.c    Wed Jun  6 02:48:09 2018        
(r334701)
@@ -354,7 +354,7 @@ pmc_stat_internal(int argc, char **argv, int system_mo
 
        STAILQ_FOREACH(ev, &pmc_args.pa_events, ev_next) {
                if (pmc_allocate(ev->ev_spec, ev->ev_mode,
-                   ev->ev_flags, ev->ev_cpu, &ev->ev_pmcid) < 0)
+                   ev->ev_flags, ev->ev_cpu, &ev->ev_pmcid, ev->ev_count) < 0)
                        err(EX_OSERR,
                            "ERROR: Cannot allocate %s-mode pmc with 
specification \"%s\"",
                            PMC_IS_SYSTEM_MODE(ev->ev_mode) ?

Added: head/usr.sbin/pmc/cmd_pmc_summary.cc
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/usr.sbin/pmc/cmd_pmc_summary.cc        Wed Jun  6 02:48:09 2018        
(r334701)
@@ -0,0 +1,220 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2018, Matthew Macy
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/cpuset.h>
+#include <sys/event.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/ttycom.h>
+#include <sys/user.h>
+#include <sys/wait.h>
+
+#include <assert.h>
+#include <curses.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <kvm.h>
+#include <libgen.h>
+#include <limits.h>
+#include <locale.h>
+#include <math.h>
+#include <pmc.h>
+#include <pmclog.h>
+#include <regex.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#include <libpmcstat.h>
+#include "cmd_pmc.h"
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <unordered_map>
+
+using  std::unordered_map;
+typedef unordered_map <int, std::string> idmap;
+typedef unordered_map <uint32_t, uint64_t> intmap;
+typedef unordered_map <std::string, intmap> strintmap;
+typedef std::pair<uint64_t, uint32_t> sampleid;
+typedef std::pair<uint64_t, std::string> samplename;
+typedef unordered_map <uint32_t, std::vector<samplename>> eventcountmap;
+
+#define        P_KPROC         0x00004 /* Kernel process. */
+
+static void
+usage(void)
+{
+       errx(EX_USAGE,
+           "\t summarize log file\n"
+                "\t -k <k>, --topk <k> show topk processes for each counter\n"
+           );
+}
+
+static int
+pmc_summary_handler(int logfd, int k, bool do_full)
+{
+       struct pmclog_parse_state *ps;
+       struct pmclog_ev ev;
+       idmap pidmap, tidmap, eventnamemap;
+       strintmap tideventmap, pideventmap;
+       intmap eventmap, pmcidmap, ratemap;
+       intmap kerntidmap, kernpidmap;
+       eventcountmap countmap;
+
+       ps = static_cast<struct pmclog_parse_state*>(pmclog_open(logfd));
+       if (ps == NULL)
+               errx(EX_OSERR, "ERROR: Cannot allocate pmclog parse state: 
%s\n",
+                        strerror(errno));
+       while (pmclog_read(ps, &ev) == 0) {
+               if (ev.pl_type == PMCLOG_TYPE_PMCALLOCATE) {
+                       pmcidmap[ev.pl_u.pl_a.pl_pmcid] = ev.pl_u.pl_a.pl_event;
+                       ratemap[ev.pl_u.pl_a.pl_event] = ev.pl_u.pl_a.pl_rate;
+                       eventnamemap[ev.pl_u.pl_a.pl_event] = 
ev.pl_u.pl_a.pl_evname;
+               }
+               if (ev.pl_type == PMCLOG_TYPE_THR_CREATE) {
+                       tidmap[ev.pl_u.pl_tc.pl_tid] = ev.pl_u.pl_tc.pl_tdname;
+                       kerntidmap[ev.pl_u.pl_tc.pl_tid] = 
!!(ev.pl_u.pl_tc.pl_flags & P_KPROC);
+                       if (tideventmap.find(ev.pl_u.pl_tc.pl_tdname) == 
tideventmap.end())
+                               tideventmap[ev.pl_u.pl_tc.pl_tdname] = intmap();
+               }
+               if (ev.pl_type == PMCLOG_TYPE_PROC_CREATE) {
+                       pidmap[ev.pl_u.pl_pc.pl_pid] = ev.pl_u.pl_pc.pl_pcomm;
+                       kernpidmap[ev.pl_u.pl_pc.pl_pid] = 
!!(ev.pl_u.pl_pc.pl_flags & P_KPROC);
+                       if (pideventmap.find(ev.pl_u.pl_pc.pl_pcomm) == 
pideventmap.end())
+                               pideventmap[ev.pl_u.pl_pc.pl_pcomm] = intmap();
+               }
+               if (ev.pl_type == PMCLOG_TYPE_CALLCHAIN) {
+                       auto event = pmcidmap[ev.pl_u.pl_cc.pl_pmcid];
+
+                       if (event == 0)
+                               continue;
+                       eventmap[event]++;
+                       auto tidname = tidmap.find(ev.pl_u.pl_cc.pl_tid);
+                       auto pidname = pidmap.find(ev.pl_u.pl_cc.pl_pid);
+                       if (tidname != tidmap.end()) {
+                               auto &teventmap = tideventmap[tidname->second];
+                               teventmap[event]++;
+                       }
+                       if (pidname != pidmap.end()) {
+                               auto &peventmap = pideventmap[pidname->second];
+                               peventmap[event]++;
+                       }
+               }
+       }
+       for (auto &pkv : pideventmap)
+               for (auto &ekv : pkv.second) {
+                       auto &samplevec = countmap[ekv.first];
+                       samplevec.emplace_back(ekv.second, pkv.first);
+               }
+       for (auto &kv : countmap)
+               std::sort(kv.second.begin(), kv.second.end(), [](auto &a, auto 
&b) {return (a.first < b.first);});
+       if (do_full) {
+               for (auto &kv : countmap) {
+                       auto &name = eventnamemap[kv.first];
+                       auto rate = ratemap[kv.first];
+                       std::cout << "idx: " << kv.first << " name: " << name 
<< " rate: " << rate << std::endl;
+                       while (!kv.second.empty()) {
+                               auto &val = kv.second.back();
+                               kv.second.pop_back();
+                               std::cout << val.second << ": " << val.first << 
std::endl;
+                       }
+               }
+               return (0);
+       }
+       for (auto &kv : countmap) {
+               auto &name = eventnamemap[kv.first];
+               auto rate = ratemap[kv.first];
+               std::cout << name << ":" << std::endl;
+               for (auto i = 0; i < k; i++) {
+                       auto largest = kv.second.back();
+                       kv.second.pop_back();
+                       std::cout << "\t" << largest.second << ": " << 
largest.first*rate << std::endl;
+               }
+       }
+       return (0);
+}
+
+static struct option longopts[] = {
+       {"full", no_argument, NULL, 'f'},
+       {"topk", required_argument, NULL, 'k'},
+       {NULL, 0, NULL, 0}
+};
+
+int
+cmd_pmc_summary(int argc, char **argv)
+{
+       int option, logfd, k;
+       bool do_full;
+
+       do_full = false;
+       k = 5;
+       while ((option = getopt_long(argc, argv, "k:f", longopts, NULL)) != -1) 
{
+               switch (option) {
+               case 'f':
+                       do_full = 1;
+                       break;
+               case 'k':
+                       k = atoi(optarg);
+                       break;
+               case '?':
+               default:
+                       usage();
+               }
+       }
+       argc -= optind;
+       argv += optind;
+       if (argc != 1) {
+               printf("argc: %d\n", argc);
+               for (int i = 0; i < argc; i++)
+                       printf("%s\n", argv[i]);
+               usage();
+       }
+       if ((logfd = open(argv[0], O_RDONLY,
+           S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0)
+               errx(EX_OSERR, "ERROR: Cannot open \"%s\" for reading: %s.", 
argv[0],
+                   strerror(errno));
+
+       return (pmc_summary_handler(logfd, k, do_full));
+}

Modified: head/usr.sbin/pmc/pmc.c
==============================================================================
--- head/usr.sbin/pmc/pmc.c     Wed Jun  6 01:51:05 2018        (r334700)
+++ head/usr.sbin/pmc/pmc.c     Wed Jun  6 02:48:09 2018        (r334701)
@@ -66,6 +66,7 @@ static struct cmd_handler disp_table[] = {
        {"stat-system", cmd_pmc_stat_system},
        {"list-events", cmd_pmc_list_events},
        {"filter", cmd_pmc_filter},
+       {"summary", cmd_pmc_summary},
        {NULL, NULL}
 };
 

Modified: head/usr.sbin/pmcstat/pmcstat.c
==============================================================================
--- head/usr.sbin/pmcstat/pmcstat.c     Wed Jun  6 01:51:05 2018        
(r334700)
+++ head/usr.sbin/pmcstat/pmcstat.c     Wed Jun  6 02:48:09 2018        
(r334701)
@@ -1129,7 +1129,8 @@ main(int argc, char **argv)
 
        STAILQ_FOREACH(ev, &args.pa_events, ev_next) {
                if (pmc_allocate(ev->ev_spec, ev->ev_mode,
-                   ev->ev_flags, ev->ev_cpu, &ev->ev_pmcid) < 0)
+                       ev->ev_flags, ev->ev_cpu, &ev->ev_pmcid,
+                       ev->ev_count) < 0)
                        err(EX_OSERR,
 "ERROR: Cannot allocate %s-mode pmc with specification \"%s\"",
                            PMC_IS_SYSTEM_MODE(ev->ev_mode) ?
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to