aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/util/auxtrace.c123
-rw-r--r--tools/perf/util/auxtrace.h14
2 files changed, 137 insertions, 0 deletions
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index c4515e1a9d7f..3cd89eca1e88 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -40,6 +40,8 @@
40#include "asm/bug.h" 40#include "asm/bug.h"
41#include "auxtrace.h" 41#include "auxtrace.h"
42 42
43#include <linux/hash.h>
44
43#include "event.h" 45#include "event.h"
44#include "session.h" 46#include "session.h"
45#include "debug.h" 47#include "debug.h"
@@ -944,3 +946,124 @@ int auxtrace_mmap__read(struct auxtrace_mmap *mm, struct auxtrace_record *itr,
944 946
945 return 1; 947 return 1;
946} 948}
949
950/**
951 * struct auxtrace_cache - hash table to implement a cache
952 * @hashtable: the hashtable
953 * @sz: hashtable size (number of hlists)
954 * @entry_size: size of an entry
955 * @limit: limit the number of entries to this maximum, when reached the cache
956 * is dropped and caching begins again with an empty cache
957 * @cnt: current number of entries
958 * @bits: hashtable size (@sz = 2^@bits)
959 */
960struct auxtrace_cache {
961 struct hlist_head *hashtable;
962 size_t sz;
963 size_t entry_size;
964 size_t limit;
965 size_t cnt;
966 unsigned int bits;
967};
968
969struct auxtrace_cache *auxtrace_cache__new(unsigned int bits, size_t entry_size,
970 unsigned int limit_percent)
971{
972 struct auxtrace_cache *c;
973 struct hlist_head *ht;
974 size_t sz, i;
975
976 c = zalloc(sizeof(struct auxtrace_cache));
977 if (!c)
978 return NULL;
979
980 sz = 1UL << bits;
981
982 ht = calloc(sz, sizeof(struct hlist_head));
983 if (!ht)
984 goto out_free;
985
986 for (i = 0; i < sz; i++)
987 INIT_HLIST_HEAD(&ht[i]);
988
989 c->hashtable = ht;
990 c->sz = sz;
991 c->entry_size = entry_size;
992 c->limit = (c->sz * limit_percent) / 100;
993 c->bits = bits;
994
995 return c;
996
997out_free:
998 free(c);
999 return NULL;
1000}
1001
1002static void auxtrace_cache__drop(struct auxtrace_cache *c)
1003{
1004 struct auxtrace_cache_entry *entry;
1005 struct hlist_node *tmp;
1006 size_t i;
1007
1008 if (!c)
1009 return;
1010
1011 for (i = 0; i < c->sz; i++) {
1012 hlist_for_each_entry_safe(entry, tmp, &c->hashtable[i], hash) {
1013 hlist_del(&entry->hash);
1014 auxtrace_cache__free_entry(c, entry);
1015 }
1016 }
1017
1018 c->cnt = 0;
1019}
1020
1021void auxtrace_cache__free(struct auxtrace_cache *c)
1022{
1023 if (!c)
1024 return;
1025
1026 auxtrace_cache__drop(c);
1027 free(c->hashtable);
1028 free(c);
1029}
1030
1031void *auxtrace_cache__alloc_entry(struct auxtrace_cache *c)
1032{
1033 return malloc(c->entry_size);
1034}
1035
1036void auxtrace_cache__free_entry(struct auxtrace_cache *c __maybe_unused,
1037 void *entry)
1038{
1039 free(entry);
1040}
1041
1042int auxtrace_cache__add(struct auxtrace_cache *c, u32 key,
1043 struct auxtrace_cache_entry *entry)
1044{
1045 if (c->limit && ++c->cnt > c->limit)
1046 auxtrace_cache__drop(c);
1047
1048 entry->key = key;
1049 hlist_add_head(&entry->hash, &c->hashtable[hash_32(key, c->bits)]);
1050
1051 return 0;
1052}
1053
1054void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key)
1055{
1056 struct auxtrace_cache_entry *entry;
1057 struct hlist_head *hlist;
1058
1059 if (!c)
1060 return NULL;
1061
1062 hlist = &c->hashtable[hash_32(key, c->bits)];
1063 hlist_for_each_entry(entry, hlist, hash) {
1064 if (entry->key == key)
1065 return entry;
1066 }
1067
1068 return NULL;
1069}
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index ba78d825bf73..53b60a64a693 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -333,6 +333,20 @@ int auxtrace_heap__add(struct auxtrace_heap *heap, unsigned int queue_nr,
333void auxtrace_heap__pop(struct auxtrace_heap *heap); 333void auxtrace_heap__pop(struct auxtrace_heap *heap);
334void auxtrace_heap__free(struct auxtrace_heap *heap); 334void auxtrace_heap__free(struct auxtrace_heap *heap);
335 335
336struct auxtrace_cache_entry {
337 struct hlist_node hash;
338 u32 key;
339};
340
341struct auxtrace_cache *auxtrace_cache__new(unsigned int bits, size_t entry_size,
342 unsigned int limit_percent);
343void auxtrace_cache__free(struct auxtrace_cache *auxtrace_cache);
344void *auxtrace_cache__alloc_entry(struct auxtrace_cache *c);
345void auxtrace_cache__free_entry(struct auxtrace_cache *c, void *entry);
346int auxtrace_cache__add(struct auxtrace_cache *c, u32 key,
347 struct auxtrace_cache_entry *entry);
348void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key);
349
336struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist, 350struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist,
337 int *err); 351 int *err);
338 352