Skip to contentSkip to conversation

perf tools: Add API for adding 'private' data to struct thread

RFC New David Ahern 1 participant 1 message Mar 5, 2012 perf events

lore
Share & tools
lore
#0 lore raw

RFC 1/1 perf tools: Add API for adding 'private' data to struct thread

Allow commands to attach 'private' data to a thread struct. This allows commands to avoid caching data locally with corresponding lookup code. Pointer to private data is obtained using thread__get_priv() and set using thread__set_priv.

If a struct thread is deleted, the corresponding private data is also freed. On fork and comm events (comm == exec right now) the privata data is freed.

The default handler for freeing private memory does a simple free(). If the private data is a complex structure with additional internal memory allocations users can define a callback:

    void (*priv_free)(void *p)

and set thread_conf.priv_free.

This API differs from symbol_conf wherein users set priv_size and the size of allocations is increased accordingly. This works fine for constant-sized allocations - as needed for symbol processing. However, a more flexible API is needed for threads to allow for more complicated associations of data.

---
 tools/perf/util/thread.c |   16 ++++++++++++++++
 tools/perf/util/thread.h |   16 ++++++++++++++++
 2 files changed, 32 insertions(+), 0 deletions(-)
tools/perf/util/thread.c +16 -0
index fb4b7ea..7dcb70f 100644
@@ -22,9 +22,22 @@ static struct thread *thread__new(pid_t pid)
 	return self;
 }
 
+struct thread_conf thread_conf = {
+	.priv_free = free,
+};
+
+static void thread__free_priv(struct thread *self)
+{
+	if (self->priv) {
+		thread_conf.priv_free(self->priv);
+		self->priv = NULL;
+	}
+}
+
 void thread__delete(struct thread *self)
 {
 	map_groups__exit(&self->mg);
+	thread__free_priv(self);
 	free(self->comm);
 	free(self);
 }
@@ -40,6 +53,7 @@ int thread__set_comm(struct thread *self, const char *comm)
 	if (!err) {
 		self->comm_set = true;
 		map_groups__flush(&self->mg);
+		thread__free_priv(self);
 	}
 	return err;
 }
@@ -110,6 +124,8 @@ int thread__fork(struct thread *self, struct thread *parent)
 {
 	int i;
 
+	thread__free_priv(self);
+
 	if (parent->comm_set) {
 		if (self->comm)
 			free(self->comm);
tools/perf/util/thread.h +16 -0
index 70c2c13..dc4e38f 100644
@@ -16,8 +16,14 @@ struct thread {
 	bool			comm_set;
 	char			*comm;
 	int			comm_len;
+	void			*priv;
 };
 
+struct thread_conf {
+	void (*priv_free)(void *p);
+};
+extern struct thread_conf thread_conf;
+
 struct machine;
 
 void thread__delete(struct thread *self);
@@ -41,4 +47,14 @@ void thread__find_addr_location(struct thread *thread, struct machine *machine,
 				u8 cpumode, enum map_type type, u64 addr,
 				struct addr_location *al,
 				symbol_filter_t filter);
+
+static inline void *thread__get_priv(struct thread *thread)
+{
+	return thread->priv;
+}
+
+static inline void thread__set_priv(struct thread *thread, void *p)
+{
+	thread->priv = p;
+}
 #endif	/* __PERF_THREAD_H */
Signature · 1 line
1.7.5.4