comm.c 2.2 KB

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