thread.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #include "../perf.h"
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include "session.h"
  6. #include "thread.h"
  7. #include "util.h"
  8. #include "debug.h"
  9. #include "comm.h"
  10. struct thread *thread__new(pid_t pid, pid_t tid)
  11. {
  12. char *comm_str;
  13. struct comm *comm;
  14. struct thread *thread = zalloc(sizeof(*thread));
  15. if (thread != NULL) {
  16. map_groups__init(&thread->mg);
  17. thread->pid_ = pid;
  18. thread->tid = tid;
  19. thread->ppid = -1;
  20. INIT_LIST_HEAD(&thread->comm_list);
  21. comm_str = malloc(32);
  22. if (!comm_str)
  23. goto err_thread;
  24. snprintf(comm_str, 32, ":%d", tid);
  25. comm = comm__new(comm_str, 0);
  26. free(comm_str);
  27. if (!comm)
  28. goto err_thread;
  29. list_add(&comm->list, &thread->comm_list);
  30. }
  31. return thread;
  32. err_thread:
  33. free(thread);
  34. return NULL;
  35. }
  36. void thread__delete(struct thread *thread)
  37. {
  38. struct comm *comm, *tmp;
  39. map_groups__exit(&thread->mg);
  40. list_for_each_entry_safe(comm, tmp, &thread->comm_list, list) {
  41. list_del(&comm->list);
  42. comm__free(comm);
  43. }
  44. free(thread);
  45. }
  46. struct comm *thread__comm(const struct thread *thread)
  47. {
  48. if (list_empty(&thread->comm_list))
  49. return NULL;
  50. return list_first_entry(&thread->comm_list, struct comm, list);
  51. }
  52. /* CHECKME: time should always be 0 if event aren't ordered */
  53. int thread__set_comm(struct thread *thread, const char *str, u64 timestamp)
  54. {
  55. struct comm *new, *curr = thread__comm(thread);
  56. /* Override latest entry if it had no specific time coverage */
  57. if (!curr->start) {
  58. comm__override(curr, str, timestamp);
  59. return 0;
  60. }
  61. new = comm__new(str, timestamp);
  62. if (!new)
  63. return -ENOMEM;
  64. list_add(&new->list, &thread->comm_list);
  65. thread->comm_set = true;
  66. return 0;
  67. }
  68. const char *thread__comm_str(const struct thread *thread)
  69. {
  70. const struct comm *comm = thread__comm(thread);
  71. if (!comm)
  72. return NULL;
  73. return comm__str(comm);
  74. }
  75. /* CHECKME: it should probably better return the max comm len from its comm list */
  76. int thread__comm_len(struct thread *thread)
  77. {
  78. if (!thread->comm_len) {
  79. const char *comm = thread__comm_str(thread);
  80. if (!comm)
  81. return 0;
  82. thread->comm_len = strlen(comm);
  83. }
  84. return thread->comm_len;
  85. }
  86. size_t thread__fprintf(struct thread *thread, FILE *fp)
  87. {
  88. return fprintf(fp, "Thread %d %s\n", thread->tid, thread__comm_str(thread)) +
  89. map_groups__fprintf(&thread->mg, verbose, fp);
  90. }
  91. void thread__insert_map(struct thread *thread, struct map *map)
  92. {
  93. map_groups__fixup_overlappings(&thread->mg, map, verbose, stderr);
  94. map_groups__insert(&thread->mg, map);
  95. }
  96. int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
  97. {
  98. int i, err;
  99. if (parent->comm_set) {
  100. const char *comm = thread__comm_str(parent);
  101. if (!comm)
  102. return -ENOMEM;
  103. err = thread__set_comm(thread, comm, timestamp);
  104. if (!err)
  105. return err;
  106. thread->comm_set = true;
  107. }
  108. for (i = 0; i < MAP__NR_TYPES; ++i)
  109. if (map_groups__clone(&thread->mg, &parent->mg, i) < 0)
  110. return -ENOMEM;
  111. thread->ppid = parent->tid;
  112. return 0;
  113. }