From a3e6ce641573c455fdf020fa10f3481046dfddf7 Mon Sep 17 00:00:00 2001 From: compudj Date: Thu, 1 Dec 2005 18:05:05 +0000 Subject: [PATCH] code finished, not compiled yet git-svn-id: http://ltt.polymtl.ca/svn@1348 04897980-b3bd-0310-b5e0-8ef037075253 --- genevent-new/genevent.c | 1114 +++++++++++++++++++++++++-------------- genevent-new/gentest.c | 8 +- genevent-new/parser.c | 13 +- 3 files changed, 727 insertions(+), 408 deletions(-) diff --git a/genevent-new/genevent.c b/genevent-new/genevent.c index 124168d2..4042dafa 100644 --- a/genevent-new/genevent.c +++ b/genevent-new/genevent.c @@ -325,6 +325,62 @@ int print_arg(type_descriptor_t * td, FILE *fd, unsigned int tabs, } +/* Does the type has a fixed size ? (as know from the compiler) + * + * 1 : fixed size + * 0 : variable length + */ +int has_type_fixed_size(type_descriptor_t *td) +{ + switch(td->type) { + case INT_FIXED: + case UINT_FIXED: + case CHAR: + case UCHAR: + case SHORT: + case USHORT: + case INT: + case UINT: + case FLOAT: + case POINTER: + case LONG: + case ULONG: + case SIZE_T: + case SSIZE_T: + case OFF_T: + case ENUM: + case UNION: /* The union must have fixed size children. Must be checked by + the parser */ + return 1; + break; + case STRING: + case SEQUENCE: + return 0; + break; + case STRUCT: + { + int has_type_fixed = 0; + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + + has_type_fixed = has_type_fixed_size(type); + if(!has_type_fixed) return 0; + } + return 1; + } + break; + case ARRAY: + assert(td->size >= 0); + return has_type_fixed(((field_t*)td->fields.array[0])->type); + break; + } +} + + + + + /* print type declaration. * * Copied from construct_types_and_fields in LTTV facility.c */ @@ -398,7 +454,9 @@ int print_type_declaration(type_descriptor_t * td, FILE *fd, unsigned int tabs, fprintf(fd, "struct lttng_sequence_%s", basename); fprintf(fd, " {\n"); print_tabs(1, fd); - fprintf(fd, "unsigned int len;\n"); + if(print_type(((field_t*)td->fields.array[0])->type, + fd, tabs, basename, "")) return 1; + fprintf(fd, "len;\n"); print_tabs(1, fd); if(print_type(((field_t*)td->fields.array[1])->type, fd, tabs, basename, "")) return 1; @@ -465,358 +523,98 @@ int print_type_declaration(type_descriptor_t * td, FILE *fd, unsigned int tabs, } +/* print type alignment. + * + * Copied from construct_types_and_fields in LTTV facility.c + * + * basename is the name which identifies the type (along with a prefix + * (possibly)). */ - - -/***************************************************************************** - *Function name - * set_named_type_offsets : set the precomputable offset of the named type - *Input params - * type : the type - ****************************************************************************/ -void set_named_type_offsets(type_descriptor_t *type) +int print_type_alignment(type_descriptor_t * td, FILE *fd, unsigned int tabs, + char *nest_name, char *field_name) { - enum field_status current_child_status = FIELD_FIXED_GENEVENT; - off_t current_offset = 0; - - preset_type_size( - current_offset, - ¤t_child_status, - type); - if(current_child_status == FIELD_FIXED_GENEVENT) { - current_offset += type->size; + char basename[PATH_MAX]; + unsigned int basename_len = 0; + + strncpy(basename, nest_name, PATH_MAX); + basename_len = strlen(basename); + + /* For a named type, we use the type_name directly */ + if(td->type_name != NULL) { + strncpy(basename, td->type_name, PATH_MAX); + basename_len = strlen(basename); } else { - current_offset = 0; - } -} - - -/***************************************************************************** - *Function name - * set_event_fields_offsets : set the precomputable offset of the fields - *Input params - * event : the event - ****************************************************************************/ -void set_event_fields_offsets(event_t *event) -{ - enum field_status current_child_status = FIELD_FIXED; - off_t current_offset = 0; - - for(unsigned int i = 0; i < event->type->fields.position; i++) { - /* For each field, set the field offset. */ - field_t *child_field = (field_t*)event->type->fields.array[i]; - type_descriptor_t *t = f->type; - /* Skip named types */ - if(t->type_name != NULL) continue; - - preset_type_size( - current_offset, - ¤t_child_status, - t); - if(current_child_status == FIELD_FIXED_GENEVENT) { - current_offset += type->size; - } else { - current_offset = 0; + /* For a unnamed type, there must be a field name, except for + * the array. */ + if((basename_len != 0) + && (basename[basename_len-1] != '_' + && (field_name[0] != '\0'))) { + strncat(basename, "_", PATH_MAX - basename_len); + basename_len = strlen(basename); } + strncat(basename, field_name, PATH_MAX - basename_len); } -} - - - -/***************************************************************************** - *Function name - * print_type_size : print the fixed sizes of the field type - * taken from LTTV. - * - * use offset_parent as offset to calculate alignment. - *Input params - * offset_parent : offset from the parent - * fixed_parent : Do we know a fixed offset to the parent ? - * type : type - ****************************************************************************/ -void print_type_size( - off_t offset_parent, - enum field_status *fixed_parent, - type_descriptor_t *type, - FILE *fd, - char *size_name) -{ - enum field_status local_fixed_parent; - guint i; - - g_assert(type->fixed_size == FIELD_UNKNOWN); - - size_t current_offset; - enum field_status current_child_status, final_child_status; - size_t max_size; - - switch(type->type) { - /* type sizes known by genevent/compiler */ + + switch(td->type) { case INT_FIXED: case UINT_FIXED: - case FLOAT: case CHAR: case UCHAR: case SHORT: case USHORT: - /* Align */ - fprintf(fd, "%s += ltt_align(%s, %s)", size_name); - /* Data */ - type->fixed_size = FIELD_FIXED_GENEVENT; - break; - /* host type sizes unknown by genevent, but known by the compiler */ - case INT: - case UINT: - case ENUM: - /* An enum is either : char or int. In gcc, always int. Hope - * it's always like this. */ - type->fixed_size = FIELD_FIXED_COMPILER; - type->compiler_size = COMPILER_INT; - break; - case LONG: - case ULONG: - type->fixed_size = FIELD_FIXED_COMPILER; - type->compiler_size = COMPILER_LONG; - break; - case POINTER: - type->fixed_size = FIELD_FIXED_COMPILER; - type->compiler_size = COMPILER_POINTER; - break; - case SIZE_T: - case SSIZE_T: - case OFF_T: - type->fixed_size = FIELD_FIXED_COMPILER; - type->compiler_size = COMPILER_SIZE_T; - break; - /* compound types : - * if all children has fixed size, then the parent size can be - * known directly and the copy can be done efficiently. - * if only part of the children has fixed size, then the contiguous - * elements will be copied in one bulk, but the variable size elements - * will be copied separately. This is necessary because those variable - * size elements are referenced by pointer in C. - */ - case SEQUENCE: - current_offset = 0; - local_fixed_parent = FIELD_FIXED_GENEVENT; - preset_type_size( - 0, - &local_fixed_parent, - ((field_t*)type->fields.array[0])->type); - preset_field_type_size( - 0, - &local_fixed_parent, - ((field_t*)type->fields.array[1])->type); - type->fixed_size = FIELD_VARIABLE; - *fixed_parent = FIELD_VARIABLE; - break; - case LTT_STRING: - field->fixed_size = FIELD_VARIABLE; - *fixed_parent = FIELD_VARIABLE; - break; - case LTT_ARRAY: - local_fixed_parent = FIELD_FIXED_GENEVENT; - preset_type_size( - 0, - &local_fixed_parent, - ((field_t*)type->fields.array[0])->type); - type->fixed_size = local_fixed_parent; - if(type->fixed_size == FIELD_FIXED_GENEVENT) { - type->size = - type->element_number * ((field_t*)type->fields.array[0])->type->size; - } else if(type->fixed_size == FIELD_FIXED_COMPILER) { - type->size = - type->element_number; - } else { - type->size = 0; - *fixed_parent = FIELD_VARIABLE; - } - break; - case LTT_STRUCT: - current_offset = 0; - current_child_status = FIELD_FIXED_GENEVENT; - for(i=0;ielement_number;i++) { - preset_field_type_size( - current_offset, - ¤t_child_status, - ((field_t*)type->fields.array[i])->type); - if(current_child_status == FIELD_FIXED_GENEVENT) { - current_offset += field->child[i]->field_size; - } else { - current_offset = 0; - } - } - if(current_child_status != FIELD_FIXED_GENEVENT) { - *fixed_parent = current_child_status; - type->size = 0; - type->fixed_size = current_child_status; - } else { - type->size = current_offset; - type->fixed_size = FIELD_FIXED_GENEVENT; - } - break; - case LTT_UNION: - current_offset = 0; - max_size = 0; - final_child_status = FIELD_FIXED_GENEVENT; - for(i=0;ielement_number;i++) { - enum field_status current_child_status = FIELD_FIXED; - preset_field_type_size( - current_offset, - ¤t_child_status, - ((field_t*)type->fields.array[i])->type); - if(current_child_status != FIELD_FIXED_GENEVENT) - final_child_status = current_child_status; - else - max_size = - max(max_size, ((field_t*)type->fields.array[i])->type->size); - } - if(final_child_status != FIELD_FIXED_GENEVENT AND COMPILER) { - g_error("LTTV does not support variable size fields in unions."); - /* This will stop the application. */ - *fixed_parent = final_child_status; - type->size = 0; - type->fixed_size = current_child_status; - } else { - type->size = max_size; - type->fixed_size = FIELD_FIXED_GENEVENT; - } - break; - } - -} - + case INT: + case UINT: + case FLOAT: + case POINTER: + case LONG: + case ULONG: + case SIZE_T: + case SSIZE_T: + case OFF_T: + case ENUM: + fprintf(fd, "sizeof("); + if(print_type(td->type, + fd, 0, basename, "")) return 1; + fprintf(fd, ")"); + break; + case STRING: + fprintf(fd, "sizeof(char)"); + break; + case SEQUENCE: + fprintf(fd, "lttng_get_alignment_sequence_%s(&obj->%s)", basename, + field_name); + break; + case STRUCT: + fprintf(fd, "lttng_get_alignment_struct_%s(&obj->%s)", basename, + field_name); + break; + case UNION: + fprintf(fd, "lttng_get_alignment_union_%s(&obj->%s)", basename, + field_name); + break; + case ARRAY: + fprintf(fd, "lttng_get_alignment_array_%s(obj->%s)", basename, + field_name); + break; + } -size_t get_field_type_size(LttTracefile *tf, LttEventType *event_type, - off_t offset_root, off_t offset_parent, - LttField *field, void *data) -{ - size_t size = 0; - guint i; - LttType *type; - - g_assert(field->fixed_root != FIELD_UNKNOWN); - g_assert(field->fixed_parent != FIELD_UNKNOWN); - g_assert(field->fixed_size != FIELD_UNKNOWN); - - field->offset_root = offset_root; - field->offset_parent = offset_parent; - - type = field->field_type; - - switch(type->type_class) { - case LTT_INT: - case LTT_UINT: - case LTT_FLOAT: - case LTT_ENUM: - case LTT_POINTER: - case LTT_LONG: - case LTT_ULONG: - case LTT_SIZE_T: - case LTT_SSIZE_T: - case LTT_OFF_T: - g_assert(field->fixed_size == FIELD_FIXED); - size = field->field_size; - break; - case LTT_SEQUENCE: - { - gint seqnum = ltt_get_uint(LTT_GET_BO(tf), - field->sequ_number_size, - data + offset_root); - - if(field->child[0]->fixed_size == FIELD_FIXED) { - size = field->sequ_number_size + - (seqnum * get_field_type_size(tf, event_type, - offset_root, offset_parent, - field->child[0], data)); - } else { - size += field->sequ_number_size; - for(i=0;ichild[0], data); - offset_root += child_size; - offset_parent += child_size; - size += child_size; - } - } - field->field_size = size; - } - break; - case LTT_STRING: - size = strlen((char*)(data+offset_root)) + 1;// length + \0 - field->field_size = size; - break; - case LTT_ARRAY: - if(field->fixed_size == FIELD_FIXED) - size = field->field_size; - else { - for(i=0;ifield_type->element_number;i++) { - size_t child_size; - child_size = get_field_type_size(tf, event_type, - offset_root, offset_parent, - field->child[0], data); - offset_root += child_size; - offset_parent += child_size; - size += child_size; - } - field->field_size = size; - } - break; - case LTT_STRUCT: - if(field->fixed_size == FIELD_FIXED) - size = field->field_size; - else { - size_t current_root_offset = offset_root; - size_t current_offset = 0; - size_t child_size = 0; - for(i=0;ielement_number;i++) { - child_size = get_field_type_size(tf, - event_type, current_root_offset, current_offset, - field->child[i], data); - current_offset += child_size; - current_root_offset += child_size; - - } - size = current_offset; - field->field_size = size; - } - break; - case LTT_UNION: - if(field->fixed_size == FIELD_FIXED) - size = field->field_size; - else { - size_t current_root_offset = field->offset_root; - size_t current_offset = 0; - for(i=0;ielement_number;i++) { - size = get_field_type_size(tf, event_type, - current_root_offset, current_offset, - field->child[i], data); - size = max(size, field->child[i]->field_size); - } - field->field_size = size; - } - break; - } - - return size; + return 0; } +/* print type write. + * + * Copied from construct_types_and_fields in LTTV facility.c + * + * basename is the name which identifies the type (along with a prefix + * (possibly)). */ - - - -/* Print the code that calculates the length of an field */ -int print_field_len(type_descriptor_t * td, FILE *fd, unsigned int tabs, - char *nest_type_name, char *nest_field_name, char *field_name, - char *output_var, char *member_var) +int print_type_write(type_descriptor_t * td, FILE *fd, unsigned int tabs, + char *nest_name, char *field_name) { - /* Type name : basename */ char basename[PATH_MAX]; unsigned int basename_len = 0; - - strcpy(basename, nest_type_name); + + strncpy(basename, nest_name, PATH_MAX); basename_len = strlen(basename); /* For a named type, we use the type_name directly */ @@ -824,29 +622,17 @@ int print_field_len(type_descriptor_t * td, FILE *fd, unsigned int tabs, strncpy(basename, td->type_name, PATH_MAX); basename_len = strlen(basename); } else { - /* For a unnamed type, there must be a field name */ + /* For a unnamed type, there must be a field name, except for + * the array. */ if((basename_len != 0) - && (basename[basename_len-1] != '_') - && (field_name[0] != '\0')) { + && (basename[basename_len-1] != '_' + && (field_name[0] != '\0'))) { strncat(basename, "_", PATH_MAX - basename_len); basename_len = strlen(basename); } strncat(basename, field_name, PATH_MAX - basename_len); } - /* Field name : basefieldname */ - char basefieldname[PATH_MAX]; - unsigned int basefieldname_len = 0; - - strcpy(basefieldname, nest_field_name); - basefieldname_len = strlen(basefieldname); - - /* there must be a field name */ - strncat(basefieldname, field_name, PATH_MAX - basefieldname_len); - basefieldname_len = strlen(basefieldname); - - print_tabs(tabs, fd); - switch(td->type) { case INT_FIXED: case UINT_FIXED: @@ -864,63 +650,480 @@ int print_field_len(type_descriptor_t * td, FILE *fd, unsigned int tabs, case SSIZE_T: case OFF_T: case ENUM: - fprintf(fd, "/* Size of %s */", field_name); print_tabs(tabs, fd); - fprintf(fd, "%s = sizeof(", member_var); - if(print_type(td, fd, tabs, basename, "")) return 1; + fprintf(fd, "size = "); + fprintf(fd, "sizeof("); + if(print_type(td->type, + fd, 0, basename, "")) return 1; fprintf(fd, ");\n"); - fprintf(fd, "%s += ltt_align(%s, %s);\n", output_var, member_var); print_tabs(tabs, fd); - fprintf(fd, "%s += %s;\n", output_var, member_var); + fprintf(fd, "size += ltt_align(*to+*len, size) + size;"); + print_tabs(tabs, fd); + fprintf(fd, "*len += size;"); break; case STRING: - /* strings are made of bytes : no alignment. */ - fprintf(fd, "/* Size of %s */", basefieldname); print_tabs(tabs, fd); - fprintf(fd, "%s = strlen(%s);", member_var, basefieldname); + fprintf(fd, "lttng_write_string_%s(buffer, to_base, to, from, len, obj->%s);\n"); + break; + case SEQUENCE: + print_tabs(tabs, fd); + fprintf(fd, "lttng_write_%s(buffer, to_base, to, from, len, obj->%s)", basename, + field_name); + break; + case STRUCT: + print_tabs(tabs, fd); + fprintf(fd, "lttng_write_struct_%s(buffer, to_base, to, from, len, obj->%s)", basename, + field_name); + break; + case UNION: + print_tabs(tabs, fd); + fprintf(fd, "lttng_write_union_%s(buffer, to_base, to, from, len, obj->%s)", basename, + field_name); break; case ARRAY: - fprintf(fd, "/* Size of %s */", basefieldname); print_tabs(tabs, fd); + fprintf(fd, "lttng_write_array_%s(buffer, to_base, to, from, len, obj->%s)", basename, + field_name); + break; + } - strncat(basefieldname, ".", PATH_MAX - basefieldname_len); - basefieldname_len = strlen(basefieldname); + return 0; +} - if(print_field_len(((field_t*)td->fields.array[0])->type, - fd, tabs, - basename, basefieldname, - output_var, member_var)) return 1; - fprintf(fd, "%s = strlen(%s);", member_var, basefieldname); - fprintf(fd, "lttng_array_%s", basename); - fprintf(fd, " %s", field_name); +/* print type alignment function. + * + * Copied from construct_types_and_fields in LTTV facility.c + * + * basename is the name which identifies the type (along with a prefix + * (possibly)). */ + +int print_type_alignment_fct(type_descriptor_t * td, FILE *fd, + unsigned int tabs, + char *nest_name, char *field_name) +{ + char basename[PATH_MAX]; + unsigned int basename_len = 0; + + strncpy(basename, nest_name, PATH_MAX); + basename_len = strlen(basename); + + /* For a named type, we use the type_name directly */ + if(td->type_name != NULL) { + strncpy(basename, td->type_name, PATH_MAX); + basename_len = strlen(basename); + } else { + /* For a unnamed type, there must be a field name, except for + * the array. */ + if((basename_len != 0) + && (basename[basename_len-1] != '_' + && (field_name[0] != '\0'))) { + strncat(basename, "_", PATH_MAX - basename_len); + basename_len = strlen(basename); + } + strncat(basename, field_name, PATH_MAX - basename_len); + } + + switch(td->type) { + case SEQUENCE: + /* Function header */ + fprintf(fd, "static inline size_t lttng_get_alignment_sequence_%s(\n", + basename); + print_tabs(2, fd); + if(print_type(td->type, fd, 0, basename, "")) return 1; + fprintf(fd, " *obj)\n"); + fprintf(fd, "{\n"); + print_tabs(1, fd); + fprintf(fd, "size_t align=0, localign;"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "localign = "); + if(print_type_alignment(((field_t*)td->fields.array[0])->type, + fd, 0, basename, field->name)) return 1; + fprintf(fd, ";\n"); + print_tabs(1, fd); + fprintf(fd, "align = max(align, localign);\n"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "localign = "); + if(print_type_alignment(((field_t*)td->fields.array[1])->type, + fd, 0, basename, field->name)) return 1; + fprintf(fd, ";\n"); + print_tabs(1, fd); + fprintf(fd, "align = max(align, localign);\n"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "return align;\n"); + break; + case STRUCT: + /* Function header */ + fprintf(fd, "static inline size_t lttng_get_alignment_struct_%s(\n", + basename); + print_tabs(2, fd); + if(print_type(td->type, fd, 0, basename, "")) return 1; + fprintf(fd, " *obj)\n"); + fprintf(fd, "{\n"); + print_tabs(1, fd); + fprintf(fd, "size_t align=0, localign;"); + fprintf(fd, "\n"); + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + print_tabs(1, fd); + fprintf(fd, "localign = "); + if(print_type_alignment(type, fd, 0, basename, field->name)) return 1; + fprintf(fd, ";\n"); + print_tabs(1, fd); + fprintf(fd, "align = max(align, localign);\n"); + fprintf(fd, "\n"); + } + print_tabs(1, fd); + fprintf(fd, "return align;\n"); + + break; + case UNION: + /* Function header */ + fprintf(fd, "static inline size_t lttng_get_alignment_union_%s(\n", + basename); + print_tabs(2, fd); + if(print_type(td->type, fd, 0, basename, "")) return 1; + fprintf(fd, " *obj)\n"); + fprintf(fd, "{\n"); + print_tabs(1, fd); + fprintf(fd, "size_t align=0, localign;"); + fprintf(fd, "\n"); + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + print_tabs(1, fd); + fprintf(fd, "localign = "); + if(print_type_alignment(type, fd, 0, basename, field->name)) return 1; + fprintf(fd, ";\n"); + print_tabs(1, fd); + fprintf(fd, "align = max(align, localign);\n"); + fprintf(fd, "\n"); + } + print_tabs(1, fd); + fprintf(fd, "return align;\n"); + + break; + case ARRAY: + /* Function header */ + fprintf(fd, "static inline size_t lttng_get_alignment_array_%s(\n", + basename); + print_tabs(2, fd); + if(print_type(td->type, fd, 0, basename, "")) return 1; + fprintf(fd, " obj)\n"); + fprintf(fd, "{\n"); + print_tabs(1, fd); + fprintf(fd, "return \n"); + if(print_type_alignment(((field_t*)td->fields.array[0])->type, + fd, 0, basename, field->name)) return 1; + fprintf(fd, ";\n"); + break; + default: + printf("print_type_alignment_fct : type has no alignment function.\n"); + break; + } + + + /* Function footer */ + fprintf(fd, "}\n"); + fprintf(fd, "\n"); + +} + +/* print type write function. + * + * Copied from construct_types_and_fields in LTTV facility.c + * + * basename is the name which identifies the type (along with a prefix + * (possibly)). */ + +int print_type_write_fct(type_descriptor_t * td, FILE *fd, unsigned int tabs, + char *nest_name, char *field_name) +{ + char basename[PATH_MAX]; + unsigned int basename_len = 0; + + strncpy(basename, nest_name, PATH_MAX); + basename_len = strlen(basename); + + /* For a named type, we use the type_name directly */ + if(td->type_name != NULL) { + strncpy(basename, td->type_name, PATH_MAX); + basename_len = strlen(basename); + } else { + /* For a unnamed type, there must be a field name, except for + * the array. */ + if((basename_len != 0) + && (basename[basename_len-1] != '_' + && (field_name[0] != '\0'))) { + strncat(basename, "_", PATH_MAX - basename_len); + basename_len = strlen(basename); + } + strncat(basename, field_name, PATH_MAX - basename_len); + } + + /* Print header */ + switch(td->type) { + case SEQUENCE: + fprintf(fd, "static inline size_t lttng_get_alignment_sequence_%s(\n", + basename); + + fprintf(fd, "lttng_get_alignment_sequence_%s(&obj->%s)", basename, + field_name); + break; + case STRUCT: + fprintf(fd, "lttng_get_alignment_struct_%s(&obj->%s)", basename, + field_name); + break; + case UNION: + fprintf(fd, "lttng_get_alignment_union_%s(&obj->%s)", basename, + field_name); break; + case ARRAY: + fprintf(fd, "lttng_get_alignment_array_%s(obj->%s)", basename, + field_name); + break; + default: + printf("print_type_write_fct : type has no write function.\n"); + break; + } + + print_tabs(2, fd); + fprintf(fd, "void *buffer,\n"); + print_tabs(2, fd); + fprintf(fd, "size_t *to_base,\n"); + print_tabs(2, fd); + fprintf(fd, "size_t *to,\n"); + print_tabs(2, fd); + fprintf(fd, "void **from,\n"); + print_tabs(2, fd); + fprintf(fd, "size_t *len,\n"); + print_tabs(2, fd); + if(print_type(td->type, fd, 0, basename, "")) return 1; + + switch(td->type) { case SEQUENCE: - fprintf(fd, "lttng_sequence_%s *", basename); - fprintf(fd, " %s", field_name); + fprintf(fd, " *obj)\n"); break; - case STRUCT: - fprintf(fd, "struct lttng_%s *", basename); - fprintf(fd, " %s", field_name); + case STRUCT: + fprintf(fd, " *obj)\n"); break; - case UNION: - fprintf(fd, "union lttng_%s *", basename); - fprintf(fd, " %s", field_name); + case UNION: + fprintf(fd, " *obj)\n"); break; - default: - printf("print_type : unknown type\n"); - return 1; + case ARRAY: + fprintf(fd, " obj)\n"); + break; + default: + printf("print_type_write_fct : type has no write function.\n"); + break; + } + + fprintf(fd, "{\n"); + print_tabs(1, fd); + fprintf(fd, "size_t align, size;\n"); + fprintf(fd, "\n"); + + switch(td->type) { + case SEQUENCE: + case STRING: + print_tabs(1, fd); + fprintf(fd, "/* Flush pending memcpy */\n"); + print_tabs(1, fd); + fprintf(fd, "if(*len != 0) {\n"); + print_tabs(2, fd); + fprintf(fd, "if(buffer != NULL)\n"); + print_tabs(3, fd); + fprintf(fd, "memcpy(buffer+*to_base+*to, *from, *len);\n"); + print_tabs(1, fd); + fprintf(fd, "}\n"); + print_tabs(1, fd); + fprintf(fd, "*to += *len;\n"); + print_tabs(1, fd); + fprintf(fd, "*len = 0;\n"); + fprintf(fd, "\n"); + break; + case STRUCT: + case UNION: + case ARRAY: + break; + default: + printf("print_type_write_fct : type has no write function.\n"); + break; + } + + print_tabs(1, fd); + fprintf(fd, "align = \n"); + if(print_type_alignment(td, fd, 0, basename, field->name)) return 1; + fprintf(fd, ";\n"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "if(*len == 0) {\n"); + print_tabs(2, fd); + fprintf(fd, "*to += ltt_align(*to, align); /* align output */\n"); + print_tabs(1, fd); + fprintf(fd, "} else {\n"); + print_tabs(2, fd); + fprintf(fd, "*len += ltt_align(*to+*len, align); /* alignment, ok to do a memcpy of it */\n"); + print_tabs(1, fd); + fprintf(fd, "}\n"); + fprintf(fd, "\n"); + + /* First, check if the type has a fixed size. If it is the case, then the size + * to write is know by the compiler : simply use a sizeof() */ + if(has_type_fixed_size(td)) { + print_tabs(1, fd); + fprintf(fd, "/* Contains only fixed size fields : use compiler sizeof() */\n"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "*len += sizeof("); + if(print_type(td, fd, 0, basename, field->name)) return 1; + fprintf(fd, ");\n"); + } else { + /* The type contains nested variable size subtypes : + * we must write field by field. */ + print_tabs(1, fd); + fprintf(fd, "/* Contains variable sized fields : must explode the structure */\n"); + fprintf(fd, "\n"); + + switch(td->type) { + case SEQUENCE: + print_tabs(1, fd); + fprintf(fd, "/* Copy members */\n"); + print_tabs(1, fd); + fprintf(fd, "size = sizeof(\n"); + if(print_type_write(((field_t*)td->fields.array[0])->type, + fd, 1, basename, field->name)) return 1; + fprintf(fd, ");\n"); + print_tabs(1, fd); + fprintf(fd, "*to += ltt_align(*to, size);\n"); + print_tabs(1, fd); + fprintf(fd, "if(buffer != NULL)\n"); + print_tabs(2, fd); + fprintf(fd, "memcpy(buffer+*to_base+*to, &obj->len, size);\n"); + print_tabs(1, fd); + fprintf(fd, "*to += size;\n"); + fprintf(fd, "\n"); + + /* Write the child : varlen child or not ? */ + if(has_type_fixed_size(((field_t*)td->fields.array[1])->type)) { + /* Fixed size len child : use a multiplication of its size */ + print_tabs(1, fd); + fprintf(fd, "size = sizeof(\n"); + if(print_type_write(((field_t*)td->fields.array[1])->type, + fd, 1, basename, field->name)) return 1; + fprintf(fd, ");\n"); + print_tabs(1, fd); + fprintf(fd, "*to += ltt_align(*to, size);\n"); + print_tabs(1, fd); + fprintf(fd, "size = obj->len * size;\n"); + print_tabs(1, fd); + fprintf(fd, "if(buffer != NULL)\n"); + print_tabs(2, fd); + fprintf(fd, "memcpy(buffer+*to_base+*to, obj->array, size);\n"); + print_tabs(1, fd); + fprintf(fd, "*to += size;\n"); + fprintf(fd, "\n"); + } else { + print_tabs(1, fd); + fprintf(fd, "/* Variable length child : iter. */\n"); + print_tabs(1, fd); + fprintf(fd, "for(unsigned int i=0; ilen; i++) {\n"); + if(print_type_write(((field_t*)td->fields.array[1])->type, + fd, 2, basename, field->name)) return 1; + print_tabs(1, fd); + fprintf(fd, "}\n"); + } + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "/* Realign the *to_base on arch size, set *to to 0 */\n"); + print_tabs(1, fd); + fprintf(fd, "*to = ltt_align(*to, sizeof(void *));\n"); + print_tabs(1, fd); + fprintf(fd, "*to_base = *to_base+*to;\n"); + print_tabs(1, fd); + fprintf(fd, "*to = 0;\n"); + fprintf(fd, "\n"); + fprintf(fd, "/* Put source *from just after the C sequence */\n"); + print_tabs(1, fd); + fprintf(fd, "*from = obj+1;\n"); + break; + case STRING: + fprintf(fd, "size = strlen(obj);\n"); + print_tabs(1, fd); + fprintf(fd, "if(buffer != NULL)\n"); + print_tabs(2, fd); + fprintf(fd, "memcpy(buffer+*to_base+*to, obj, size);\n"); + print_tabs(1, fd); + fprintf(fd, "*to += size;\n"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "/* Realign the *to_base on arch size, set *to to 0 */\n"); + print_tabs(1, fd); + fprintf(fd, "*to = ltt_align(*to, sizeof(void *));\n"); + print_tabs(1, fd); + fprintf(fd, "*to_base = *to_base+*to;\n"); + print_tabs(1, fd); + fprintf(fd, "*to = 0;\n"); + fprintf(fd, "\n"); + fprintf(fd, "/* Put source *from just after the C sequence */\n"); + print_tabs(1, fd); + fprintf(fd, "*from = obj+1;\n"); + break; + case STRUCT: + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + if(print_type_write(type, + fd, 1, basename, field->name)) return 1; + fprintf(fd, "\n"); + } + break; + case UNION: + printf("ERROR : A union CANNOT contain a variable size child.\n"); + return 1; + break; + case ARRAY: + /* Write the child : varlen child or not ? */ + if(has_type_fixed_size(((field_t*)td->fields.array[0])->type)) { + /* Error : if an array has a variable size, then its child must also + * have a variable size. */ + assert(0); + } else { + print_tabs(1, fd); + fprintf(fd, "/* Variable length child : iter. */\n"); + print_tabs(1, fd); + fprintf(fd, "for(unsigned int i=0; ifields.array[1])->type, + fd, 2, basename, field->name)) return 1; + print_tabs(1, fd); + fprintf(fd, "}\n"); + } + break; + default: + printf("print_type_write_fct : type has no write function.\n"); + break; + } + + } + + /* Function footer */ + fprintf(fd, "}\n"); + fprintf(fd, "\n"); return 0; } - /* Print the logging function of an event. This is the core of genevent */ -int print_event_logging_function(char *basename, event_t *event, FILE *fd) +int print_event_logging_function(char *basename, facility_t *fac, + event_t *event, FILE *fd) { fprintf(fd, "static inline void trace_%s(\n", basename); for(unsigned int j = 0; j < event->fields.position; j++) { @@ -945,42 +1148,155 @@ int print_event_logging_function(char *basename, event_t *event, FILE *fd) fprintf(fd, "{\n"); /* Print the function variables */ print_tabs(1, fd); - fprintf(fd, "size_t member_length;"); - fprintf(fd, "size_t event_length = 0;"); + fprintf(fd, "unsigned int index;\n"); + print_tabs(1, fd); + fprintf(fd, "struct ltt_channel_struct *channel;\n"); + print_tabs(1, fd); + fprintf(fd, "struct ltt_trace_struct *trace;\n"); + print_tabs(1, fd); + fprintf(fd, "struct rchan_buf *relayfs_buf;\n"); + print_tabs(1, fd); + fprintf(fd, "void *buffer = NULL;\n"); + print_tabs(1, fd); + fprintf(fd, "size_t to_base = 0; /* The buffer is allocated on arch_size alignment */\n"); + print_tabs(1, fd); + fprintf(fd, "size_t to = 0;\n"); + print_tabs(1, fd); + fprintf(fd, "void *from;"); + print_tabs(1, fd); + fprintf(fd, "size_t len = 0;\n"); + fprintf(fd, "\n"); + fprintf(fd, "size_t slot_size;\n"); + fprintf(fd, "\n"); + fprintf(fd, "cycles_t tsc;\n"); + fprintf(fd, "\n"); + fprintf(fd, "size_t before_hdr_pad, size_t after_hdr_pad;\n"); + fprintf(fd, "\n"); + print_tabs(1, fd); + fprintf(fd, "if(ltt_traces.num_active_traces == 0) return;\n"); + fprintf(fd, "\n"); + /* Calculate event variable len + event data alignment offset. * Assume that the padding for alignment starts at a void* * address. * This excludes the header size and alignment. */ + print_tabs(1, fd); + fprintf(fd, "/* For each field, calculate the field size. */\n"); + print_tabs(1, fd); + fprintf(fd, "/* size = to_base + to + len */\n"); + print_tabs(1, fd); + fprintf(fd, "/* Assume that the padding for alignment starts at a void*\n"); + print_tabs(1, fd); + fprintf(fd, "/* address. */\n"); + fprintf(fd, "\n"); - for(unsigned int j = 0; j < event->fields.position; j++) { - /* For each field, calculate the field size. */ - field_t *f = (field_t*)event->fields.array[j]; - type_descriptor_t *t = f->type; - if(print_field_len(t, fd, 1, basename, "", - f->name, - "event_length", - "member_length")) return 1; - if(j < event->fields.position-1) { - fprintf(fd, ","); - fprintf(fd, "\n"); - } + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + if(print_type_write(type, + fd, 1, basename, field->name)) return 1; + fprintf(fd, "\n"); } /* Take locks : make sure the trace does not vanish while we write on * it. A simple preemption disabling is enough (using rcu traces). */ + print_tabs(1, fd); + fprintf(fd, "preempt_disable();\n"); + print_tabs(1, fd); + fprintf(fd, "ltt_nesting[smp_processor_id()]++;\n"); + + /* Get facility index */ + + if(event->per_tracefile) { + print_tabs(1, fd); + fprintf(fd, "index = tracefile_index;\n"); + } else { + print_tabs(1, fd); + fprintf(fd, + "index = ltt_get_index_from_facility(ltt_facility_%s_%X,\n"\ + "\t\t\t\tevent_%s);\n", + fac->name, fac->checksum, event->name); + } + fprintf(fd,"\n"); + /* For each trace */ + print_tabs(1, fd); + fprintf(fd, "list_for_each_entry_rcu(trace, <t_traces.head, list) {\n"); + print_tabs(2, fd); + fprintf(fd, "if(!trace->active) continue;\n\n"); + + if(event->per_trace) { + print_tabs(2, fd); + fprintf(fd, "if(dest_trace != trace) continue;\n\n"); + } + + print_tabs(2, fd); + fprintf(fp, "channel = ltt_get_channel_from_index(trace, index);\n"); + print_tabs(2, fd); + fprintf(fd, "relayfs_buf = channel->rchan->buf[channel->rchan->buf->cpu];\n"); + fprintf(fd, "\n"); + /* Relay reserve */ - /* If error, increment counter and return */ + /* If error, increment event lost counter (done by ltt_reserve_slot) and + * return */ + print_tabs(2, fd); + fprintf(fd, "slot_size = 0;\n"); + print_tabs(2, fd); + fprintf(fd, "buffer = ltt_reserve_slot(trace, relayfs_buf, to_base + to + len, &slot_size, &tsc,\n" + "\t\t&before_hdr_pad, &after_hdr_pad);\n"); + /* If error, return */ + print_tabs(2, fd); + fprintf(fd, "if(!buffer) return;\n\n"); - /* write data */ + /* write data : assume stack alignment is the same as struct alignment. */ + + for(unsigned int i=0;ifields.position;i++){ + field_t *field = (field_t*)(td->fields.array[i]); + type_descriptor_t *type = field->type; + + /* Set from */ + print_tabs(3, fd); + fprintf(fd, "from = %s;\n", f->name); + + if(print_type_write(type, + fd, 2, basename, field->name)) return 1; + fprintf(fd, "\n"); + /* Don't forget to flush pending memcpy */ + print_tabs(2, fd); + fprintf(fd, "/* Flush pending memcpy */\n"); + print_tabs(2, fd); + fprintf(fd, "if(len != 0) {\n"); + print_tabs(3, fd); + fprintf(fd, "memcpy(buffer+to_base+to, from, len);\n"); + print_tabs(3, fd); + fprintf(fd, "to += len;\n"); + //print_tabs(3, fd); + //fprintf(fd, "from += len;\n"); + print_tabs(3, fd); + fprintf(fd, "len = 0;\n"); + print_tabs(2, fd); + fprintf(fd, "}\n"); + fprintf(fd, "\n"); + } + + /* commit */ + print_tabs(2, fd); + fprintf(fd, "ltt_commit_slot(relayfs_buf, buffer, slot_size);\n\n"); + print_tabs(1, fd); + fprintf(fd, "}\n\n"); + /* Release locks */ + print_tabs(1, fd); + fprintf(fd, "ltt_nesting[smp_processor_id()]--;\n"); + print_tabs(1, fd); + fprintf(fd, "preempt_enable_no_resched();\n"); fprintf(fd, "}\n"); fprintf(fd, "#endif //CONFIG_LTT\n\n"); @@ -1046,7 +1362,7 @@ int print_log_header_events(facility_t *fac, FILE *fd) fprintf(fd, "/* Event %s logging function */\n", event->name); - if(print_event_logging_function(basename, event, fd)) return 1; + if(print_event_logging_function(basename, fac, event, fd)) return 1; fprintf(fd, "\n"); } diff --git a/genevent-new/gentest.c b/genevent-new/gentest.c index 67556797..753ac4d7 100644 --- a/genevent-new/gentest.c +++ b/genevent-new/gentest.c @@ -322,6 +322,8 @@ static inline void lttng_write_mystruct_myunion( } *len += size; + + /* Assert : no varlen child. */ } @@ -428,9 +430,9 @@ static inline void lttng_write_mystruct( /* Variable length field */ lttng_write_sequence_mystruct_mysequence(buffer, to_base, to, from, len, &obj->mysequence); - /* After this previous write, we are sure that *to is 0, and *to_base is - * aligned on the architecture size : to rest of alignment will be calculated - * statically. */ + /* After this previous write, we are sure that *to is 0, *len is 0 and + * *to_base is aligned on the architecture size : to rest of alignment will + * be calculated statically. */ lttng_write_mystruct_myunion(buffer, to_base, to, from, len, &obj->myunion); diff --git a/genevent-new/parser.c b/genevent-new/parser.c index a2a07e21..e5e64ab1 100644 --- a/genevent-new/parser.c +++ b/genevent-new/parser.c @@ -3,14 +3,15 @@ parser.c: Generate helper declarations and functions to trace events from an event description file. -Copyright (C) 2002, Xianxiu Yang -Copyright (C) 2002, Michel Dagenais -This program is free software; you can redistribute it and/or modify + Copyright (C) 2005, Mathieu Desnoyers + Copyright (C) 2002, Xianxiu Yang + Copyright (C) 2002, Michel Dagenais + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; version 2 of the License. + the Free Software Foundation; version 2 of the License. -This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. -- 2.34.1