Source
x
// SPDX-License-Identifier: GPL-2.0
/*
* Infrastructure for statistic tracing (histogram output).
*
* Copyright (C) 2008-2009 Frederic Weisbecker <fweisbec@gmail.com>
*
* Based on the code from trace_branch.c which is
* Copyright (C) 2008 Steven Rostedt <srostedt@redhat.com>
*
*/
/*
* List of stat red-black nodes from a tracer
* We use a such tree to sort quickly the stat
* entries from the tracer.
*/
struct stat_node {
struct rb_node node;
void *stat;
};
/* A stat session is the stats output in one file */
struct stat_session {
struct list_head session_list;
struct tracer_stat *ts;
struct rb_root stat_root;
struct mutex stat_mutex;
struct dentry *file;
};
/* All of the sessions currently in use. Each stat file embed one session */
static LIST_HEAD(all_stat_sessions);
static DEFINE_MUTEX(all_stat_sessions_mutex);
/* The root directory for all stat files */
static struct dentry *stat_dir;
static void __reset_stat_session(struct stat_session *session)
{
struct stat_node *snode, *n;
rbtree_postorder_for_each_entry_safe(snode, n, &session->stat_root, node) {
if (session->ts->stat_release)
session->ts->stat_release(snode->stat);
kfree(snode);
}
session->stat_root = RB_ROOT;
}
static void reset_stat_session(struct stat_session *session)
{
mutex_lock(&session->stat_mutex);
__reset_stat_session(session);
mutex_unlock(&session->stat_mutex);
}
static void destroy_session(struct stat_session *session)
{
tracefs_remove(session->file);
__reset_stat_session(session);
mutex_destroy(&session->stat_mutex);
kfree(session);
}
typedef int (*cmp_stat_t)(void *, void *);
static int insert_stat(struct rb_root *root, void *stat, cmp_stat_t cmp)
{
struct rb_node **new = &(root->rb_node), *parent = NULL;
struct stat_node *data;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->stat = stat;
/*
* Figure out where to put new node
* This is a descendent sorting
*/
while (*new) {
struct stat_node *this;