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