Skip to content

Commit

Permalink
Merge branch 'perf-update'
Browse files Browse the repository at this point in the history
Fix pmu read triggers to support multi-thread.

Signed-off-by: Namhyung Kim <[email protected]>
  • Loading branch information
namhyung committed Aug 20, 2019
2 parents 30d41fa + 9830d94 commit 66eb586
Show file tree
Hide file tree
Showing 6 changed files with 199 additions and 69 deletions.
8 changes: 5 additions & 3 deletions libmcount/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ struct mcount_thread_data {
struct mcount_mem_regions mem_regions;
struct mcount_watchpoint watch;
struct mcount_arch_context arch;
struct list_head pmu_fds;
};

#ifdef HAVE_MCOUNT_ARCH_CONTEXT
Expand Down Expand Up @@ -457,8 +458,9 @@ int mcount_arch_enable_event(struct mcount_event_info *mei);

void mcount_hook_functions(void);

int prepare_pmu_event(enum uftrace_event_id id);
int read_pmu_event(enum uftrace_event_id id, void *buf);
void finish_pmu_event(void);
int read_pmu_event(struct mcount_thread_data *mtdp, enum uftrace_event_id id,
void *buf);
void release_pmu_event(struct mcount_thread_data *mtdp, enum uftrace_event_id id);
void finish_pmu_event(struct mcount_thread_data *mtdp);

#endif /* UFTRACE_MCOUNT_INTERNAL_H */
29 changes: 2 additions & 27 deletions libmcount/mcount.c
Original file line number Diff line number Diff line change
Expand Up @@ -116,30 +116,6 @@ static void mcount_filter_finish(void)

#else

static void prepare_pmu_trigger(struct rb_root *root)
{
struct rb_node *node = rb_first(root);
struct uftrace_filter *entry;

while (node) {
entry = rb_entry(node, typeof(*entry), node);

if (entry->trigger.flags & TRIGGER_FL_READ) {
if (entry->trigger.read & TRIGGER_READ_PMU_CYCLE)
if (prepare_pmu_event(EVENT_ID_READ_PMU_CYCLE) < 0)
break;
if (entry->trigger.read & TRIGGER_READ_PMU_CACHE)
if (prepare_pmu_event(EVENT_ID_READ_PMU_CACHE) < 0)
break;
if (entry->trigger.read & TRIGGER_READ_PMU_BRANCH)
if (prepare_pmu_event(EVENT_ID_READ_PMU_BRANCH) < 0)
break;
}

node = rb_next(node);
}
}

/* be careful: this can be called from signal handler */
static void mcount_finish_trigger(void)
{
Expand Down Expand Up @@ -473,8 +449,6 @@ static void mcount_filter_init(enum uftrace_pattern_type ptype, char *dirname,

if (getenv("UFTRACE_DISABLED"))
mcount_enabled = false;

prepare_pmu_trigger(&mcount_triggers);
}

static void mcount_filter_setup(struct mcount_thread_data *mtdp)
Expand All @@ -483,12 +457,14 @@ static void mcount_filter_setup(struct mcount_thread_data *mtdp)
mtdp->filter.time = mcount_threshold;
mtdp->enable_cached = mcount_enabled;
mtdp->argbuf = xmalloc(mcount_rstack_max * ARGBUF_SIZE);
INIT_LIST_HEAD(&mtdp->pmu_fds);
}

static void mcount_filter_release(struct mcount_thread_data *mtdp)
{
free(mtdp->argbuf);
mtdp->argbuf = NULL;
finish_pmu_event(mtdp);
}

static void mcount_filter_finish(void)
Expand All @@ -498,7 +474,6 @@ static void mcount_filter_finish(void)

finish_debug_info(&symtabs);

finish_pmu_event();
mcount_signal_finish();
}

Expand Down
70 changes: 48 additions & 22 deletions libmcount/pmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@ struct pmu_data {
struct list_head list;
enum uftrace_event_id evt_id;
int n_members;
int refcnt;
int fd[];
};

/* list of pmu_data */
static LIST_HEAD(pmu_fds);

/* attribute for perf_event_open(2) */
struct pmu_config {
uint32_t type;
Expand Down Expand Up @@ -86,16 +84,19 @@ static void read_perf_event(int fd, void *buf, ssize_t len)
pr_dbg("reading perf_event failed: %m\n");
}

int prepare_pmu_event(enum uftrace_event_id id)
static struct pmu_data * prepare_pmu_event(struct mcount_thread_data *mtdp,
enum uftrace_event_id id)
{
struct pmu_data *pd;
const struct pmu_info *info;
unsigned i, k;
int group_fd;

list_for_each_entry(pd, &pmu_fds, list) {
if (pd->evt_id == id)
return 0;
list_for_each_entry(pd, &mtdp->pmu_fds, list) {
if (pd->evt_id == id) {
pd->refcnt++;
return pd;
}
}

pr_dbg("setup PMU event (%d) using perf syscall\n", id);
Expand All @@ -115,7 +116,7 @@ int prepare_pmu_event(enum uftrace_event_id id)
pr_warn("failed to open '%s' perf event: %m\n",
info->setting[0].name);
free(pd);
return -1;
return NULL;
}

pd->fd[0] = group_fd;
Expand All @@ -127,39 +128,35 @@ int prepare_pmu_event(enum uftrace_event_id id)
pr_warn("failed to open '%s' perf event: %m\n",
info->setting[k].name);
free(pd);
return -1;
return NULL;
}
}

pd->n_members = info->n_members;
break;
}
pd->refcnt = 1;

if (i == ARRAY_SIZE(pmu_configs))
pr_dbg("unknown pmu event: %d - ignoring\n", id);
else
list_add_tail(&pd->list, &pmu_fds);
list_add_tail(&pd->list, &mtdp->pmu_fds);

return 0;
return pd;
}

int read_pmu_event(enum uftrace_event_id id, void *buf)
int read_pmu_event(struct mcount_thread_data *mtdp, enum uftrace_event_id id,
void *buf)
{
struct pmu_data *pd;
struct {
uint64_t nr_members;
uint64_t data[2];
} read_buf;

list_for_each_entry(pd, &pmu_fds, list) {
if (pd->evt_id == id)
break;
}

if (list_no_entry(pd, &pmu_fds, list)) {
/* unsupported pmu events */
pd = prepare_pmu_event(mtdp, id);
if (pd == NULL)
return -1;
}

/* read group events at once */
read_perf_event(pd->fd[0], &read_buf, sizeof(read_buf));
Expand All @@ -169,11 +166,11 @@ int read_pmu_event(enum uftrace_event_id id, void *buf)
return 0;
}

void finish_pmu_event(void)
void finish_pmu_event(struct mcount_thread_data *mtdp)
{
struct pmu_data *pd, *tmp;

list_for_each_entry_safe(pd, tmp, &pmu_fds, list) {
list_for_each_entry_safe(pd, tmp, &mtdp->pmu_fds, list) {
list_del(&pd->list);

switch (pd->evt_id) {
Expand All @@ -189,3 +186,32 @@ void finish_pmu_event(void)
free(pd);
}
}

void release_pmu_event(struct mcount_thread_data *mtdp, enum uftrace_event_id id)
{
struct pmu_data *pd, *tmp;

list_for_each_entry_safe(pd, tmp, &mtdp->pmu_fds, list) {
if (pd->evt_id != id)
continue;

/* -2 because read and diff pass will increase it separately */
pd->refcnt -= 2;

if (pd->refcnt > 0)
continue;

list_del(&pd->list);
switch (pd->evt_id) {
case EVENT_ID_READ_PMU_CYCLE:
case EVENT_ID_READ_PMU_CACHE:
case EVENT_ID_READ_PMU_BRANCH:
close(pd->fd[0]);
close(pd->fd[1]);
break;
default:
break;
}
free(pd);
}
}
42 changes: 25 additions & 17 deletions libmcount/record.c
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ void save_retval(struct mcount_thread_data *mtdp,
*(uint32_t *)argbuf = size;
}

static int save_proc_statm(void *buf)
static int save_proc_statm(void *ctx, void *buf)
{
FILE *fp;
struct uftrace_proc_statm *statm = buf;
Expand All @@ -563,7 +563,7 @@ static int save_proc_statm(void *buf)
return 0;
}

static void diff_proc_statm(void *dst, void *src)
static void diff_proc_statm(void *ctx, void *dst, void *src)
{
struct uftrace_proc_statm *dst_statm = dst;
struct uftrace_proc_statm *src_statm = src;
Expand All @@ -573,7 +573,7 @@ static void diff_proc_statm(void *dst, void *src)
dst_statm->shared -= src_statm->shared;
}

static int save_page_fault(void *buf)
static int save_page_fault(void *ctx, void *buf)
{
struct rusage ru;
struct uftrace_page_fault *page_fault = buf;
Expand All @@ -587,7 +587,7 @@ static int save_page_fault(void *buf)
return 0;
}

static void diff_page_fault(void *dst, void *src)
static void diff_page_fault(void *ctx, void *dst, void *src)
{
struct uftrace_page_fault *dst_pgflt = dst;
struct uftrace_page_fault *src_pgflt = src;
Expand All @@ -596,46 +596,52 @@ static void diff_page_fault(void *dst, void *src)
dst_pgflt->minor -= src_pgflt->minor;
}

static int save_pmu_cycle(void *buf)
static int save_pmu_cycle(void *ctx, void *buf)
{
return read_pmu_event(EVENT_ID_READ_PMU_CYCLE, buf);
return read_pmu_event(ctx, EVENT_ID_READ_PMU_CYCLE, buf);
}

static void diff_pmu_cycle(void *dst, void *src)
static void diff_pmu_cycle(void *ctx, void *dst, void *src)
{
struct uftrace_pmu_cycle *dst_cycle = dst;
struct uftrace_pmu_cycle *src_cycle = src;

dst_cycle->cycles -= src_cycle->cycles;
dst_cycle->instrs -= src_cycle->instrs;

release_pmu_event(ctx, EVENT_ID_READ_PMU_CYCLE);
}

static int save_pmu_cache(void *buf)
static int save_pmu_cache(void *ctx, void *buf)
{
return read_pmu_event(EVENT_ID_READ_PMU_CACHE, buf);
return read_pmu_event(ctx, EVENT_ID_READ_PMU_CACHE, buf);
}

static void diff_pmu_cache(void *dst, void *src)
static void diff_pmu_cache(void *ctx, void *dst, void *src)
{
struct uftrace_pmu_cache *dst_cache = dst;
struct uftrace_pmu_cache *src_cache = src;

dst_cache->refers -= src_cache->refers;
dst_cache->misses -= src_cache->misses;

release_pmu_event(ctx, EVENT_ID_READ_PMU_CACHE);
}

static int save_pmu_branch(void *buf)
static int save_pmu_branch(void *ctx, void *buf)
{
return read_pmu_event(EVENT_ID_READ_PMU_BRANCH, buf);
return read_pmu_event(ctx, EVENT_ID_READ_PMU_BRANCH, buf);
}

static void diff_pmu_branch(void *dst, void *src)
static void diff_pmu_branch(void *ctx, void *dst, void *src)
{
struct uftrace_pmu_branch *dst_branch = dst;
struct uftrace_pmu_branch *src_branch = src;

dst_branch->branch -= src_branch->branch;
dst_branch->misses -= src_branch->misses;

release_pmu_event(ctx, EVENT_ID_READ_PMU_BRANCH);
}

/* above functions should follow the name convention to use below macro */
Expand All @@ -648,8 +654,8 @@ static struct read_event_data {
enum uftrace_event_id id_read;
enum uftrace_event_id id_diff;
size_t size;
int (*save)(void *buf);
void (*diff)(void *dst, void *src);
int (*save)(void *ctx, void *buf);
void (*diff)(void *ctx, void *dst, void *src);
} read_events[] = {
{ TR_ID(PROC_STATM), TR_DS(proc_statm), TR_FN(proc_statm) },
{ TR_ID(PAGE_FAULT), TR_DS(page_fault), TR_FN(page_fault) },
Expand Down Expand Up @@ -694,7 +700,7 @@ void save_trigger_read(struct mcount_thread_data *mtdp,
event->dsize = red->size;
event->idx = mtdp->idx;

if (red->save(event->data) < 0)
if (red->save(mtdp, event->data) < 0)
continue;

if (diff) {
Expand All @@ -705,11 +711,13 @@ void save_trigger_read(struct mcount_thread_data *mtdp,
old_event = get_event_pointer(ptr, idx);
if (old_event->id == event->id)
break;

old_event = NULL;
}

if (old_event) {
event->id = red->id_diff;
red->diff(event->data, old_event->data);
red->diff(mtdp, event->data, old_event->data);
}
}

Expand Down
Loading

0 comments on commit 66eb586

Please sign in to comment.