1 #ifdef CCAN_LIKELY_DEBUG
2 #include <ccan/likely/likely.h>
3 #include <ccan/hash/hash.h>
4 #include <ccan/htable/htable.h>
7 static struct htable *htable;
14 unsigned long count, right;
17 /* We hash the pointers, which will be identical for same call. */
18 static unsigned long hash_trace(const struct trace *trace)
20 return hash_pointer(trace->condstr,
21 hash_pointer(trace->file,
22 trace->line + trace->expect));
25 static bool hash_cmp(const void *htelem, void *cmpdata)
27 const struct trace *t1 = htelem, *t2 = cmpdata;
28 return t1->condstr == t2->condstr
29 && t1->file == t2->file
30 && t1->line == t2->line
31 && t1->expect == t2->expect;
34 static size_t rehash(const void *elem, void *priv)
36 return hash_trace(elem);
39 static void init_trace(struct trace *trace,
40 const char *condstr, const char *file, unsigned int line,
43 trace->condstr = condstr;
46 trace->expect = expect;
47 trace->count = trace->right = 0;
50 static struct trace *add_trace(const char *condstr,
51 const char *file, unsigned int line, bool expect)
53 struct trace *trace = malloc(sizeof(*trace));
54 init_trace(trace, condstr, file, line, expect);
55 htable_add(htable, hash_trace(trace), trace);
59 long _likely_trace(bool cond, bool expect,
61 const char *file, unsigned int line)
63 struct trace *p, trace;
66 htable = htable_new(rehash, NULL);
68 init_trace(&trace, condstr, file, line, expect);
69 p = htable_get(htable, hash_trace(&trace), hash_cmp, &trace);
71 p = add_trace(condstr, file, line, expect);
80 struct get_stats_info {
82 unsigned int min_hits;
86 static double right_ratio(const struct trace *t)
88 return (double)t->right / t->count;
91 static void get_stats(struct trace *trace, struct get_stats_info *info)
93 if (trace->count < info->min_hits)
96 if (right_ratio(trace) < info->worst_ratio) {
98 info->worst_ratio = right_ratio(trace);
102 const char *likely_stats(unsigned int min_hits, unsigned int percent)
104 struct get_stats_info info;
105 struct htable_iter i;
112 info.min_hits = min_hits;
114 info.worst_ratio = 2;
116 /* This is O(n), but it's not likely called that often. */
117 for (trace = htable_first(htable, &i);
119 trace = htable_next(htable,&i)) {
120 get_stats(trace, &info);
123 if (info.worst_ratio * 100 > percent)
126 ret = malloc(strlen(info.worst->condstr) +
127 strlen(info.worst->file) +
128 sizeof(long int) * 8 +
129 sizeof("%s:%u:%slikely(%s) correct %u%% (%lu/%lu)"));
130 sprintf(ret, "%s:%u:%slikely(%s) correct %u%% (%lu/%lu)",
131 info.worst->file, info.worst->line,
132 info.worst->expect ? "" : "un", info.worst->condstr,
133 (unsigned)(info.worst_ratio * 100),
134 info.worst->right, info.worst->count);
136 htable_del(htable, hash_trace(info.worst), info.worst);
141 #endif /*CCAN_LIKELY_DEBUG*/