hist.c 21.8 KB
Newer Older
1
#include "util.h"
2
#include "build-id.h"
3
#include "hist.h"
4 5
#include "session.h"
#include "sort.h"
6
#include "evsel.h"
7
#include <math.h>
8

9 10 11 12
static bool hists__filter_entry_by_dso(struct hists *hists,
				       struct hist_entry *he);
static bool hists__filter_entry_by_thread(struct hists *hists,
					  struct hist_entry *he);
13 14
static bool hists__filter_entry_by_symbol(struct hists *hists,
					  struct hist_entry *he);
15

16 17
struct callchain_param	callchain_param = {
	.mode	= CHAIN_GRAPH_REL,
18
	.min_percent = 0.5,
19 20
	.order  = ORDER_CALLEE,
	.key	= CCKEY_FUNCTION
21 22
};

23
u16 hists__col_len(struct hists *hists, enum hist_column col)
24
{
25
	return hists->col_len[col];
26 27
}

28
void hists__set_col_len(struct hists *hists, enum hist_column col, u16 len)
29
{
30
	hists->col_len[col] = len;
31 32
}

33
bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len)
34
{
35 36
	if (len > hists__col_len(hists, col)) {
		hists__set_col_len(hists, col, len);
37 38 39 40 41
		return true;
	}
	return false;
}

42
void hists__reset_col_len(struct hists *hists)
43 44 45 46
{
	enum hist_column col;

	for (col = 0; col < HISTC_NR_COLS; ++col)
47
		hists__set_col_len(hists, col, 0);
48 49
}

50 51 52 53 54 55 56 57 58 59
static void hists__set_unres_dso_col_len(struct hists *hists, int dso)
{
	const unsigned int unresolved_col_width = BITS_PER_LONG / 4;

	if (hists__col_len(hists, dso) < unresolved_col_width &&
	    !symbol_conf.col_width_list_str && !symbol_conf.field_sep &&
	    !symbol_conf.dso_list)
		hists__set_col_len(hists, dso, unresolved_col_width);
}

60
void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
61
{
62
	const unsigned int unresolved_col_width = BITS_PER_LONG / 4;
63
	int symlen;
64 65
	u16 len;

66 67 68 69 70 71 72 73 74 75 76
	/*
	 * +4 accounts for '[x] ' priv level info
	 * +2 accounts for 0x prefix on raw addresses
	 * +3 accounts for ' y ' symtab origin info
	 */
	if (h->ms.sym) {
		symlen = h->ms.sym->namelen + 4;
		if (verbose)
			symlen += BITS_PER_LONG / 4 + 2 + 3;
		hists__new_col_len(hists, HISTC_SYMBOL, symlen);
	} else {
77 78
		symlen = unresolved_col_width + 4 + 2;
		hists__new_col_len(hists, HISTC_SYMBOL, symlen);
79
		hists__set_unres_dso_col_len(hists, HISTC_DSO);
80
	}
81 82

	len = thread__comm_len(h->thread);
83 84
	if (hists__new_col_len(hists, HISTC_COMM, len))
		hists__set_col_len(hists, HISTC_THREAD, len + 6);
85 86 87

	if (h->ms.map) {
		len = dso__name_len(h->ms.map->dso);
88
		hists__new_col_len(hists, HISTC_DSO, len);
89
	}
90

91 92 93
	if (h->parent)
		hists__new_col_len(hists, HISTC_PARENT, h->parent->namelen);

94 95 96
	if (h->branch_info) {
		if (h->branch_info->from.sym) {
			symlen = (int)h->branch_info->from.sym->namelen + 4;
97 98
			if (verbose)
				symlen += BITS_PER_LONG / 4 + 2 + 3;
99 100 101 102 103 104 105 106 107 108 109 110
			hists__new_col_len(hists, HISTC_SYMBOL_FROM, symlen);

			symlen = dso__name_len(h->branch_info->from.map->dso);
			hists__new_col_len(hists, HISTC_DSO_FROM, symlen);
		} else {
			symlen = unresolved_col_width + 4 + 2;
			hists__new_col_len(hists, HISTC_SYMBOL_FROM, symlen);
			hists__set_unres_dso_col_len(hists, HISTC_DSO_FROM);
		}

		if (h->branch_info->to.sym) {
			symlen = (int)h->branch_info->to.sym->namelen + 4;
111 112
			if (verbose)
				symlen += BITS_PER_LONG / 4 + 2 + 3;
113 114 115 116 117 118 119 120 121 122
			hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen);

			symlen = dso__name_len(h->branch_info->to.map->dso);
			hists__new_col_len(hists, HISTC_DSO_TO, symlen);
		} else {
			symlen = unresolved_col_width + 4 + 2;
			hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen);
			hists__set_unres_dso_col_len(hists, HISTC_DSO_TO);
		}
	}
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154

	if (h->mem_info) {
		if (h->mem_info->daddr.sym) {
			symlen = (int)h->mem_info->daddr.sym->namelen + 4
			       + unresolved_col_width + 2;
			hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
					   symlen);
		} else {
			symlen = unresolved_col_width + 4 + 2;
			hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL,
					   symlen);
		}
		if (h->mem_info->daddr.map) {
			symlen = dso__name_len(h->mem_info->daddr.map->dso);
			hists__new_col_len(hists, HISTC_MEM_DADDR_DSO,
					   symlen);
		} else {
			symlen = unresolved_col_width + 4 + 2;
			hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
		}
	} else {
		symlen = unresolved_col_width + 4 + 2;
		hists__new_col_len(hists, HISTC_MEM_DADDR_SYMBOL, symlen);
		hists__set_unres_dso_col_len(hists, HISTC_MEM_DADDR_DSO);
	}

	hists__new_col_len(hists, HISTC_MEM_LOCKED, 6);
	hists__new_col_len(hists, HISTC_MEM_TLB, 22);
	hists__new_col_len(hists, HISTC_MEM_SNOOP, 12);
	hists__new_col_len(hists, HISTC_MEM_LVL, 21 + 3);
	hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12);
	hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12);
155 156 157 158

	if (h->transaction)
		hists__new_col_len(hists, HISTC_TRANSACTION,
				   hist_entry__transaction_len());
159 160
}

161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
void hists__output_recalc_col_len(struct hists *hists, int max_rows)
{
	struct rb_node *next = rb_first(&hists->entries);
	struct hist_entry *n;
	int row = 0;

	hists__reset_col_len(hists);

	while (next && row++ < max_rows) {
		n = rb_entry(next, struct hist_entry, rb_node);
		if (!n->filtered)
			hists__calc_col_len(hists, n);
		next = rb_next(&n->rb_node);
	}
}

177 178
static void he_stat__add_cpumode_period(struct he_stat *he_stat,
					unsigned int cpumode, u64 period)
179
{
180
	switch (cpumode) {
181
	case PERF_RECORD_MISC_KERNEL:
182
		he_stat->period_sys += period;
183 184
		break;
	case PERF_RECORD_MISC_USER:
185
		he_stat->period_us += period;
186 187
		break;
	case PERF_RECORD_MISC_GUEST_KERNEL:
188
		he_stat->period_guest_sys += period;
189 190
		break;
	case PERF_RECORD_MISC_GUEST_USER:
191
		he_stat->period_guest_us += period;
192 193 194 195 196 197
		break;
	default:
		break;
	}
}

198 199
static void he_stat__add_period(struct he_stat *he_stat, u64 period,
				u64 weight)
200
{
201

202
	he_stat->period		+= period;
203
	he_stat->weight		+= weight;
204 205 206 207 208 209 210 211 212 213 214
	he_stat->nr_events	+= 1;
}

static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src)
{
	dest->period		+= src->period;
	dest->period_sys	+= src->period_sys;
	dest->period_us		+= src->period_us;
	dest->period_guest_sys	+= src->period_guest_sys;
	dest->period_guest_us	+= src->period_guest_us;
	dest->nr_events		+= src->nr_events;
215
	dest->weight		+= src->weight;
216 217
}

218
static void he_stat__decay(struct he_stat *he_stat)
219
{
220 221
	he_stat->period = (he_stat->period * 7) / 8;
	he_stat->nr_events = (he_stat->nr_events * 7) / 8;
222
	/* XXX need decay for weight too? */
223 224 225 226
}

static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
{
227
	u64 prev_period = he->stat.period;
228
	u64 diff;
229 230

	if (prev_period == 0)
231
		return true;
232

233
	he_stat__decay(&he->stat);
234

235 236 237
	diff = prev_period - he->stat.period;

	hists->stats.total_period -= diff;
238
	if (!he->filtered)
239
		hists->stats.total_non_filtered_period -= diff;
240

241
	return he->stat.period == 0;
242 243
}

244
void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel)
245 246 247 248 249 250 251
{
	struct rb_node *next = rb_first(&hists->entries);
	struct hist_entry *n;

	while (next) {
		n = rb_entry(next, struct hist_entry, rb_node);
		next = rb_next(&n->rb_node);
252 253 254 255 256
		/*
		 * We may be annotating this, for instance, so keep it here in
		 * case some it gets new samples, we'll eventually free it when
		 * the user stops browsing and it agains gets fully decayed.
		 */
257 258 259 260
		if (((zap_user && n->level == '.') ||
		     (zap_kernel && n->level != '.') ||
		     hists__decay_entry(hists, n)) &&
		    !n->used) {
261 262
			rb_erase(&n->rb_node, &hists->entries);

263
			if (sort__need_collapse)
264 265 266
				rb_erase(&n->rb_node_in, &hists->entries_collapsed);

			--hists->nr_entries;
267 268 269 270
			if (!n->filtered)
				--hists->nr_non_filtered_entries;

			hist_entry__free(n);
271 272 273 274
		}
	}
}

275
/*
276
 * histogram, sorted on item, collects periods
277 278
 */

279 280
static struct hist_entry *hist_entry__new(struct hist_entry *template)
{
281
	size_t callchain_size = symbol_conf.use_callchain ? sizeof(struct callchain_root) : 0;
282
	struct hist_entry *he = zalloc(sizeof(*he) + callchain_size);
283

284 285
	if (he != NULL) {
		*he = *template;
286

287 288
		if (he->ms.map)
			he->ms.map->referenced = true;
289 290

		if (he->branch_info) {
291 292
			/*
			 * This branch info is (a part of) allocated from
293
			 * sample__resolve_bstack() and will be freed after
294 295 296 297 298 299 300 301 302 303 304
			 * adding new entries.  So we need to save a copy.
			 */
			he->branch_info = malloc(sizeof(*he->branch_info));
			if (he->branch_info == NULL) {
				free(he);
				return NULL;
			}

			memcpy(he->branch_info, template->branch_info,
			       sizeof(*he->branch_info));

305 306 307 308 309 310
			if (he->branch_info->from.map)
				he->branch_info->from.map->referenced = true;
			if (he->branch_info->to.map)
				he->branch_info->to.map->referenced = true;
		}

311 312 313 314 315 316 317
		if (he->mem_info) {
			if (he->mem_info->iaddr.map)
				he->mem_info->iaddr.map->referenced = true;
			if (he->mem_info->daddr.map)
				he->mem_info->daddr.map->referenced = true;
		}

318
		if (symbol_conf.use_callchain)
319
			callchain_init(he->callchain);
320 321

		INIT_LIST_HEAD(&he->pairs.node);
322 323
	}

324
	return he;
325 326
}

327 328 329 330 331 332 333
static u8 symbol__parent_filter(const struct symbol *parent)
{
	if (symbol_conf.exclude_other && parent == NULL)
		return 1 << HIST_FILTER__PARENT;
	return 0;
}

334
static struct hist_entry *add_hist_entry(struct hists *hists,
335 336
					 struct hist_entry *entry,
					 struct addr_location *al)
337
{
338
	struct rb_node **p;
339 340
	struct rb_node *parent = NULL;
	struct hist_entry *he;
341
	int64_t cmp;
342 343
	u64 period = entry->stat.period;
	u64 weight = entry->stat.weight;
344

345 346
	p = &hists->entries_in->rb_node;

347 348
	while (*p != NULL) {
		parent = *p;
349
		he = rb_entry(parent, struct hist_entry, rb_node_in);
350

351 352 353 354 355 356 357
		/*
		 * Make sure that it receives arguments in a same order as
		 * hist_entry__collapse() so that we can use an appropriate
		 * function when searching an entry regardless which sort
		 * keys were used.
		 */
		cmp = hist_entry__cmp(he, entry);
358 359

		if (!cmp) {
360
			he_stat__add_period(&he->stat, period, weight);
361

362
			/*
363
			 * This mem info was allocated from sample__resolve_mem
364 365
			 * and will not be used anymore.
			 */
366
			zfree(&entry->mem_info);
367

368 369 370 371 372 373 374 375 376 377 378
			/* If the map of an existing hist_entry has
			 * become out-of-date due to an exec() or
			 * similar, update it.  Otherwise we will
			 * mis-adjust symbol addresses when computing
			 * the history counter to increment.
			 */
			if (he->ms.map != entry->ms.map) {
				he->ms.map = entry->ms.map;
				if (he->ms.map)
					he->ms.map->referenced = true;
			}
379
			goto out;
380 381 382 383 384 385 386 387
		}

		if (cmp < 0)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

388
	he = hist_entry__new(entry);
389
	if (!he)
390
		return NULL;
391 392 393

	rb_link_node(&he->rb_node_in, parent, p);
	rb_insert_color(&he->rb_node_in, hists->entries_in);
394
out:
395
	he_stat__add_cpumode_period(&he->stat, al->cpumode, period);
396 397 398
	return he;
}

399
struct hist_entry *__hists__add_entry(struct hists *hists,
400
				      struct addr_location *al,
401 402 403 404
				      struct symbol *sym_parent,
				      struct branch_info *bi,
				      struct mem_info *mi,
				      u64 period, u64 weight, u64 transaction)
405 406 407
{
	struct hist_entry entry = {
		.thread	= al->thread,
408
		.comm = thread__comm(al->thread),
409 410 411 412 413 414 415
		.ms = {
			.map	= al->map,
			.sym	= al->sym,
		},
		.cpu	= al->cpu,
		.ip	= al->addr,
		.level	= al->level,
416
		.stat = {
417
			.nr_events = 1,
418
			.period	= period,
419
			.weight = weight,
420
		},
421
		.parent = sym_parent,
422
		.filtered = symbol__parent_filter(sym_parent) | al->filtered,
423
		.hists	= hists,
424 425
		.branch_info = bi,
		.mem_info = mi,
426
		.transaction = transaction,
427 428
	};

429
	return add_hist_entry(hists, &entry, al);
430 431
}

432 433 434
int64_t
hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
{
435
	struct perf_hpp_fmt *fmt;
436 437
	int64_t cmp = 0;

438
	perf_hpp__for_each_sort_list(fmt) {
439 440 441
		if (perf_hpp__should_skip(fmt))
			continue;

442
		cmp = fmt->cmp(left, right);
443 444 445 446 447 448 449 450 451 452
		if (cmp)
			break;
	}

	return cmp;
}

int64_t
hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
{
453
	struct perf_hpp_fmt *fmt;
454 455
	int64_t cmp = 0;

456
	perf_hpp__for_each_sort_list(fmt) {
457 458 459
		if (perf_hpp__should_skip(fmt))
			continue;

460
		cmp = fmt->collapse(left, right);
461 462 463 464 465 466 467 468 469
		if (cmp)
			break;
	}

	return cmp;
}

void hist_entry__free(struct hist_entry *he)
{
470 471
	zfree(&he->branch_info);
	zfree(&he->mem_info);
472
	free_srcline(he->srcline);
473 474 475 476 477 478 479
	free(he);
}

/*
 * collapse the histogram
 */

480
static bool hists__collapse_insert_entry(struct hists *hists __maybe_unused,
481 482
					 struct rb_root *root,
					 struct hist_entry *he)
483
{
484
	struct rb_node **p = &root->rb_node;
485 486 487 488 489 490
	struct rb_node *parent = NULL;
	struct hist_entry *iter;
	int64_t cmp;

	while (*p != NULL) {
		parent = *p;
491
		iter = rb_entry(parent, struct hist_entry, rb_node_in);
492 493 494 495

		cmp = hist_entry__collapse(iter, he);

		if (!cmp) {
496
			he_stat__add_stat(&iter->stat, &he->stat);
497

498
			if (symbol_conf.use_callchain) {
499 500 501
				callchain_cursor_reset(&callchain_cursor);
				callchain_merge(&callchain_cursor,
						iter->callchain,
502 503
						he->callchain);
			}
504
			hist_entry__free(he);
505
			return false;
506 507 508 509 510 511 512 513
		}

		if (cmp < 0)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

514 515
	rb_link_node(&he->rb_node_in, parent, p);
	rb_insert_color(&he->rb_node_in, root);
516
	return true;
517 518
}

519
static struct rb_root *hists__get_rotate_entries_in(struct hists *hists)
520
{
521 522 523 524 525 526 527 528 529 530 531 532 533
	struct rb_root *root;

	pthread_mutex_lock(&hists->lock);

	root = hists->entries_in;
	if (++hists->entries_in > &hists->entries_in_array[1])
		hists->entries_in = &hists->entries_in_array[0];

	pthread_mutex_unlock(&hists->lock);

	return root;
}

534 535 536 537
static void hists__apply_filters(struct hists *hists, struct hist_entry *he)
{
	hists__filter_entry_by_dso(hists, he);
	hists__filter_entry_by_thread(hists, he);
538
	hists__filter_entry_by_symbol(hists, he);
539 540
}

541
void hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
542 543
{
	struct rb_root *root;
544 545 546
	struct rb_node *next;
	struct hist_entry *n;

547
	if (!sort__need_collapse)
548 549
		return;

550 551
	root = hists__get_rotate_entries_in(hists);
	next = rb_first(root);
552

553
	while (next) {
554 555
		if (session_done())
			break;
556 557
		n = rb_entry(next, struct hist_entry, rb_node_in);
		next = rb_next(&n->rb_node_in);
558

559
		rb_erase(&n->rb_node_in, root);
560 561 562 563 564 565 566 567
		if (hists__collapse_insert_entry(hists, &hists->entries_collapsed, n)) {
			/*
			 * If it wasn't combined with one of the entries already
			 * collapsed, we need to apply the filters that may have
			 * been set by, say, the hist_browser.
			 */
			hists__apply_filters(hists, n);
		}
568 569
		if (prog)
			ui_progress__update(prog, 1);
570
	}
571
}
572

573
static int hist_entry__sort(struct hist_entry *a, struct hist_entry *b)
574
{
575 576
	struct perf_hpp_fmt *fmt;
	int64_t cmp = 0;
577

578
	perf_hpp__for_each_sort_list(fmt) {
579 580 581
		if (perf_hpp__should_skip(fmt))
			continue;

582 583
		cmp = fmt->sort(a, b);
		if (cmp)
584 585 586
			break;
	}

587
	return cmp;
588 589
}

590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
static void hists__reset_filter_stats(struct hists *hists)
{
	hists->nr_non_filtered_entries = 0;
	hists->stats.total_non_filtered_period = 0;
}

void hists__reset_stats(struct hists *hists)
{
	hists->nr_entries = 0;
	hists->stats.total_period = 0;

	hists__reset_filter_stats(hists);
}

static void hists__inc_filter_stats(struct hists *hists, struct hist_entry *h)
{
	hists->nr_non_filtered_entries++;
	hists->stats.total_non_filtered_period += h->stat.period;
}

void hists__inc_stats(struct hists *hists, struct hist_entry *h)
{
	if (!h->filtered)
		hists__inc_filter_stats(hists, h);

	hists->nr_entries++;
	hists->stats.total_period += h->stat.period;
}

619 620 621
static void __hists__insert_output_entry(struct rb_root *entries,
					 struct hist_entry *he,
					 u64 min_callchain_hits)
622
{
623
	struct rb_node **p = &entries->rb_node;
624 625 626
	struct rb_node *parent = NULL;
	struct hist_entry *iter;

627
	if (symbol_conf.use_callchain)
628
		callchain_param.sort(&he->sorted_chain, he->callchain,
629 630 631 632 633 634
				      min_callchain_hits, &callchain_param);

	while (*p != NULL) {
		parent = *p;
		iter = rb_entry(parent, struct hist_entry, rb_node);

635
		if (hist_entry__sort(he, iter) > 0)
636 637 638 639 640 641
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

	rb_link_node(&he->rb_node, parent, p);
642
	rb_insert_color(&he->rb_node, entries);
643 644
}

645
void hists__output_resort(struct hists *hists)
646
{
647
	struct rb_root *root;
648 649 650 651
	struct rb_node *next;
	struct hist_entry *n;
	u64 min_callchain_hits;

652
	min_callchain_hits = hists->stats.total_period * (callchain_param.min_percent / 100);
653

654
	if (sort__need_collapse)
655 656 657 658 659 660
		root = &hists->entries_collapsed;
	else
		root = hists->entries_in;

	next = rb_first(root);
	hists->entries = RB_ROOT;
661

662
	hists__reset_stats(hists);
663
	hists__reset_col_len(hists);
664

665
	while (next) {
666 667
		n = rb_entry(next, struct hist_entry, rb_node_in);
		next = rb_next(&n->rb_node_in);
668

669
		__hists__insert_output_entry(&hists->entries, n, min_callchain_hits);
670
		hists__inc_stats(hists, n);
671 672 673

		if (!n->filtered)
			hists__calc_col_len(hists, n);
674
	}
675
}
676

677
static void hists__remove_entry_filter(struct hists *hists, struct hist_entry *h,
678 679 680 681 682 683
				       enum hist_filter filter)
{
	h->filtered &= ~(1 << filter);
	if (h->filtered)
		return;

684 685
	/* force fold unfiltered entry for simplicity */
	h->ms.unfolded = false;
686
	h->row_offset = 0;
687

688
	hists->stats.nr_non_filtered_samples += h->stat.nr_events;
689

690
	hists__inc_filter_stats(hists, h);
691
	hists__calc_col_len(hists, h);
692 693
}

694 695 696 697 698 699 700 701 702 703 704 705 706

static bool hists__filter_entry_by_dso(struct hists *hists,
				       struct hist_entry *he)
{
	if (hists->dso_filter != NULL &&
	    (he->ms.map == NULL || he->ms.map->dso != hists->dso_filter)) {
		he->filtered |= (1 << HIST_FILTER__DSO);
		return true;
	}

	return false;
}

707
void hists__filter_by_dso(struct hists *hists)
708 709 710
{
	struct rb_node *nd;

711
	hists->stats.nr_non_filtered_samples = 0;
712 713

	hists__reset_filter_stats(hists);
714
	hists__reset_col_len(hists);
715

716
	for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
717 718 719 720 721
		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);

		if (symbol_conf.exclude_other && !h->parent)
			continue;

722
		if (hists__filter_entry_by_dso(hists, h))
723 724
			continue;

725
		hists__remove_entry_filter(hists, h, HIST_FILTER__DSO);
726 727 728
	}
}

729 730 731 732 733 734 735 736 737 738 739 740
static bool hists__filter_entry_by_thread(struct hists *hists,
					  struct hist_entry *he)
{
	if (hists->thread_filter != NULL &&
	    he->thread != hists->thread_filter) {
		he->filtered |= (1 << HIST_FILTER__THREAD);
		return true;
	}

	return false;
}

741
void hists__filter_by_thread(struct hists *hists)
742 743 744
{
	struct rb_node *nd;

745
	hists->stats.nr_non_filtered_samples = 0;
746 747

	hists__reset_filter_stats(hists);
748
	hists__reset_col_len(hists);
749

750
	for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
751 752
		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);

753
		if (hists__filter_entry_by_thread(hists, h))
754
			continue;
755

756
		hists__remove_entry_filter(hists, h, HIST_FILTER__THREAD);
757 758
	}
}
759

760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
static bool hists__filter_entry_by_symbol(struct hists *hists,
					  struct hist_entry *he)
{
	if (hists->symbol_filter_str != NULL &&
	    (!he->ms.sym || strstr(he->ms.sym->name,
				   hists->symbol_filter_str) == NULL)) {
		he->filtered |= (1 << HIST_FILTER__SYMBOL);
		return true;
	}

	return false;
}

void hists__filter_by_symbol(struct hists *hists)
{
	struct rb_node *nd;

777
	hists->stats.nr_non_filtered_samples = 0;
778 779

	hists__reset_filter_stats(hists);
780 781 782 783 784 785 786 787 788 789 790 791
	hists__reset_col_len(hists);

	for (nd = rb_first(&hists->entries); nd; nd = rb_next(nd)) {
		struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);

		if (hists__filter_entry_by_symbol(hists, h))
			continue;

		hists__remove_entry_filter(hists, h, HIST_FILTER__SYMBOL);
	}
}

792 793 794 795 796 797
void events_stats__inc(struct events_stats *stats, u32 type)
{
	++stats->nr_events[0];
	++stats->nr_events[type];
}

798
void hists__inc_nr_events(struct hists *hists, u32 type)
799
{
800
	events_stats__inc(&hists->stats, type);
801
}
802

803 804 805
static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
						 struct hist_entry *pair)
{
806 807
	struct rb_root *root;
	struct rb_node **p;
808 809
	struct rb_node *parent = NULL;
	struct hist_entry *he;
810
	int64_t cmp;
811

812 813 814 815 816 817 818
	if (sort__need_collapse)
		root = &hists->entries_collapsed;
	else
		root = hists->entries_in;

	p = &root->rb_node;

819 820
	while (*p != NULL) {
		parent = *p;
821
		he = rb_entry(parent, struct hist_entry, rb_node_in);
822

823
		cmp = hist_entry__collapse(he, pair);
824 825 826 827 828 829 830 831 832 833 834 835

		if (!cmp)
			goto out;

		if (cmp < 0)
			p = &(*p)->rb_left;
		else
			p = &(*p)->rb_right;
	}

	he = hist_entry__new(pair);
	if (he) {
836 837
		memset(&he->stat, 0, sizeof(he->stat));
		he->hists = hists;
838 839
		rb_link_node(&he->rb_node_in, parent, p);
		rb_insert_color(&he->rb_node_in, root);
840
		hists__inc_stats(hists, he);
841
		he->dummy = true;
842 843 844 845 846
	}
out:
	return he;
}

847 848 849
static struct hist_entry *hists__find_entry(struct hists *hists,
					    struct hist_entry *he)
{
850 851 852 853 854 855
	struct rb_node *n;

	if (sort__need_collapse)
		n = hists->entries_collapsed.rb_node;
	else
		n = hists->entries_in->rb_node;
856 857

	while (n) {
858 859
		struct hist_entry *iter = rb_entry(n, struct hist_entry, rb_node_in);
		int64_t cmp = hist_entry__collapse(iter, he);
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876

		if (cmp < 0)
			n = n->rb_left;
		else if (cmp > 0)
			n = n->rb_right;
		else
			return iter;
	}

	return NULL;
}

/*
 * Look for pairs to link to the leader buckets (hist_entries):
 */
void hists__match(struct hists *leader, struct hists *other)
{
877
	struct rb_root *root;
878 879 880
	struct rb_node *nd;
	struct hist_entry *pos, *pair;

881 882 883 884 885 886 887
	if (sort__need_collapse)
		root = &leader->entries_collapsed;
	else
		root = leader->entries_in;

	for (nd = rb_first(root); nd; nd = rb_next(nd)) {
		pos  = rb_entry(nd, struct hist_entry, rb_node_in);
888 889 890
		pair = hists__find_entry(other, pos);

		if (pair)
891
			hist_entry__add_pair(pair, pos);
892 893
	}
}
894 895 896 897 898 899 900 901

/*
 * Look for entries in the other hists that are not present in the leader, if
 * we find them, just add a dummy entry on the leader hists, with period=0,
 * nr_events=0, to serve as the list header.
 */
int hists__link(struct hists *leader, struct hists *other)
{
902
	struct rb_root *root;
903 904 905
	struct rb_node *nd;
	struct hist_entry *pos, *pair;

906 907 908 909 910 911 912
	if (sort__need_collapse)
		root = &other->entries_collapsed;
	else
		root = other->entries_in;

	for (nd = rb_first(root); nd; nd = rb_next(nd)) {
		pos = rb_entry(nd, struct hist_entry, rb_node_in);
913 914 915 916 917

		if (!hist_entry__has_pairs(pos)) {
			pair = hists__add_dummy_entry(leader, pos);
			if (pair == NULL)
				return -1;
918
			hist_entry__add_pair(pos, pair);
919 920 921 922 923
		}
	}

	return 0;
}
924 925 926 927 928 929

u64 hists__total_period(struct hists *hists)
{
	return symbol_conf.filter_relative ? hists->stats.total_non_filtered_period :
		hists->stats.total_period;
}
N
Namhyung Kim 已提交
930 931 932 933 934 935 936 937 938 939 940 941 942

int parse_filter_percentage(const struct option *opt __maybe_unused,
			    const char *arg, int unset __maybe_unused)
{
	if (!strcmp(arg, "relative"))
		symbol_conf.filter_relative = true;
	else if (!strcmp(arg, "absolute"))
		symbol_conf.filter_relative = false;
	else
		return -1;

	return 0;
}
943 944 945 946 947 948 949 950

int perf_hist_config(const char *var, const char *value)
{
	if (!strcmp(var, "hist.percentage"))
		return parse_filter_percentage(NULL, value, 0);

	return 0;
}