comm.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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. struct comm_str {
  11. char *str;
  12. struct rb_node rb_node;
  13. refcount_t refcnt;
  14. };
  15. /* Should perhaps be moved to struct machine */
  16. static struct rb_root comm_str_root;
  17. static struct rw_semaphore comm_str_lock = {.lock = PTHREAD_RWLOCK_INITIALIZER,};
  18. static struct comm_str *comm_str__get(struct comm_str *cs)
  19. {
  20. if (cs)
  21. refcount_inc(&cs->refcnt);
  22. return cs;
  23. }
  24. static void comm_str__put(struct comm_str *cs)
  25. {
  26. if (cs && refcount_dec_and_test(&cs->refcnt)) {
  27. down_write(&comm_str_lock);
  28. rb_erase(&cs->rb_node, &comm_str_root);
  29. up_write(&comm_str_lock);
  30. zfree(&cs->str);
  31. free(cs);
  32. }
  33. }
  34. static struct comm_str *comm_str__alloc(const char *str)
  35. {
  36. struct comm_str *cs;
  37. cs = zalloc(sizeof(*cs));
  38. if (!cs)
  39. return NULL;
  40. cs->str = strdup(str);
  41. if (!cs->str) {
  42. free(cs);
  43. return NULL;
  44. }
  45. refcount_set(&cs->refcnt, 1);
  46. return cs;
  47. }
  48. static
  49. struct comm_str *__comm_str__findnew(const char *str, struct rb_root *root)
  50. {
  51. struct rb_node **p = &root->rb_node;
  52. struct rb_node *parent = NULL;
  53. struct comm_str *iter, *new;
  54. int cmp;
  55. while (*p != NULL) {
  56. parent = *p;
  57. iter = rb_entry(parent, struct comm_str, rb_node);
  58. cmp = strcmp(str, iter->str);
  59. if (!cmp)
  60. return comm_str__get(iter);
  61. if (cmp < 0)
  62. p = &(*p)->rb_left;
  63. else
  64. p = &(*p)->rb_right;
  65. }
  66. new = comm_str__alloc(str);
  67. if (!new)
  68. return NULL;
  69. rb_link_node(&new->rb_node, parent, p);
  70. rb_insert_color(&new->rb_node, root);
  71. return new;
  72. }
  73. static struct comm_str *comm_str__findnew(const char *str, struct rb_root *root)
  74. {
  75. struct comm_str *cs;
  76. down_write(&comm_str_lock);
  77. cs = __comm_str__findnew(str, root);
  78. up_write(&comm_str_lock);
  79. return cs;
  80. }
  81. struct comm *comm__new(const char *str, u64 timestamp, bool exec)
  82. {
  83. struct comm *comm = zalloc(sizeof(*comm));
  84. if (!comm)
  85. return NULL;
  86. comm->start = timestamp;
  87. comm->exec = exec;
  88. comm->comm_str = comm_str__findnew(str, &comm_str_root);
  89. if (!comm->comm_str) {
  90. free(comm);
  91. return NULL;
  92. }
  93. return comm;
  94. }
  95. int comm__override(struct comm *comm, const char *str, u64 timestamp, bool exec)
  96. {
  97. struct comm_str *new, *old = comm->comm_str;
  98. new = comm_str__findnew(str, &comm_str_root);
  99. if (!new)
  100. return -ENOMEM;
  101. comm_str__put(old);
  102. comm->comm_str = new;
  103. comm->start = timestamp;
  104. if (exec)
  105. comm->exec = true;
  106. return 0;
  107. }
  108. void comm__free(struct comm *comm)
  109. {
  110. comm_str__put(comm->comm_str);
  111. free(comm);
  112. }
  113. const char *comm__str(const struct comm *comm)
  114. {
  115. return comm->comm_str->str;
  116. }