linux/tools/perf/util/comm.c
<<
>>
Prefs
   1#include "comm.h"
   2#include "util.h"
   3#include <errno.h>
   4#include <stdlib.h>
   5#include <stdio.h>
   6#include <string.h>
   7#include <linux/refcount.h>
   8
   9struct comm_str {
  10        char *str;
  11        struct rb_node rb_node;
  12        refcount_t refcnt;
  13};
  14
  15/* Should perhaps be moved to struct machine */
  16static struct rb_root comm_str_root;
  17
  18static struct comm_str *comm_str__get(struct comm_str *cs)
  19{
  20        if (cs)
  21                refcount_inc(&cs->refcnt);
  22        return cs;
  23}
  24
  25static void comm_str__put(struct comm_str *cs)
  26{
  27        if (cs && refcount_dec_and_test(&cs->refcnt)) {
  28                rb_erase(&cs->rb_node, &comm_str_root);
  29                zfree(&cs->str);
  30                free(cs);
  31        }
  32}
  33
  34static struct comm_str *comm_str__alloc(const char *str)
  35{
  36        struct comm_str *cs;
  37
  38        cs = zalloc(sizeof(*cs));
  39        if (!cs)
  40                return NULL;
  41
  42        cs->str = strdup(str);
  43        if (!cs->str) {
  44                free(cs);
  45                return NULL;
  46        }
  47
  48        refcount_set(&cs->refcnt, 1);
  49
  50        return cs;
  51}
  52
  53static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
  54{
  55        struct rb_node **p = &root->rb_node;
  56        struct rb_node *parent = NULL;
  57        struct comm_str *iter, *new;
  58        int cmp;
  59
  60        while (*p != NULL) {
  61                parent = *p;
  62                iter = rb_entry(parent, struct comm_str, rb_node);
  63
  64                cmp = strcmp(str, iter->str);
  65                if (!cmp)
  66                        return comm_str__get(iter);
  67
  68                if (cmp < 0)
  69                        p = &(*p)->rb_left;
  70                else
  71                        p = &(*p)->rb_right;
  72        }
  73
  74        new = comm_str__alloc(str);
  75        if (!new)
  76                return NULL;
  77
  78        rb_link_node(&new->rb_node, parent, p);
  79        rb_insert_color(&new->rb_node, root);
  80
  81        return new;
  82}
  83
  84struct comm *comm__new(const char *str, u64 timestamp, bool exec)
  85{
  86        struct comm *comm = zalloc(sizeof(*comm));
  87
  88        if (!comm)
  89                return NULL;
  90
  91        comm->start = timestamp;
  92        comm->exec = exec;
  93
  94        comm->comm_str = comm_str__findnew(str, &comm_str_root);
  95        if (!comm->comm_str) {
  96                free(comm);
  97                return NULL;
  98        }
  99
 100        return comm;
 101}
 102
 103int comm__override(struct comm *comm, const char *str, u64 timestamp, bool exec)
 104{
 105        struct comm_str *new, *old = comm->comm_str;
 106
 107        new = comm_str__findnew(str, &comm_str_root);
 108        if (!new)
 109                return -ENOMEM;
 110
 111        comm_str__put(old);
 112        comm->comm_str = new;
 113        comm->start = timestamp;
 114        if (exec)
 115                comm->exec = true;
 116
 117        return 0;
 118}
 119
 120void comm__free(struct comm *comm)
 121{
 122        comm_str__put(comm->comm_str);
 123        free(comm);
 124}
 125
 126const char *comm__str(const struct comm *comm)
 127{
 128        return comm->comm_str->str;
 129}
 130