brintos

brintos / linux-shallow public Read only

0
0
Text · 2.9 KiB · 6d47298 Raw
145 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * dlfilter-show-cycles.c: Print the number of cycles at the start of each line4 * Copyright (c) 2021, Intel Corporation.5 */6#include <perf/perf_dlfilter.h>7#include <string.h>8#include <stdio.h>9 10#define MAX_CPU 409611 12enum {13	INSTR_CYC,14	BRNCH_CYC,15	OTHER_CYC,16	MAX_ENTRY17};18 19static __u64 cycles[MAX_CPU][MAX_ENTRY];20static __u64 cycles_rpt[MAX_CPU][MAX_ENTRY];21 22#define BITS		1623#define TABLESZ		(1 << BITS)24#define TABLEMAX	(TABLESZ / 2)25#define MASK		(TABLESZ - 1)26 27static struct entry {28	__u32 used;29	__s32 tid;30	__u64 cycles[MAX_ENTRY];31	__u64 cycles_rpt[MAX_ENTRY];32} table[TABLESZ];33 34static int tid_cnt;35 36static int event_entry(const char *event)37{38	if (!event)39		return OTHER_CYC;40	if (!strncmp(event, "instructions", 12))41		return INSTR_CYC;42	if (!strncmp(event, "branches", 8))43		return BRNCH_CYC;44	return OTHER_CYC;45}46 47static struct entry *find_entry(__s32 tid)48{49	__u32 pos = tid & MASK;50	struct entry *e;51 52	e = &table[pos];53	while (e->used) {54		if (e->tid == tid)55			return e;56		if (++pos == TABLESZ)57			pos = 0;58		e = &table[pos];59	}60 61	if (tid_cnt >= TABLEMAX) {62		fprintf(stderr, "Too many threads\n");63		return NULL;64	}65 66	tid_cnt += 1;67	e->used = 1;68	e->tid = tid;69	return e;70}71 72static void add_entry(__s32 tid, int pos, __u64 cnt)73{74	struct entry *e = find_entry(tid);75 76	if (e)77		e->cycles[pos] += cnt;78}79 80int filter_event_early(void *data, const struct perf_dlfilter_sample *sample, void *ctx)81{82	__s32 cpu = sample->cpu;83	__s32 tid = sample->tid;84	int pos;85 86	if (!sample->cyc_cnt)87		return 0;88 89	pos = event_entry(sample->event);90 91	if (cpu >= 0 && cpu < MAX_CPU)92		cycles[cpu][pos] += sample->cyc_cnt;93	else if (tid != -1)94		add_entry(tid, pos, sample->cyc_cnt);95	return 0;96}97 98static void print_vals(__u64 cycles, __u64 delta)99{100	if (delta)101		printf("%10llu %10llu ", (unsigned long long)cycles, (unsigned long long)delta);102	else103		printf("%10llu %10s ", (unsigned long long)cycles, "");104}105 106int filter_event(void *data, const struct perf_dlfilter_sample *sample, void *ctx)107{108	__s32 cpu = sample->cpu;109	__s32 tid = sample->tid;110	int pos;111 112	pos = event_entry(sample->event);113 114	if (cpu >= 0 && cpu < MAX_CPU) {115		print_vals(cycles[cpu][pos], cycles[cpu][pos] - cycles_rpt[cpu][pos]);116		cycles_rpt[cpu][pos] = cycles[cpu][pos];117		return 0;118	}119 120	if (tid != -1) {121		struct entry *e = find_entry(tid);122 123		if (e) {124			print_vals(e->cycles[pos], e->cycles[pos] - e->cycles_rpt[pos]);125			e->cycles_rpt[pos] = e->cycles[pos];126			return 0;127		}128	}129 130	printf("%22s", "");131	return 0;132}133 134const char *filter_description(const char **long_description)135{136	static char *long_desc = "Cycle counts are accumulated per CPU (or "137		"per thread if CPU is not recorded) from IPC information, and "138		"printed together with the change since the last print, at the "139		"start of each line. Separate counts are kept for branches, "140		"instructions or other events.";141 142	*long_description = long_desc;143	return "Print the number of cycles at the start of each line";144}145