From db9aea95eaf92acdf2dc87d888da7a8754c48364 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Sun, 19 May 2019 21:57:52 -0700 Subject: [PATCH] libsysprof-capture: add metadata frame type This will allow sources and aids to discover information about what was done between capture loading and saving. --- .../sysprof-capture-cursor.c | 4 ++ .../sysprof-capture-reader.c | 39 +++++++++++++++ .../sysprof-capture-reader.h | 2 + .../sysprof-capture-types.h | 11 +++++ .../sysprof-capture-writer.c | 45 ++++++++++++++++++ .../sysprof-capture-writer.h | 8 ++++ src/tests/test-capture.c | 47 +++++++++++++++++++ src/tools/sysprof-cat.c | 17 +++++++ src/tools/sysprof-dump.c | 18 ++++++- 9 files changed, 189 insertions(+), 2 deletions(-) diff --git a/src/libsysprof-capture/sysprof-capture-cursor.c b/src/libsysprof-capture/sysprof-capture-cursor.c index 4fe78890..9cb1e31b 100644 --- a/src/libsysprof-capture/sysprof-capture-cursor.c +++ b/src/libsysprof-capture/sysprof-capture-cursor.c @@ -159,6 +159,10 @@ sysprof_capture_cursor_foreach (SysprofCaptureCursor *self, delegate = READ_DELEGATE (sysprof_capture_reader_read_counter_set); break; + case SYSPROF_CAPTURE_FRAME_METADATA: + delegate = READ_DELEGATE (sysprof_capture_reader_read_metadata); + break; + default: if (!sysprof_capture_reader_skip (self->reader)) return; diff --git a/src/libsysprof-capture/sysprof-capture-reader.c b/src/libsysprof-capture/sysprof-capture-reader.c index 5f609e2e..e2aed4fd 100644 --- a/src/libsysprof-capture/sysprof-capture-reader.c +++ b/src/libsysprof-capture/sysprof-capture-reader.c @@ -532,6 +532,45 @@ sysprof_capture_reader_read_mark (SysprofCaptureReader *self) return mark; } +const SysprofCaptureMetadata * +sysprof_capture_reader_read_metadata (SysprofCaptureReader *self) +{ + SysprofCaptureMetadata *metadata; + + g_assert (self != NULL); + g_assert ((self->pos % SYSPROF_CAPTURE_ALIGN) == 0); + g_assert (self->pos <= self->bufsz); + + if (!sysprof_capture_reader_ensure_space_for (self, sizeof *metadata)) + return NULL; + + metadata = (SysprofCaptureMetadata *)(gpointer)&self->buf[self->pos]; + + sysprof_capture_reader_bswap_frame (self, &metadata->frame); + + if (metadata->frame.type != SYSPROF_CAPTURE_FRAME_METADATA) + return NULL; + + if (metadata->frame.len < (sizeof *metadata + 1)) + return NULL; + + if (!sysprof_capture_reader_ensure_space_for (self, metadata->frame.len)) + return NULL; + + metadata = (SysprofCaptureMetadata *)(gpointer)&self->buf[self->pos]; + + self->pos += metadata->frame.len; + + if ((self->pos % SYSPROF_CAPTURE_ALIGN) != 0) + return NULL; + + /* Ensure trailing \0 in .id and .metadata */ + metadata->id[sizeof metadata->id - 1] = 0; + self->buf[self->pos + metadata->frame.len - 1] = 0; + + return metadata; +} + const SysprofCaptureProcess * sysprof_capture_reader_read_process (SysprofCaptureReader *self) { diff --git a/src/libsysprof-capture/sysprof-capture-reader.h b/src/libsysprof-capture/sysprof-capture-reader.h index c0c8392e..5f478489 100644 --- a/src/libsysprof-capture/sysprof-capture-reader.h +++ b/src/libsysprof-capture/sysprof-capture-reader.h @@ -60,6 +60,8 @@ const SysprofCaptureMap *sysprof_capture_reader_read_map SYSPROF_AVAILABLE_IN_ALL const SysprofCaptureMark *sysprof_capture_reader_read_mark (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL +const SysprofCaptureMetadata *sysprof_capture_reader_read_metadata (SysprofCaptureReader *self); +SYSPROF_AVAILABLE_IN_ALL const SysprofCaptureExit *sysprof_capture_reader_read_exit (SysprofCaptureReader *self); SYSPROF_AVAILABLE_IN_ALL const SysprofCaptureFork *sysprof_capture_reader_read_fork (SysprofCaptureReader *self); diff --git a/src/libsysprof-capture/sysprof-capture-types.h b/src/libsysprof-capture/sysprof-capture-types.h index 0608e1c3..582e9f9d 100644 --- a/src/libsysprof-capture/sysprof-capture-types.h +++ b/src/libsysprof-capture/sysprof-capture-types.h @@ -89,6 +89,7 @@ typedef enum SYSPROF_CAPTURE_FRAME_CTRDEF = 8, SYSPROF_CAPTURE_FRAME_CTRSET = 9, SYSPROF_CAPTURE_FRAME_MARK = 10, + SYSPROF_CAPTURE_FRAME_METADATA = 11, } SysprofCaptureFrameType; SYSPROF_ALIGNED_BEGIN(1) @@ -239,6 +240,15 @@ typedef struct } SysprofCaptureMark SYSPROF_ALIGNED_END(1); +SYSPROF_ALIGNED_BEGIN(1) +typedef struct +{ + SysprofCaptureFrame frame; + gchar id[40]; + gchar metadata[0]; +} SysprofCaptureMetadata +SYSPROF_ALIGNED_END(1); + G_STATIC_ASSERT (sizeof (SysprofCaptureFileHeader) == 256); G_STATIC_ASSERT (sizeof (SysprofCaptureFrame) == 24); G_STATIC_ASSERT (sizeof (SysprofCaptureMap) == 56); @@ -253,6 +263,7 @@ G_STATIC_ASSERT (sizeof (SysprofCaptureCounterValues) == 96); G_STATIC_ASSERT (sizeof (SysprofCaptureFrameCounterDefine) == 32); G_STATIC_ASSERT (sizeof (SysprofCaptureFrameCounterSet) == 32); G_STATIC_ASSERT (sizeof (SysprofCaptureMark) == 96); +G_STATIC_ASSERT (sizeof (SysprofCaptureMetadata) == 64); static inline gint sysprof_capture_address_compare (SysprofCaptureAddress a, diff --git a/src/libsysprof-capture/sysprof-capture-writer.c b/src/libsysprof-capture/sysprof-capture-writer.c index 6939cc80..f73895c6 100644 --- a/src/libsysprof-capture/sysprof-capture-writer.c +++ b/src/libsysprof-capture/sysprof-capture-writer.c @@ -587,6 +587,51 @@ sysprof_capture_writer_add_mark (SysprofCaptureWriter *self, return TRUE; } +gboolean +sysprof_capture_writer_add_metadata (SysprofCaptureWriter *self, + gint64 time, + gint cpu, + gint32 pid, + const gchar *id, + const gchar *metadata, + gssize metadata_len) +{ + SysprofCaptureMetadata *ev; + gsize len; + + g_assert (self != NULL); + g_assert (id != NULL); + + if (metadata == NULL) + { + metadata = ""; + len = 0; + } + + if (metadata_len < 0) + metadata_len = strlen (metadata); + + len = sizeof *ev + metadata_len + 1; + ev = (SysprofCaptureMetadata *)sysprof_capture_writer_allocate (self, &len); + if (!ev) + return FALSE; + + sysprof_capture_writer_frame_init (&ev->frame, + len, + cpu, + pid, + time, + SYSPROF_CAPTURE_FRAME_METADATA); + + g_strlcpy (ev->id, id, sizeof ev->id); + memcpy (ev->metadata, metadata, metadata_len); + ev->metadata[metadata_len] = 0; + + self->stat.frame_count[SYSPROF_CAPTURE_FRAME_METADATA]++; + + return TRUE; +} + SysprofCaptureAddress sysprof_capture_writer_add_jitmap (SysprofCaptureWriter *self, const gchar *name) diff --git a/src/libsysprof-capture/sysprof-capture-writer.h b/src/libsysprof-capture/sysprof-capture-writer.h index 47b3e3ab..ebb2b8d2 100644 --- a/src/libsysprof-capture/sysprof-capture-writer.h +++ b/src/libsysprof-capture/sysprof-capture-writer.h @@ -62,6 +62,14 @@ gboolean sysprof_capture_writer_add_mark (SysprofCaptureWrit const gchar *name, const gchar *message); SYSPROF_AVAILABLE_IN_ALL +gboolean sysprof_capture_writer_add_metadata (SysprofCaptureWriter *self, + gint64 time, + gint cpu, + gint32 pid, + const gchar *id, + const gchar *metadata, + gssize metadata_len); +SYSPROF_AVAILABLE_IN_ALL guint64 sysprof_capture_writer_add_jitmap (SysprofCaptureWriter *self, const gchar *name); SYSPROF_AVAILABLE_IN_ALL diff --git a/src/tests/test-capture.c b/src/tests/test-capture.c index 5af92ba6..daa25c16 100644 --- a/src/tests/test-capture.c +++ b/src/tests/test-capture.c @@ -607,6 +607,52 @@ test_reader_writer_mark (void) g_unlink ("mark1.syscap"); } +static void +test_reader_writer_metadata (void) +{ + SysprofCaptureWriter *writer; + SysprofCaptureReader *reader; + const SysprofCaptureMetadata *metadata; + SysprofCaptureFrameType type; + GError *error = NULL; + gint r; + + writer = sysprof_capture_writer_new ("metadata1.syscap", 0); + +#define STR1 "[Something]\nhere=1\n" +#define STR2 "[and]\nthere=2\n" + + sysprof_capture_writer_add_metadata (writer, SYSPROF_CAPTURE_CURRENT_TIME, -1, -1, "aid.cpu", STR1, -1); + sysprof_capture_writer_add_metadata (writer, SYSPROF_CAPTURE_CURRENT_TIME, -1, -1, "aid.mem", STR2, strlen (STR2)); + + g_clear_pointer (&writer, sysprof_capture_writer_unref); + + reader = sysprof_capture_reader_new ("metadata1.syscap", &error); + g_assert_no_error (error); + g_assert (reader != NULL); + + metadata = sysprof_capture_reader_read_metadata (reader); + g_assert_nonnull (metadata); + g_assert_cmpstr (metadata->id, ==, "aid.cpu"); + g_assert_cmpstr (metadata->metadata, ==, STR1); + g_assert_cmpint (metadata->frame.time, >, 0); + g_assert_cmpint (metadata->frame.cpu, ==, -1); + + metadata = sysprof_capture_reader_read_metadata (reader); + g_assert_nonnull (metadata); + g_assert_cmpstr (metadata->id, ==, "aid.mem"); + g_assert_cmpstr (metadata->metadata, ==, STR2); + g_assert_cmpint (metadata->frame.time, >, 0); + g_assert_cmpint (metadata->frame.cpu, ==, -1); + + r = sysprof_capture_reader_peek_type (reader, &type); + g_assert_cmpint (r, ==, FALSE); + + g_clear_pointer (&reader, sysprof_capture_reader_unref); + + g_unlink ("metadata1.syscap"); +} + int main (int argc, char *argv[]) @@ -617,5 +663,6 @@ main (int argc, g_test_add_func ("/SysprofCapture/Writer/splice", test_writer_splice); g_test_add_func ("/SysprofCapture/Reader/splice", test_reader_splice); g_test_add_func ("/SysprofCapture/ReaderWriter/mark", test_reader_writer_mark); + g_test_add_func ("/SysprofCapture/ReaderWriter/metadata", test_reader_writer_metadata); return g_test_run (); } diff --git a/src/tools/sysprof-cat.c b/src/tools/sysprof-cat.c index f72718db..e236990b 100644 --- a/src/tools/sysprof-cat.c +++ b/src/tools/sysprof-cat.c @@ -272,6 +272,23 @@ main (gint argc, break; } + case SYSPROF_CAPTURE_FRAME_METADATA: + { + const SysprofCaptureMetadata *frame; + + if (!(frame = sysprof_capture_reader_read_metadata (reader))) + goto panic; + + sysprof_capture_writer_add_metadata (writer, + frame->frame.time, + frame->frame.cpu, + frame->frame.pid, + frame->id, + frame->metadata, + frame->frame.len - G_STRUCT_OFFSET (SysprofCaptureMetadata, metadata)); + break; + } + case SYSPROF_CAPTURE_FRAME_JITMAP: { GHashTable *jitmap; diff --git a/src/tools/sysprof-dump.c b/src/tools/sysprof-dump.c index 1e81bb05..270bf65d 100644 --- a/src/tools/sysprof-dump.c +++ b/src/tools/sysprof-dump.c @@ -130,8 +130,8 @@ main (gint argc, gdouble ptime = (mark->frame.time - begin_time) / (gdouble)NSEC_PER_SEC; g_print ("MARK: pid=%d time=%"G_GINT64_FORMAT" (%lf)\n" - " group = %s\n" - " name = %s\n" + " group = %s\n" + " name = %s\n" " duration = %"G_GUINT64_FORMAT"\n" " message = %s\n", mark->frame.pid, mark->frame.time, ptime, @@ -140,6 +140,20 @@ main (gint argc, break; } + case SYSPROF_CAPTURE_FRAME_METADATA: + { + const SysprofCaptureMetadata *metadata = sysprof_capture_reader_read_metadata (reader); + gdouble ptime = (metadata->frame.time - begin_time) / (gdouble)NSEC_PER_SEC; + + g_print ("METADATA: pid=%d time=%"G_GINT64_FORMAT" (%lf)\n" + " id = %s\n" + "\"\"\"\n%s\n\"\"\"", + metadata->frame.pid, metadata->frame.time, ptime, + metadata->id, metadata->metadata); + + break; + } + case SYSPROF_CAPTURE_FRAME_PROCESS: { const SysprofCaptureProcess *pr = sysprof_capture_reader_read_process (reader);