From 8b7ad762ff0cab7725d70468f4b5415f33237158 Mon Sep 17 00:00:00 2001 From: schodet Date: Thu, 16 Oct 2008 13:23:39 +0000 Subject: * lib/trace: - added trace bundles. git-svn-id: svn+ssh://pessac/svn/cesar/trunk@3292 017c9cb6-072f-447c-8318-d5b54f68fe89 --- cesar/lib/src/trace.c | 94 ++++++++++++++++++++- cesar/lib/test/trace/src/test_trace.c | 153 ++++++++++++++++++++++++++-------- cesar/lib/trace.h | 41 ++++++++- 3 files changed, 248 insertions(+), 40 deletions(-) (limited to 'cesar') diff --git a/cesar/lib/src/trace.c b/cesar/lib/src/trace.c index 48cca1fa73..5be937102a 100644 --- a/cesar/lib/src/trace.c +++ b/cesar/lib/src/trace.c @@ -218,6 +218,7 @@ trace_buffer_add (trace_buffer_t *buf, const char *name, uint drop_level, buf->drop_level = drop_level; buf->preload = preload; buf->locked = locked; + buf->name = name; buf->namespace = namespace; /* Allocate chunks. */ blk_t *tail; @@ -341,6 +342,25 @@ trace_buffer_dump (trace_buffer_t *buf, trace_dump_callback_t cb, void *user) trace_chunk_t *head, *tail; u32 *data, *data_end; int sum = 0; + dbg_assert (buf); + dbg_assert (buf->head); + dbg_assert (buf->tail); + dbg_assert (buf->name); + dbg_assert (cb); + /* Dump buffer name. */ + static const char trace_start_before[] = "---trace-begin["; + static const char trace_start_after[] = "]---\n"; + static const char trace_stop[] = "---trace-end---\n"; + uint name_len = strlen (buf->name); + memcpy (text + text_size, trace_start_before, + sizeof (trace_start_before) - 1); + text_size += sizeof (trace_start_before) - 1; + memcpy (text + text_size, buf->name, name_len); + text_size += name_len; + memcpy (text + text_size, trace_start_after, + sizeof (trace_start_after) - 1); + text_size += sizeof (trace_start_after) - 1; + dbg_assert ((uint) text_size < sizeof (text) - DUMP_TEXT_SLACK); /* TODO: acquire lock, increment reference counter. */ tail = buf->tail; head = buf->head; @@ -376,8 +396,11 @@ trace_buffer_dump (trace_buffer_t *buf, trace_dump_callback_t cb, void *user) head = head->next; } while (1); /* Final text. */ - if (sum != -1 && text_size) + if (sum != -1) { + dbg_assert (sizeof (trace_stop) - 1 < DUMP_TEXT_SLACK); + memcpy (text + text_size, trace_stop, sizeof (trace_stop) - 1); + text_size += sizeof (trace_stop) - 1; if (cb (user, text, text_size) != text_size) sum = -1; else @@ -386,8 +409,69 @@ trace_buffer_dump (trace_buffer_t *buf, trace_dump_callback_t cb, void *user) return sum; } +int +trace_bundle_start (const char *name, trace_dump_callback_t cb, void *user) +{ + int name_len = 0; + dbg_assert (cb); + static const char bundle_start_before[] = "---trace-bundle-begin["; + static const char bundle_start_after[] = "]---\n"; + if (cb (user, bundle_start_before, sizeof (bundle_start_before) - 1) + != sizeof (bundle_start_before) - 1) + return -1; + if (name) + { + name_len = strlen (name); + if (cb (user, name, name_len) != name_len) + return -1; + } + if (cb (user, bundle_start_after, sizeof (bundle_start_after) - 1) + != sizeof (bundle_start_after) - 1) + return -1; + return sizeof (bundle_start_before) - 1 + sizeof (bundle_start_after) - 1 + + name_len; +} + +int +trace_bundle_stop (trace_dump_callback_t cb, void *user) +{ + dbg_assert (cb); + static const char bundle_stop[] = "---trace-bundle-end---\n"; + if (cb (user, bundle_stop, sizeof (bundle_stop) - 1) + != sizeof (bundle_stop) - 1) + return -1; + return sizeof (bundle_stop) - 1; +} + +int +trace_bundle_dump_all (const char *name, trace_dump_callback_t cb, void *user) +{ + trace_t * const ctx = &trace_global; + int sum = 0, r; + /* Header. */ + r = trace_bundle_start (name, cb, user); + if (r == -1) return -1; + sum += r; + /* Dump all. */ + list_node_t *i, *end; + i = list_begin (&ctx->buffers); + end = list_end (&ctx->buffers); + for (; i != end; i = list_next (i)) + { + trace_buffer_t *buf = PARENT_OF (trace_buffer_t, node, i); + r = trace_buffer_dump (buf, cb, user); + if (r == -1) return -1; + sum += r; + } + /* Footer. */ + r = trace_bundle_stop (cb, user); + if (r == -1) return -1; + sum += r; + return sum; +} + static int -trace_buffer_dbg_dump_callback (void *user, char *text, uint text_size) +trace_buffer_dbg_dump_callback (void *user, const char *text, uint text_size) { dbg_assert (text && text_size); arch_io_write (text, text_size); @@ -400,6 +484,12 @@ trace_buffer_dbg_dump (trace_buffer_t *buf) trace_buffer_dump (buf, trace_buffer_dbg_dump_callback, NULL); } +void +trace_dbg_dump_all (void) +{ + trace_bundle_dump_all ("dbg", trace_buffer_dbg_dump_callback, NULL); +} + static void trace_printn_prepare (trace_buffer_t *buf, uint count) { diff --git a/cesar/lib/test/trace/src/test_trace.c b/cesar/lib/test/trace/src/test_trace.c index c2d1f0e8ff..0351b6b02d 100644 --- a/cesar/lib/test/trace/src/test_trace.c +++ b/cesar/lib/test/trace/src/test_trace.c @@ -34,23 +34,48 @@ struct growing_buffer_t }; typedef struct growing_buffer_t growing_buffer_t; -int -dump_callback (void *user, char *text, uint text_size) +void +growing_init (growing_buffer_t *g) { - dbg_assert (user); - dbg_assert (text && text_size != 0); - growing_buffer_t *g = user; - /* Grow buffer if necessary. */ - if (g->buf_pos + text_size >= g->buf_size) + dbg_assert (g); + g->buf_pos = 0; + g->buf_size = 128; + g->buf = malloc (g->buf_size); + dbg_assert (g->buf); +} + +void +growing_uninit (growing_buffer_t *g) +{ + dbg_assert (g); + free (g->buf); +} + +static void +growing_grow (growing_buffer_t *g, uint size) +{ + dbg_assert (g); + if (g->buf_pos + size >= g->buf_size) { - g->buf_size = (g->buf_size + text_size) * 2; + g->buf_size = (g->buf_size + size) * 2; g->buf = realloc (g->buf, g->buf_size); dbg_assert (g->buf); } - /* Copy data. */ - memcpy (g->buf + g->buf_pos, text, text_size); - g->buf_pos += text_size; - return text_size; +} + +void +growing_memcpy (growing_buffer_t *g, const char *text, uint text_size) +{ + dbg_assert (g); + dbg_assert (text); + if (text_size) + { + /* Grow buffer if necessary. */ + growing_grow (g, text_size); + /* Copy data. */ + memcpy (g->buf + g->buf_pos, text, text_size); + g->buf_pos += text_size; + } } void @@ -79,6 +104,17 @@ growing_sprintf (growing_buffer_t *g, const char *fmt, ...) } while (1); } +int +dump_callback (void *user, const char *text, uint text_size) +{ + dbg_assert (user); + dbg_assert (text && text_size != 0); + growing_buffer_t *g = user; + /* Copy data. */ + growing_memcpy (g, text, text_size); + return text_size; +} + void trace_basic_test_case (test_t t) { @@ -220,32 +256,30 @@ trace_basic_test_case (test_t t) trace_buffer_remove (&trace_buf[1]); trace_buffer_remove (&trace_buf[2]); } test_end; + enum + { + TEST_TRACE_TRACE_ONE, + TEST_TRACE_TRACE_TWO, + TEST_TRACE_TRACE_THREE, + TEST_TRACE_TRACE_FOUR, + }; + static const trace_event_id_t ei[] = { + TRACE_EVENT (TEST_TRACE_TRACE_ONE, "one"), + TRACE_EVENT (TEST_TRACE_TRACE_TWO, "two %d", TIMESTAMP), + TRACE_EVENT (TEST_TRACE_TRACE_THREE, "three %u, %x, %d, %b, %b"), + TRACE_EVENT (TEST_TRACE_TRACE_FOUR, "four %m, %d"), + }; + trace_namespace_t ns; + trace_namespace_init (&ns, ei, COUNT (ei)); test_begin (t, "dump") { #define TEST_TRACE_TRACE(id, args...) \ TRACE_SHORT (TEST_TRACE_TRACE_, &trace_buf[0], id, ## args) - enum - { - TEST_TRACE_TRACE_ONE, - TEST_TRACE_TRACE_TWO, - TEST_TRACE_TRACE_THREE, - TEST_TRACE_TRACE_FOUR, - }; - static const trace_event_id_t ei[] = { - TRACE_EVENT (TEST_TRACE_TRACE_ONE, "one"), - TRACE_EVENT (TEST_TRACE_TRACE_TWO, "two %d", TIMESTAMP), - TRACE_EVENT (TEST_TRACE_TRACE_THREE, "three %u, %x, %d, %b, %b"), - TRACE_EVENT (TEST_TRACE_TRACE_FOUR, "four %m, %d"), - }; - trace_namespace_t ns; - trace_namespace_init (&ns, ei, COUNT (ei)); trace_buffer_add (&trace_buf[0], "trace", 2, 1, false, &ns); /* Trace and record expected trace. */ growing_buffer_t expected_dump; - expected_dump.buf_pos = 0; - expected_dump.buf_size = 100; - expected_dump.buf = malloc (expected_dump.buf_size); - dbg_assert (expected_dump.buf); + growing_init (&expected_dump); + growing_sprintf (&expected_dump, "---trace-begin[%s]---\n", "trace"); for (i = 0; i < NB_PRINT; i++) { trace_print0 (&trace_buf[0], TEST_TRACE_TRACE_ONE); @@ -262,13 +296,11 @@ trace_basic_test_case (test_t t) growing_sprintf (&expected_dump, "[.] four 12:34:56:78:9a:bc, %d\n", i); } + growing_sprintf (&expected_dump, "---trace-end---\n"); test_verbose_print ("%s", expected_dump.buf); /* Dump to memory. */ growing_buffer_t dump; - dump.buf_pos = 0; - dump.buf_size = 100; - dump.buf = malloc (dump.buf_size); - dbg_assert (dump.buf); + growing_init (&dump); int ret = trace_buffer_dump (&trace_buf[0], dump_callback, &dump); /* Check dump. */ test_fail_unless (expected_dump.buf_pos == dump.buf_pos); @@ -276,9 +308,56 @@ trace_basic_test_case (test_t t) test_fail_unless (memcmp (expected_dump.buf, dump.buf, dump.buf_pos) == 0); /* Cleanup. */ - free (expected_dump.buf); - free (dump.buf); + growing_uninit (&expected_dump); + growing_uninit (&dump); + trace_buffer_remove (&trace_buf[0]); +#undef TEST_TRACE_TRACE + } test_end; + test_begin (t, "dump all") + { +#define TEST_TRACE_TRACE(buf, id, args...) \ + TRACE_SHORT (TEST_TRACE_TRACE_, &trace_buf[buf], id, ## args) + trace_buffer_add (&trace_buf[0], "trace0", 2, 1, false, &ns); + trace_buffer_add (&trace_buf[1], "trace1", 2, 1, false, &ns); + /* Trace and record expected trace. */ + growing_buffer_t expected_dump; + growing_init (&expected_dump); + growing_buffer_t expected_dump1; + growing_init (&expected_dump1); + growing_sprintf (&expected_dump, "---trace-bundle-begin[%s]---\n", "thebundle"); + growing_sprintf (&expected_dump, "---trace-begin[%s]---\n", "trace0"); + for (i = 0; i < NB_PRINT / 10; i++) + { + TEST_TRACE_TRACE (0, ONE); + growing_sprintf (&expected_dump, "[.] one\n"); + TEST_TRACE_TRACE (0, TWO, i, i + 1); + growing_sprintf (&expected_dump, "[0x%08x] two %d\n", i, i + 1); + TEST_TRACE_TRACE (1, TWO, i, i * 2); + growing_sprintf (&expected_dump1, "[0x%08x] two %d\n", i, i * 2); + } + growing_sprintf (&expected_dump, "---trace-end---\n"); + growing_sprintf (&expected_dump, "---trace-begin[%s]---\n", "trace1"); + growing_memcpy (&expected_dump, expected_dump1.buf, + expected_dump1.buf_pos); + growing_sprintf (&expected_dump, "---trace-end---\n"); + growing_sprintf (&expected_dump, "---trace-bundle-end---\n"); + test_verbose_print ("%s", expected_dump.buf); + /* Dump to memory. */ + growing_buffer_t dump; + growing_init (&dump); + int ret = trace_bundle_dump_all ("thebundle", dump_callback, &dump); + /* Check dump. */ + test_fail_unless (expected_dump.buf_pos == dump.buf_pos); + test_fail_unless ((int) dump.buf_pos == ret); + test_fail_unless (memcmp (expected_dump.buf, dump.buf, dump.buf_pos) + == 0); + /* Cleanup. */ + growing_uninit (&expected_dump); + growing_uninit (&expected_dump1); + growing_uninit (&dump); trace_buffer_remove (&trace_buf[0]); + trace_buffer_remove (&trace_buf[1]); +#undef TEST_TRACE_TRACE } test_end; /* Uninit. */ trace_uninit (); diff --git a/cesar/lib/trace.h b/cesar/lib/trace.h index 10da874ddf..fd8debaca8 100644 --- a/cesar/lib/trace.h +++ b/cesar/lib/trace.h @@ -175,7 +175,8 @@ struct trace_namespace_t * \param text_size size of text to write, i.e. number of characters * \return should return size, any other value will stop dump */ -typedef int (*trace_dump_callback_t) (void *user, char *text, uint text_size); +typedef int (*trace_dump_callback_t) (void *user, const char *text, + uint text_size); BEGIN_DECLS @@ -282,6 +283,38 @@ trace_buffer_remove (trace_buffer_t *buf); int trace_buffer_dump (trace_buffer_t *buf, trace_dump_callback_t cb, void *user); +/** + * Start a text trace bundle. + * \param name bundle name, may be NULL for no name + * \param cb callback called several times with text data + * \param user user data passed to the callback + * \return number of character written or -1 on any error (if one callback + * did not return its size parameter) + */ +int +trace_bundle_start (const char *name, trace_dump_callback_t cb, void *user); + +/** + * Stop a text trace bundle. + * \param cb callback called several times with text data + * \param user user data passed to the callback + * \return number of character written or -1 on any error (if one callback + * did not return its size parameter) + */ +int +trace_bundle_stop (trace_dump_callback_t cb, void *user); + +/** + * Dump all trace buffers as a text trace bundle. + * \param name bundle name, may be NULL for no name + * \param cb callback called several times with text data + * \param user user data passed to the callback + * \return number of character written or -1 on any error (if one callback + * did not return its size parameter) + */ +int +trace_bundle_dump_all (const char *name, trace_dump_callback_t cb, void *user); + /** * Dump a full trace buffer as text during debug. * \param buf trace buffer @@ -291,6 +324,12 @@ trace_buffer_dump (trace_buffer_t *buf, trace_dump_callback_t cb, void *user); void trace_buffer_dbg_dump (trace_buffer_t *buf); +/** + * Dump all trace buffer as a text bundle during debug. + */ +void +trace_dbg_dump_all (void); + /** * Write event to trace buffer. * \param buf the trace buffer to write to -- cgit v1.2.3