From 50cb9c56c5e3a2a37b63537a1604e5c209d17cd7 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Sat, 28 Jan 2012 14:18:49 -0500 Subject: [PATCH] Implement clock IR generation Signed-off-by: Mathieu Desnoyers --- .../metadata/ctf-visitor-generate-io-struct.c | 171 ++++++++++++++++++ include/babeltrace/ctf-ir/metadata.h | 36 +++- 2 files changed, 206 insertions(+), 1 deletion(-) diff --git a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c index 70fd5df2..cb3dc008 100644 --- a/formats/ctf/metadata/ctf-visitor-generate-io-struct.c +++ b/formats/ctf/metadata/ctf-visitor-generate-io-struct.c @@ -2069,6 +2069,164 @@ error: return ret; } +static +int ctf_clock_declaration_visit(FILE *fd, int depth, struct ctf_node *node, + struct ctf_clock *clock, struct ctf_trace *trace) +{ + int ret = 0; + + switch (node->type) { + case NODE_CTF_EXPRESSION: + { + char *left; + + left = concatenate_unary_strings(&node->u.ctf_expression.left); + if (!strcmp(left, "name")) { + char *right; + + if (CTF_CLOCK_FIELD_IS_SET(clock, name)) { + fprintf(fd, "[error] %s: name already declared in clock declaration\n", __func__); + ret = -EPERM; + goto error; + } + right = concatenate_unary_strings(&node->u.ctf_expression.right); + if (!right) { + fprintf(fd, "[error] %s: unexpected unary expression for clock name\n", __func__); + ret = -EINVAL; + goto error; + } + clock->name = g_quark_from_string(right); + g_free(right); + CTF_EVENT_SET_FIELD(clock, name); + } else if (!strcmp(left, "uuid")) { + char *right; + + if (clock->uuid) { + fprintf(fd, "[error] %s: uuid already declared in clock declaration\n", __func__); + ret = -EPERM; + goto error; + } + right = concatenate_unary_strings(&node->u.ctf_expression.right); + if (!right) { + fprintf(fd, "[error] %s: unexpected unary expression for clock uuid\n", __func__); + ret = -EINVAL; + goto error; + } + clock->uuid = g_quark_from_string(right); + g_free(right); + } else if (!strcmp(left, "description")) { + char *right; + + if (clock->description) { + fprintf(fd, "[warning] %s: duplicated clock description\n", __func__); + goto error; /* ret is 0, so not an actual error, just warn. */ + } + right = concatenate_unary_strings(&node->u.ctf_expression.right); + if (!right) { + fprintf(fd, "[warning] %s: unexpected unary expression for clock description\n", __func__); + goto error; /* ret is 0, so not an actual error, just warn. */ + } + clock->description = right; + } else if (!strcmp(left, "freq")) { + if (clock->freq) { + fprintf(fd, "[error] %s: freq already declared in clock declaration\n", __func__); + ret = -EPERM; + goto error; + } + ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->freq); + if (ret) { + fprintf(fd, "[error] %s: unexpected unary expression for clock freq\n", __func__); + ret = -EINVAL; + goto error; + } + } else if (!strcmp(left, "precision")) { + if (clock->precision) { + fprintf(fd, "[error] %s: precision already declared in clock declaration\n", __func__); + ret = -EPERM; + goto error; + } + ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->precision); + if (ret) { + fprintf(fd, "[error] %s: unexpected unary expression for clock precision\n", __func__); + ret = -EINVAL; + goto error; + } + } else if (!strcmp(left, "offset_s")) { + if (clock->offset_s) { + fprintf(fd, "[error] %s: offset_s already declared in clock declaration\n", __func__); + ret = -EPERM; + goto error; + } + ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->offset_s); + if (ret) { + fprintf(fd, "[error] %s: unexpected unary expression for clock offset_s\n", __func__); + ret = -EINVAL; + goto error; + } + } else if (!strcmp(left, "offset")) { + if (clock->offset) { + fprintf(fd, "[error] %s: offset already declared in clock declaration\n", __func__); + ret = -EPERM; + goto error; + } + ret = get_unary_unsigned(&node->u.ctf_expression.right, &clock->offset); + if (ret) { + fprintf(fd, "[error] %s: unexpected unary expression for clock offset\n", __func__); + ret = -EINVAL; + goto error; + } + } else { + fprintf(fd, "[warning] %s: attribute \"%s\" is unknown in clock declaration.\n", __func__, left); + } + +error: + g_free(left); + break; + } + default: + return -EPERM; + /* TODO: declaration specifier should be added. */ + } + + return ret; +} + +static +int ctf_clock_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace) +{ + int ret = 0; + struct ctf_node *iter; + struct ctf_clock *clock; + + clock = g_new0(struct ctf_clock, 1); + cds_list_for_each_entry(iter, &node->u.clock.declaration_list, siblings) { + ret = ctf_clock_declaration_visit(fd, depth + 1, iter, clock, trace); + if (ret) + goto error; + } + if (!CTF_CLOCK_FIELD_IS_SET(clock, name)) { + ret = -EPERM; + fprintf(fd, "[error] %s: missing namefield in clock declaration\n", __func__); + goto error; + } + g_hash_table_insert(trace->clocks, (gpointer) (unsigned long) clock->name, clock); + return 0; + +error: + g_free(clock->description); + g_free(clock); + return ret; +} + +static +void clock_free(gpointer data) +{ + struct ctf_clock *clock = data; + + g_free(clock->description); + g_free(clock); +} + static int ctf_root_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace) { @@ -2114,6 +2272,7 @@ int ctf_root_declaration_visit(FILE *fd, int depth, struct ctf_node *node, struc return 0; } +/* TODO: missing metadata "destroy" (memory leak) */ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node, struct ctf_trace *trace, int byte_order) { @@ -2122,6 +2281,8 @@ int ctf_visitor_construct_metadata(FILE *fd, int depth, struct ctf_node *node, printf_verbose("CTF visitor: metadata construction... "); trace->byte_order = byte_order; + trace->clocks = g_hash_table_new_full(g_direct_hash, g_direct_equal, + NULL, clock_free); retry: trace->root_declaration_scope = new_declaration_scope(NULL); @@ -2152,6 +2313,15 @@ retry: goto error; } } + cds_list_for_each_entry(iter, &node->u.root.clock, siblings) { + ret = ctf_clock_visit(fd, depth + 1, iter, + trace); + if (ret) { + fprintf(fd, "[error] %s: clock declaration error\n", __func__); + goto error; + } + } + if (!trace->streams) { fprintf(fd, "[error] %s: missing trace declaration\n", __func__); ret = -EINVAL; @@ -2186,5 +2356,6 @@ retry: error: free_declaration_scope(trace->root_declaration_scope); + g_hash_table_destroy(trace->clocks); return ret; } diff --git a/include/babeltrace/ctf-ir/metadata.h b/include/babeltrace/ctf-ir/metadata.h index 2d216f2f..2cae4630 100644 --- a/include/babeltrace/ctf-ir/metadata.h +++ b/include/babeltrace/ctf-ir/metadata.h @@ -54,6 +54,40 @@ struct ctf_stream_event { struct definition_struct *event_fields; }; +#define CTF_CLOCK_SET_FIELD(ctf_clock, field) \ + do { \ + (ctf_clock)->field_mask |= CTF_CLOCK_ ## field; \ + } while (0) + +#define CTF_CLOCK_FIELD_IS_SET(ctf_clock, field) \ + ((ctf_clock)->field_mask & CTF_CLOCK_ ## field) + +#define CTF_CLOCK_GET_FIELD(ctf_clock, field) \ + ({ \ + assert(CTF_CLOCK_FIELD_IS_SET(ctf_clock, field)); \ + (ctf_clock)->(field); \ + }) + +struct ctf_clock { + GQuark name; + GQuark uuid; + char *description; + uint64_t freq; /* frequency, in HZ */ + /* precision in seconds is: precision * (1/freq) */ + uint64_t precision; + /* + * The offset from Epoch is: offset_s + (offset * (1/freq)) + * Coarse clock offset from Epoch (in seconds). + */ + uint64_t offset_s; + /* Fine clock offset from Epoch, in (1/freq) units. */ + uint64_t offset; + + enum { /* Fields populated mask */ + CTF_CLOCK_name = (1U << 0), + } field_mask; +}; + #define CTF_TRACE_SET_FIELD(ctf_trace, field) \ do { \ (ctf_trace)->field_mask |= CTF_TRACE_ ## field; \ @@ -68,7 +102,6 @@ struct ctf_stream_event { (ctf_trace)->(field); \ }) - struct ctf_trace { struct trace_descriptor parent; /* root scope */ @@ -79,6 +112,7 @@ struct ctf_trace { struct definition_scope *definition_scope; GPtrArray *streams; /* Array of struct ctf_stream_class pointers */ struct ctf_stream *metadata; + GHashTable *clocks; struct declaration_struct *packet_header_decl; -- 2.34.1