mirror of
				https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
				synced 2025-10-31 20:42:39 +00:00 
			
		
		
		
	 3e3405906d
			
		
	
	
		3e3405906d
		
	
	
	
	
		
			
			Fix --del option to update current existing event list after perf probe deleted an event. Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Jim Keniston <jkenisto@us.ibm.com> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com> Cc: Christoph Hellwig <hch@infradead.org> Cc: Frank Ch. Eigler <fche@redhat.com> Cc: Jason Baron <jbaron@redhat.com> Cc: K.Prasad <prasad@linux.vnet.ibm.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: systemtap <systemtap@sources.redhat.com> Cc: DLE <dle-develop@lists.sourceforge.net> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <20091215153149.17436.61265.stgit@dhcp-100-2-132.bos.redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
		
			
				
	
	
		
			201 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			201 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
 | |
|  *
 | |
|  * Licensed under the GPLv2.
 | |
|  */
 | |
| 
 | |
| #include "strlist.h"
 | |
| #include <errno.h>
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| 
 | |
| static struct str_node *str_node__new(const char *s, bool dupstr)
 | |
| {
 | |
| 	struct str_node *self = malloc(sizeof(*self));
 | |
| 
 | |
| 	if (self != NULL) {
 | |
| 		if (dupstr) {
 | |
| 			s = strdup(s);
 | |
| 			if (s == NULL)
 | |
| 				goto out_delete;
 | |
| 		}
 | |
| 		self->s = s;
 | |
| 	}
 | |
| 
 | |
| 	return self;
 | |
| 
 | |
| out_delete:
 | |
| 	free(self);
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| static void str_node__delete(struct str_node *self, bool dupstr)
 | |
| {
 | |
| 	if (dupstr)
 | |
| 		free((void *)self->s);
 | |
| 	free(self);
 | |
| }
 | |
| 
 | |
| int strlist__add(struct strlist *self, const char *new_entry)
 | |
| {
 | |
| 	struct rb_node **p = &self->entries.rb_node;
 | |
| 	struct rb_node *parent = NULL;
 | |
| 	struct str_node *sn;
 | |
| 
 | |
| 	while (*p != NULL) {
 | |
| 		int rc;
 | |
| 
 | |
| 		parent = *p;
 | |
| 		sn = rb_entry(parent, struct str_node, rb_node);
 | |
| 		rc = strcmp(sn->s, new_entry);
 | |
| 
 | |
| 		if (rc > 0)
 | |
| 			p = &(*p)->rb_left;
 | |
| 		else if (rc < 0)
 | |
| 			p = &(*p)->rb_right;
 | |
| 		else
 | |
| 			return -EEXIST;
 | |
| 	}
 | |
| 
 | |
| 	sn = str_node__new(new_entry, self->dupstr);
 | |
| 	if (sn == NULL)
 | |
| 		return -ENOMEM;
 | |
| 
 | |
| 	rb_link_node(&sn->rb_node, parent, p);
 | |
| 	rb_insert_color(&sn->rb_node, &self->entries);
 | |
| 	++self->nr_entries;
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int strlist__load(struct strlist *self, const char *filename)
 | |
| {
 | |
| 	char entry[1024];
 | |
| 	int err;
 | |
| 	FILE *fp = fopen(filename, "r");
 | |
| 
 | |
| 	if (fp == NULL)
 | |
| 		return errno;
 | |
| 
 | |
| 	while (fgets(entry, sizeof(entry), fp) != NULL) {
 | |
| 		const size_t len = strlen(entry);
 | |
| 
 | |
| 		if (len == 0)
 | |
| 			continue;
 | |
| 		entry[len - 1] = '\0';
 | |
| 
 | |
| 		err = strlist__add(self, entry);
 | |
| 		if (err != 0)
 | |
| 			goto out;
 | |
| 	}
 | |
| 
 | |
| 	err = 0;
 | |
| out:
 | |
| 	fclose(fp);
 | |
| 	return err;
 | |
| }
 | |
| 
 | |
| void strlist__remove(struct strlist *self, struct str_node *sn)
 | |
| {
 | |
| 	rb_erase(&sn->rb_node, &self->entries);
 | |
| 	str_node__delete(sn, self->dupstr);
 | |
| }
 | |
| 
 | |
| struct str_node *strlist__find(struct strlist *self, const char *entry)
 | |
| {
 | |
| 	struct rb_node **p = &self->entries.rb_node;
 | |
| 	struct rb_node *parent = NULL;
 | |
| 
 | |
| 	while (*p != NULL) {
 | |
| 		struct str_node *sn;
 | |
| 		int rc;
 | |
| 
 | |
| 		parent = *p;
 | |
| 		sn = rb_entry(parent, struct str_node, rb_node);
 | |
| 		rc = strcmp(sn->s, entry);
 | |
| 
 | |
| 		if (rc > 0)
 | |
| 			p = &(*p)->rb_left;
 | |
| 		else if (rc < 0)
 | |
| 			p = &(*p)->rb_right;
 | |
| 		else
 | |
| 			return sn;
 | |
| 	}
 | |
| 
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| static int strlist__parse_list_entry(struct strlist *self, const char *s)
 | |
| {
 | |
| 	if (strncmp(s, "file://", 7) == 0)
 | |
| 		return strlist__load(self, s + 7);
 | |
| 
 | |
| 	return strlist__add(self, s);
 | |
| }
 | |
| 
 | |
| int strlist__parse_list(struct strlist *self, const char *s)
 | |
| {
 | |
| 	char *sep;
 | |
| 	int err;
 | |
| 
 | |
| 	while ((sep = strchr(s, ',')) != NULL) {
 | |
| 		*sep = '\0';
 | |
| 		err = strlist__parse_list_entry(self, s);
 | |
| 		*sep = ',';
 | |
| 		if (err != 0)
 | |
| 			return err;
 | |
| 		s = sep + 1;
 | |
| 	}
 | |
| 
 | |
| 	return *s ? strlist__parse_list_entry(self, s) : 0;
 | |
| }
 | |
| 
 | |
| struct strlist *strlist__new(bool dupstr, const char *slist)
 | |
| {
 | |
| 	struct strlist *self = malloc(sizeof(*self));
 | |
| 
 | |
| 	if (self != NULL) {
 | |
| 		self->entries	 = RB_ROOT;
 | |
| 		self->dupstr	 = dupstr;
 | |
| 		self->nr_entries = 0;
 | |
| 		if (slist && strlist__parse_list(self, slist) != 0)
 | |
| 			goto out_error;
 | |
| 	}
 | |
| 
 | |
| 	return self;
 | |
| out_error:
 | |
| 	free(self);
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| void strlist__delete(struct strlist *self)
 | |
| {
 | |
| 	if (self != NULL) {
 | |
| 		struct str_node *pos;
 | |
| 		struct rb_node *next = rb_first(&self->entries);
 | |
| 
 | |
| 		while (next) {
 | |
| 			pos = rb_entry(next, struct str_node, rb_node);
 | |
| 			next = rb_next(&pos->rb_node);
 | |
| 			strlist__remove(self, pos);
 | |
| 		}
 | |
| 		self->entries = RB_ROOT;
 | |
| 		free(self);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| struct str_node *strlist__entry(const struct strlist *self, unsigned int idx)
 | |
| {
 | |
| 	struct rb_node *nd;
 | |
| 
 | |
| 	for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
 | |
| 		struct str_node *pos = rb_entry(nd, struct str_node, rb_node);
 | |
| 
 | |
| 		if (!idx--)
 | |
| 			return pos;
 | |
| 	}
 | |
| 
 | |
| 	return NULL;
 | |
| }
 |