3178f58b98
The comm overriding API ignores memory allocation failures by silently keeping the previous and out of date comm. As a result, the user may get buggy events without ever being notified about the problem and its source. Lets start to fix this by propagating the error from the API. Not all callers may be doing proper error handling on comm set yet but this is the first step toward it. Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com> Acked-by: Namhyung Kim <namhyung@kernel.org> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Link: http://lkml.kernel.org/r/1389713836-13375-2-git-send-email-fweisbec@gmail.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
123 lines
2.0 KiB
C
123 lines
2.0 KiB
C
#include "comm.h"
|
|
#include "util.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
struct comm_str {
|
|
char *str;
|
|
struct rb_node rb_node;
|
|
int ref;
|
|
};
|
|
|
|
/* Should perhaps be moved to struct machine */
|
|
static struct rb_root comm_str_root;
|
|
|
|
static void comm_str__get(struct comm_str *cs)
|
|
{
|
|
cs->ref++;
|
|
}
|
|
|
|
static void comm_str__put(struct comm_str *cs)
|
|
{
|
|
if (!--cs->ref) {
|
|
rb_erase(&cs->rb_node, &comm_str_root);
|
|
zfree(&cs->str);
|
|
free(cs);
|
|
}
|
|
}
|
|
|
|
static struct comm_str *comm_str__alloc(const char *str)
|
|
{
|
|
struct comm_str *cs;
|
|
|
|
cs = zalloc(sizeof(*cs));
|
|
if (!cs)
|
|
return NULL;
|
|
|
|
cs->str = strdup(str);
|
|
if (!cs->str) {
|
|
free(cs);
|
|
return NULL;
|
|
}
|
|
|
|
return cs;
|
|
}
|
|
|
|
static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
|
|
{
|
|
struct rb_node **p = &root->rb_node;
|
|
struct rb_node *parent = NULL;
|
|
struct comm_str *iter, *new;
|
|
int cmp;
|
|
|
|
while (*p != NULL) {
|
|
parent = *p;
|
|
iter = rb_entry(parent, struct comm_str, rb_node);
|
|
|
|
cmp = strcmp(str, iter->str);
|
|
if (!cmp)
|
|
return iter;
|
|
|
|
if (cmp < 0)
|
|
p = &(*p)->rb_left;
|
|
else
|
|
p = &(*p)->rb_right;
|
|
}
|
|
|
|
new = comm_str__alloc(str);
|
|
if (!new)
|
|
return NULL;
|
|
|
|
rb_link_node(&new->rb_node, parent, p);
|
|
rb_insert_color(&new->rb_node, root);
|
|
|
|
return new;
|
|
}
|
|
|
|
struct comm *comm__new(const char *str, u64 timestamp)
|
|
{
|
|
struct comm *comm = zalloc(sizeof(*comm));
|
|
|
|
if (!comm)
|
|
return NULL;
|
|
|
|
comm->start = timestamp;
|
|
|
|
comm->comm_str = comm_str__findnew(str, &comm_str_root);
|
|
if (!comm->comm_str) {
|
|
free(comm);
|
|
return NULL;
|
|
}
|
|
|
|
comm_str__get(comm->comm_str);
|
|
|
|
return comm;
|
|
}
|
|
|
|
int comm__override(struct comm *comm, const char *str, u64 timestamp)
|
|
{
|
|
struct comm_str *new, *old = comm->comm_str;
|
|
|
|
new = comm_str__findnew(str, &comm_str_root);
|
|
if (!new)
|
|
return -ENOMEM;
|
|
|
|
comm_str__get(new);
|
|
comm_str__put(old);
|
|
comm->comm_str = new;
|
|
comm->start = timestamp;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void comm__free(struct comm *comm)
|
|
{
|
|
comm_str__put(comm->comm_str);
|
|
free(comm);
|
|
}
|
|
|
|
const char *comm__str(const struct comm *comm)
|
|
{
|
|
return comm->comm_str->str;
|
|
}
|