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