// SPDX-License-Identifier: GPL-2.0
#include "debug.h"
#include "env.h"
#include "lock-contention.h"
#include "machine.h"
#include "symbol.h"
#include <limits.h>
#include <string.h>
#include <linux/hash.h>
#include <linux/zalloc.h>
#define __lockhashfn(key) hash_long((unsigned long )key, LOCKHASH_BITS)
#define lockhashentry(key) (lockhash_table + __lockhashfn((key)))
struct callstack_filter {
struct list_head list;
char name[];
};
static LIST_HEAD(callstack_filters);
struct hlist_head *lockhash_table;
int parse_call_stack(const struct option *opt __maybe_unused, const char *str,
int unset __maybe_unused)
{
char *s, *tmp, *tok;
int ret = 0 ;
s = strdup(str);
if (s == NULL)
return -1 ;
for (tok = strtok_r(s, ", " , &tmp); tok; tok = strtok_r(NULL, ", " , &tmp)) {
struct callstack_filter *entry;
entry = malloc(sizeof (*entry) + strlen(tok) + 1 );
if (entry == NULL) {
pr_err("Memory allocation failure\n" );
free(s);
return -1 ;
}
strcpy(entry->name, tok);
list_add_tail(&entry->list, &callstack_filters);
}
free(s);
return ret;
}
bool needs_callstack(void )
{
return !list_empty(&callstack_filters);
}
struct lock_stat *lock_stat_find(u64 addr)
{
struct hlist_head *entry = lockhashentry(addr);
struct lock_stat *ret;
hlist_for_each_entry(ret, entry, hash_entry) {
if (ret->addr == addr)
return ret;
}
return NULL;
}
struct lock_stat *lock_stat_findnew(u64 addr, const char *name, int flags)
{
struct hlist_head *entry = lockhashentry(addr);
struct lock_stat *ret, *new ;
hlist_for_each_entry(ret, entry, hash_entry) {
if (ret->addr == addr)
return ret;
}
new = zalloc(sizeof (struct lock_stat));
if (!new )
goto alloc_failed;
new ->addr = addr;
new ->name = strdup(name);
if (!new ->name) {
free(new );
goto alloc_failed;
}
new ->flags = flags;
new ->wait_time_min = ULLONG_MAX;
hlist_add_head(&new ->hash_entry, entry);
return new ;
alloc_failed:
pr_err("memory allocation failed\n" );
return NULL;
}
bool match_callstack_filter(struct machine *machine, u64 *callstack, int max_stack_depth)
{
struct map *kmap;
struct symbol *sym;
u64 ip;
const char *arch = perf_env__arch(machine->env);
if (list_empty(&callstack_filters))
return true ;
for (int i = 0 ; i < max_stack_depth; i++) {
struct callstack_filter *filter;
/*
* In powerpc , the callchain saved by kernel always includes
* first three entries as the NIP ( next instruction pointer ) ,
* LR ( link register ) , and the contents of LR save area in the
* second stack frame . In certain scenarios its possible to have
* invalid kernel instruction addresses in either LR or the second
* stack frame ' s LR . In that case , kernel will store that address as
* zero .
*
* The below check will continue to look into callstack ,
* incase first or second callstack index entry has 0
* address for powerpc .
*/
if (!callstack || (!callstack[i] && (strcmp(arch, "powerpc" ) ||
(i != 1 && i != 2 ))))
break ;
ip = callstack[i];
sym = machine__find_kernel_symbol(machine, ip, &kmap);
if (sym == NULL)
continue ;
list_for_each_entry(filter, &callstack_filters, list) {
if (strstr(sym->name, filter->name))
return true ;
}
}
return false ;
}
Messung V0.5 in Prozent C=99 H=91 G=94
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-10-11)
¤
*© Formatika GbR, Deutschland