simple.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. /*
  2. * Simple trace backend
  3. *
  4. * Copyright IBM, Corp. 2010
  5. *
  6. * This work is licensed under the terms of the GNU GPL, version 2. See
  7. * the COPYING file in the top-level directory.
  8. *
  9. */
  10. #include "qemu/osdep.h"
  11. #ifndef _WIN32
  12. #include <pthread.h>
  13. #endif
  14. #include "qemu/timer.h"
  15. #include "trace/control.h"
  16. #include "trace/simple.h"
  17. #include "qemu/error-report.h"
  18. #include "qemu/qemu-print.h"
  19. /** Trace file header event ID, picked to avoid conflict with real event IDs */
  20. #define HEADER_EVENT_ID (~(uint64_t)0)
  21. /** Trace file magic number */
  22. #define HEADER_MAGIC 0xf2b177cb0aa429b4ULL
  23. /** Trace file version number, bump if format changes */
  24. #define HEADER_VERSION 4
  25. /** Records were dropped event ID */
  26. #define DROPPED_EVENT_ID (~(uint64_t)0 - 1)
  27. /** Trace record is valid */
  28. #define TRACE_RECORD_VALID ((uint64_t)1 << 63)
  29. /*
  30. * Trace records are written out by a dedicated thread. The thread waits for
  31. * records to become available, writes them out, and then waits again.
  32. */
  33. static GMutex trace_lock;
  34. static GCond trace_available_cond;
  35. static GCond trace_empty_cond;
  36. static bool trace_available;
  37. static bool trace_writeout_enabled;
  38. enum {
  39. TRACE_BUF_LEN = 4096 * 64,
  40. TRACE_BUF_FLUSH_THRESHOLD = TRACE_BUF_LEN / 4,
  41. };
  42. uint8_t trace_buf[TRACE_BUF_LEN];
  43. static volatile gint trace_idx;
  44. static unsigned int writeout_idx;
  45. static volatile gint dropped_events;
  46. static uint32_t trace_pid;
  47. static FILE *trace_fp;
  48. static char *trace_file_name;
  49. #define TRACE_RECORD_TYPE_MAPPING 0
  50. #define TRACE_RECORD_TYPE_EVENT 1
  51. /* * Trace buffer entry */
  52. typedef struct {
  53. uint64_t event; /* event ID value */
  54. uint64_t timestamp_ns;
  55. uint32_t length; /* in bytes */
  56. uint32_t pid;
  57. uint64_t arguments[];
  58. } TraceRecord;
  59. typedef struct {
  60. uint64_t header_event_id; /* HEADER_EVENT_ID */
  61. uint64_t header_magic; /* HEADER_MAGIC */
  62. uint64_t header_version; /* HEADER_VERSION */
  63. } TraceLogHeader;
  64. static void read_from_buffer(unsigned int idx, void *dataptr, size_t size);
  65. static unsigned int write_to_buffer(unsigned int idx, void *dataptr, size_t size);
  66. static void clear_buffer_range(unsigned int idx, size_t len)
  67. {
  68. uint32_t num = 0;
  69. while (num < len) {
  70. if (idx >= TRACE_BUF_LEN) {
  71. idx = idx % TRACE_BUF_LEN;
  72. }
  73. trace_buf[idx++] = 0;
  74. num++;
  75. }
  76. }
  77. /**
  78. * Read a trace record from the trace buffer
  79. *
  80. * @idx Trace buffer index
  81. * @record Trace record to fill
  82. *
  83. * Returns false if the record is not valid.
  84. */
  85. static bool get_trace_record(unsigned int idx, TraceRecord **recordptr)
  86. {
  87. uint64_t event_flag = 0;
  88. TraceRecord record;
  89. /* read the event flag to see if its a valid record */
  90. read_from_buffer(idx, &record, sizeof(event_flag));
  91. if (!(record.event & TRACE_RECORD_VALID)) {
  92. return false;
  93. }
  94. smp_rmb(); /* read memory barrier before accessing record */
  95. /* read the record header to know record length */
  96. read_from_buffer(idx, &record, sizeof(TraceRecord));
  97. *recordptr = malloc(record.length); /* don't use g_malloc, can deadlock when traced */
  98. /* make a copy of record to avoid being overwritten */
  99. read_from_buffer(idx, *recordptr, record.length);
  100. smp_rmb(); /* memory barrier before clearing valid flag */
  101. (*recordptr)->event &= ~TRACE_RECORD_VALID;
  102. /* clear the trace buffer range for consumed record otherwise any byte
  103. * with its MSB set may be considered as a valid event id when the writer
  104. * thread crosses this range of buffer again.
  105. */
  106. clear_buffer_range(idx, record.length);
  107. return true;
  108. }
  109. /**
  110. * Kick writeout thread
  111. *
  112. * @wait Whether to wait for writeout thread to complete
  113. */
  114. static void flush_trace_file(bool wait)
  115. {
  116. g_mutex_lock(&trace_lock);
  117. trace_available = true;
  118. g_cond_signal(&trace_available_cond);
  119. if (wait) {
  120. g_cond_wait(&trace_empty_cond, &trace_lock);
  121. }
  122. g_mutex_unlock(&trace_lock);
  123. }
  124. static void wait_for_trace_records_available(void)
  125. {
  126. g_mutex_lock(&trace_lock);
  127. while (!(trace_available && trace_writeout_enabled)) {
  128. g_cond_signal(&trace_empty_cond);
  129. g_cond_wait(&trace_available_cond, &trace_lock);
  130. }
  131. trace_available = false;
  132. g_mutex_unlock(&trace_lock);
  133. }
  134. static gpointer writeout_thread(gpointer opaque)
  135. {
  136. TraceRecord *recordptr;
  137. union {
  138. TraceRecord rec;
  139. uint8_t bytes[sizeof(TraceRecord) + sizeof(uint64_t)];
  140. } dropped;
  141. unsigned int idx = 0;
  142. int dropped_count;
  143. size_t unused __attribute__ ((unused));
  144. uint64_t type = TRACE_RECORD_TYPE_EVENT;
  145. for (;;) {
  146. wait_for_trace_records_available();
  147. if (g_atomic_int_get(&dropped_events)) {
  148. dropped.rec.event = DROPPED_EVENT_ID;
  149. dropped.rec.timestamp_ns = get_clock();
  150. dropped.rec.length = sizeof(TraceRecord) + sizeof(uint64_t);
  151. dropped.rec.pid = trace_pid;
  152. do {
  153. dropped_count = g_atomic_int_get(&dropped_events);
  154. } while (!g_atomic_int_compare_and_exchange(&dropped_events,
  155. dropped_count, 0));
  156. dropped.rec.arguments[0] = dropped_count;
  157. unused = fwrite(&type, sizeof(type), 1, trace_fp);
  158. unused = fwrite(&dropped.rec, dropped.rec.length, 1, trace_fp);
  159. }
  160. while (get_trace_record(idx, &recordptr)) {
  161. unused = fwrite(&type, sizeof(type), 1, trace_fp);
  162. unused = fwrite(recordptr, recordptr->length, 1, trace_fp);
  163. writeout_idx += recordptr->length;
  164. free(recordptr); /* don't use g_free, can deadlock when traced */
  165. idx = writeout_idx % TRACE_BUF_LEN;
  166. }
  167. fflush(trace_fp);
  168. }
  169. return NULL;
  170. }
  171. void trace_record_write_u64(TraceBufferRecord *rec, uint64_t val)
  172. {
  173. rec->rec_off = write_to_buffer(rec->rec_off, &val, sizeof(uint64_t));
  174. }
  175. void trace_record_write_str(TraceBufferRecord *rec, const char *s, uint32_t slen)
  176. {
  177. /* Write string length first */
  178. rec->rec_off = write_to_buffer(rec->rec_off, &slen, sizeof(slen));
  179. /* Write actual string now */
  180. rec->rec_off = write_to_buffer(rec->rec_off, (void*)s, slen);
  181. }
  182. int trace_record_start(TraceBufferRecord *rec, uint32_t event, size_t datasize)
  183. {
  184. unsigned int idx, rec_off, old_idx, new_idx;
  185. uint32_t rec_len = sizeof(TraceRecord) + datasize;
  186. uint64_t event_u64 = event;
  187. uint64_t timestamp_ns = get_clock();
  188. do {
  189. old_idx = g_atomic_int_get(&trace_idx);
  190. smp_rmb();
  191. new_idx = old_idx + rec_len;
  192. if (new_idx - writeout_idx > TRACE_BUF_LEN) {
  193. /* Trace Buffer Full, Event dropped ! */
  194. g_atomic_int_inc(&dropped_events);
  195. return -ENOSPC;
  196. }
  197. } while (!g_atomic_int_compare_and_exchange(&trace_idx, old_idx, new_idx));
  198. idx = old_idx % TRACE_BUF_LEN;
  199. rec_off = idx;
  200. rec_off = write_to_buffer(rec_off, &event_u64, sizeof(event_u64));
  201. rec_off = write_to_buffer(rec_off, &timestamp_ns, sizeof(timestamp_ns));
  202. rec_off = write_to_buffer(rec_off, &rec_len, sizeof(rec_len));
  203. rec_off = write_to_buffer(rec_off, &trace_pid, sizeof(trace_pid));
  204. rec->tbuf_idx = idx;
  205. rec->rec_off = (idx + sizeof(TraceRecord)) % TRACE_BUF_LEN;
  206. return 0;
  207. }
  208. static void read_from_buffer(unsigned int idx, void *dataptr, size_t size)
  209. {
  210. uint8_t *data_ptr = dataptr;
  211. uint32_t x = 0;
  212. while (x < size) {
  213. if (idx >= TRACE_BUF_LEN) {
  214. idx = idx % TRACE_BUF_LEN;
  215. }
  216. data_ptr[x++] = trace_buf[idx++];
  217. }
  218. }
  219. static unsigned int write_to_buffer(unsigned int idx, void *dataptr, size_t size)
  220. {
  221. uint8_t *data_ptr = dataptr;
  222. uint32_t x = 0;
  223. while (x < size) {
  224. if (idx >= TRACE_BUF_LEN) {
  225. idx = idx % TRACE_BUF_LEN;
  226. }
  227. trace_buf[idx++] = data_ptr[x++];
  228. }
  229. return idx; /* most callers wants to know where to write next */
  230. }
  231. void trace_record_finish(TraceBufferRecord *rec)
  232. {
  233. TraceRecord record;
  234. read_from_buffer(rec->tbuf_idx, &record, sizeof(TraceRecord));
  235. smp_wmb(); /* write barrier before marking as valid */
  236. record.event |= TRACE_RECORD_VALID;
  237. write_to_buffer(rec->tbuf_idx, &record, sizeof(TraceRecord));
  238. if (((unsigned int)g_atomic_int_get(&trace_idx) - writeout_idx)
  239. > TRACE_BUF_FLUSH_THRESHOLD) {
  240. flush_trace_file(false);
  241. }
  242. }
  243. static int st_write_event_mapping(void)
  244. {
  245. uint64_t type = TRACE_RECORD_TYPE_MAPPING;
  246. TraceEventIter iter;
  247. TraceEvent *ev;
  248. trace_event_iter_init(&iter, NULL);
  249. while ((ev = trace_event_iter_next(&iter)) != NULL) {
  250. uint64_t id = trace_event_get_id(ev);
  251. const char *name = trace_event_get_name(ev);
  252. uint32_t len = strlen(name);
  253. if (fwrite(&type, sizeof(type), 1, trace_fp) != 1 ||
  254. fwrite(&id, sizeof(id), 1, trace_fp) != 1 ||
  255. fwrite(&len, sizeof(len), 1, trace_fp) != 1 ||
  256. fwrite(name, len, 1, trace_fp) != 1) {
  257. return -1;
  258. }
  259. }
  260. return 0;
  261. }
  262. void st_set_trace_file_enabled(bool enable)
  263. {
  264. if (enable == !!trace_fp) {
  265. return; /* no change */
  266. }
  267. /* Halt trace writeout */
  268. flush_trace_file(true);
  269. trace_writeout_enabled = false;
  270. flush_trace_file(true);
  271. if (enable) {
  272. static const TraceLogHeader header = {
  273. .header_event_id = HEADER_EVENT_ID,
  274. .header_magic = HEADER_MAGIC,
  275. /* Older log readers will check for version at next location */
  276. .header_version = HEADER_VERSION,
  277. };
  278. trace_fp = fopen(trace_file_name, "wb");
  279. if (!trace_fp) {
  280. return;
  281. }
  282. if (fwrite(&header, sizeof header, 1, trace_fp) != 1 ||
  283. st_write_event_mapping() < 0) {
  284. fclose(trace_fp);
  285. trace_fp = NULL;
  286. return;
  287. }
  288. /* Resume trace writeout */
  289. trace_writeout_enabled = true;
  290. flush_trace_file(false);
  291. } else {
  292. fclose(trace_fp);
  293. trace_fp = NULL;
  294. }
  295. }
  296. /**
  297. * Set the name of a trace file
  298. *
  299. * @file The trace file name or NULL for the default name-<pid> set at
  300. * config time
  301. */
  302. void st_set_trace_file(const char *file)
  303. {
  304. st_set_trace_file_enabled(false);
  305. g_free(trace_file_name);
  306. if (!file) {
  307. /* Type cast needed for Windows where getpid() returns an int. */
  308. trace_file_name = g_strdup_printf(CONFIG_TRACE_FILE, (pid_t)getpid());
  309. } else {
  310. trace_file_name = g_strdup_printf("%s", file);
  311. }
  312. st_set_trace_file_enabled(true);
  313. }
  314. void st_print_trace_file_status(void)
  315. {
  316. qemu_printf("Trace file \"%s\" %s.\n",
  317. trace_file_name, trace_fp ? "on" : "off");
  318. }
  319. void st_flush_trace_buffer(void)
  320. {
  321. flush_trace_file(true);
  322. }
  323. /* Helper function to create a thread with signals blocked. Use glib's
  324. * portable threads since QEMU abstractions cannot be used due to reentrancy in
  325. * the tracer. Also note the signal masking on POSIX hosts so that the thread
  326. * does not steal signals when the rest of the program wants them blocked.
  327. */
  328. static GThread *trace_thread_create(GThreadFunc fn)
  329. {
  330. GThread *thread;
  331. #ifndef _WIN32
  332. sigset_t set, oldset;
  333. sigfillset(&set);
  334. pthread_sigmask(SIG_SETMASK, &set, &oldset);
  335. #endif
  336. thread = g_thread_new("trace-thread", fn, NULL);
  337. #ifndef _WIN32
  338. pthread_sigmask(SIG_SETMASK, &oldset, NULL);
  339. #endif
  340. return thread;
  341. }
  342. bool st_init(void)
  343. {
  344. GThread *thread;
  345. trace_pid = getpid();
  346. thread = trace_thread_create(writeout_thread);
  347. if (!thread) {
  348. warn_report("unable to initialize simple trace backend");
  349. return false;
  350. }
  351. atexit(st_flush_trace_buffer);
  352. return true;
  353. }