values.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #include <stdlib.h>
  2. #include "util.h"
  3. #include "values.h"
  4. #include "debug.h"
  5. int perf_read_values_init(struct perf_read_values *values)
  6. {
  7. values->threads_max = 16;
  8. values->pid = malloc(values->threads_max * sizeof(*values->pid));
  9. values->tid = malloc(values->threads_max * sizeof(*values->tid));
  10. values->value = malloc(values->threads_max * sizeof(*values->value));
  11. if (!values->pid || !values->tid || !values->value) {
  12. pr_debug("failed to allocate read_values threads arrays");
  13. goto out_free_pid;
  14. }
  15. values->threads = 0;
  16. values->counters_max = 16;
  17. values->counterrawid = malloc(values->counters_max
  18. * sizeof(*values->counterrawid));
  19. values->countername = malloc(values->counters_max
  20. * sizeof(*values->countername));
  21. if (!values->counterrawid || !values->countername) {
  22. pr_debug("failed to allocate read_values counters arrays");
  23. goto out_free_counter;
  24. }
  25. values->counters = 0;
  26. return 0;
  27. out_free_counter:
  28. zfree(&values->counterrawid);
  29. zfree(&values->countername);
  30. out_free_pid:
  31. zfree(&values->pid);
  32. zfree(&values->tid);
  33. zfree(&values->value);
  34. return -ENOMEM;
  35. }
  36. void perf_read_values_destroy(struct perf_read_values *values)
  37. {
  38. int i;
  39. if (!values->threads_max || !values->counters_max)
  40. return;
  41. for (i = 0; i < values->threads; i++)
  42. zfree(&values->value[i]);
  43. zfree(&values->value);
  44. zfree(&values->pid);
  45. zfree(&values->tid);
  46. zfree(&values->counterrawid);
  47. for (i = 0; i < values->counters; i++)
  48. zfree(&values->countername[i]);
  49. zfree(&values->countername);
  50. }
  51. static int perf_read_values__enlarge_threads(struct perf_read_values *values)
  52. {
  53. int nthreads_max = values->threads_max * 2;
  54. void *npid = realloc(values->pid, nthreads_max * sizeof(*values->pid)),
  55. *ntid = realloc(values->tid, nthreads_max * sizeof(*values->tid)),
  56. *nvalue = realloc(values->value, nthreads_max * sizeof(*values->value));
  57. if (!npid || !ntid || !nvalue)
  58. goto out_err;
  59. values->threads_max = nthreads_max;
  60. values->pid = npid;
  61. values->tid = ntid;
  62. values->value = nvalue;
  63. return 0;
  64. out_err:
  65. free(npid);
  66. free(ntid);
  67. free(nvalue);
  68. pr_debug("failed to enlarge read_values threads arrays");
  69. return -ENOMEM;
  70. }
  71. static int perf_read_values__findnew_thread(struct perf_read_values *values,
  72. u32 pid, u32 tid)
  73. {
  74. int i;
  75. for (i = 0; i < values->threads; i++)
  76. if (values->pid[i] == pid && values->tid[i] == tid)
  77. return i;
  78. if (values->threads == values->threads_max) {
  79. i = perf_read_values__enlarge_threads(values);
  80. if (i < 0)
  81. return i;
  82. }
  83. i = values->threads + 1;
  84. values->value[i] = malloc(values->counters_max * sizeof(**values->value));
  85. if (!values->value[i]) {
  86. pr_debug("failed to allocate read_values counters array");
  87. return -ENOMEM;
  88. }
  89. values->pid[i] = pid;
  90. values->tid[i] = tid;
  91. values->threads = i;
  92. return i;
  93. }
  94. static void perf_read_values__enlarge_counters(struct perf_read_values *values)
  95. {
  96. int i;
  97. values->counters_max *= 2;
  98. values->counterrawid = realloc(values->counterrawid,
  99. values->counters_max * sizeof(*values->counterrawid));
  100. values->countername = realloc(values->countername,
  101. values->counters_max * sizeof(*values->countername));
  102. if (!values->counterrawid || !values->countername)
  103. die("failed to enlarge read_values counters arrays");
  104. for (i = 0; i < values->threads; i++) {
  105. values->value[i] = realloc(values->value[i],
  106. values->counters_max * sizeof(**values->value));
  107. if (!values->value[i])
  108. die("failed to enlarge read_values counters arrays");
  109. }
  110. }
  111. static int perf_read_values__findnew_counter(struct perf_read_values *values,
  112. u64 rawid, const char *name)
  113. {
  114. int i;
  115. for (i = 0; i < values->counters; i++)
  116. if (values->counterrawid[i] == rawid)
  117. return i;
  118. if (values->counters == values->counters_max)
  119. perf_read_values__enlarge_counters(values);
  120. i = values->counters++;
  121. values->counterrawid[i] = rawid;
  122. values->countername[i] = strdup(name);
  123. return i;
  124. }
  125. int perf_read_values_add_value(struct perf_read_values *values,
  126. u32 pid, u32 tid,
  127. u64 rawid, const char *name, u64 value)
  128. {
  129. int tindex, cindex;
  130. tindex = perf_read_values__findnew_thread(values, pid, tid);
  131. if (tindex < 0)
  132. return tindex;
  133. cindex = perf_read_values__findnew_counter(values, rawid, name);
  134. if (cindex < 0)
  135. return cindex;
  136. values->value[tindex][cindex] = value;
  137. return 0;
  138. }
  139. static void perf_read_values__display_pretty(FILE *fp,
  140. struct perf_read_values *values)
  141. {
  142. int i, j;
  143. int pidwidth, tidwidth;
  144. int *counterwidth;
  145. counterwidth = malloc(values->counters * sizeof(*counterwidth));
  146. if (!counterwidth)
  147. die("failed to allocate counterwidth array");
  148. tidwidth = 3;
  149. pidwidth = 3;
  150. for (j = 0; j < values->counters; j++)
  151. counterwidth[j] = strlen(values->countername[j]);
  152. for (i = 0; i < values->threads; i++) {
  153. int width;
  154. width = snprintf(NULL, 0, "%d", values->pid[i]);
  155. if (width > pidwidth)
  156. pidwidth = width;
  157. width = snprintf(NULL, 0, "%d", values->tid[i]);
  158. if (width > tidwidth)
  159. tidwidth = width;
  160. for (j = 0; j < values->counters; j++) {
  161. width = snprintf(NULL, 0, "%" PRIu64, values->value[i][j]);
  162. if (width > counterwidth[j])
  163. counterwidth[j] = width;
  164. }
  165. }
  166. fprintf(fp, "# %*s %*s", pidwidth, "PID", tidwidth, "TID");
  167. for (j = 0; j < values->counters; j++)
  168. fprintf(fp, " %*s", counterwidth[j], values->countername[j]);
  169. fprintf(fp, "\n");
  170. for (i = 0; i < values->threads; i++) {
  171. fprintf(fp, " %*d %*d", pidwidth, values->pid[i],
  172. tidwidth, values->tid[i]);
  173. for (j = 0; j < values->counters; j++)
  174. fprintf(fp, " %*" PRIu64,
  175. counterwidth[j], values->value[i][j]);
  176. fprintf(fp, "\n");
  177. }
  178. free(counterwidth);
  179. }
  180. static void perf_read_values__display_raw(FILE *fp,
  181. struct perf_read_values *values)
  182. {
  183. int width, pidwidth, tidwidth, namewidth, rawwidth, countwidth;
  184. int i, j;
  185. tidwidth = 3; /* TID */
  186. pidwidth = 3; /* PID */
  187. namewidth = 4; /* "Name" */
  188. rawwidth = 3; /* "Raw" */
  189. countwidth = 5; /* "Count" */
  190. for (i = 0; i < values->threads; i++) {
  191. width = snprintf(NULL, 0, "%d", values->pid[i]);
  192. if (width > pidwidth)
  193. pidwidth = width;
  194. width = snprintf(NULL, 0, "%d", values->tid[i]);
  195. if (width > tidwidth)
  196. tidwidth = width;
  197. }
  198. for (j = 0; j < values->counters; j++) {
  199. width = strlen(values->countername[j]);
  200. if (width > namewidth)
  201. namewidth = width;
  202. width = snprintf(NULL, 0, "%" PRIx64, values->counterrawid[j]);
  203. if (width > rawwidth)
  204. rawwidth = width;
  205. }
  206. for (i = 0; i < values->threads; i++) {
  207. for (j = 0; j < values->counters; j++) {
  208. width = snprintf(NULL, 0, "%" PRIu64, values->value[i][j]);
  209. if (width > countwidth)
  210. countwidth = width;
  211. }
  212. }
  213. fprintf(fp, "# %*s %*s %*s %*s %*s\n",
  214. pidwidth, "PID", tidwidth, "TID",
  215. namewidth, "Name", rawwidth, "Raw",
  216. countwidth, "Count");
  217. for (i = 0; i < values->threads; i++)
  218. for (j = 0; j < values->counters; j++)
  219. fprintf(fp, " %*d %*d %*s %*" PRIx64 " %*" PRIu64,
  220. pidwidth, values->pid[i],
  221. tidwidth, values->tid[i],
  222. namewidth, values->countername[j],
  223. rawwidth, values->counterrawid[j],
  224. countwidth, values->value[i][j]);
  225. }
  226. void perf_read_values_display(FILE *fp, struct perf_read_values *values, int raw)
  227. {
  228. if (raw)
  229. perf_read_values__display_raw(fp, values);
  230. else
  231. perf_read_values__display_pretty(fp, values);
  232. }