code finished, not compiled yet
authorcompudj <compudj@04897980-b3bd-0310-b5e0-8ef037075253>
Thu, 1 Dec 2005 18:05:05 +0000 (18:05 +0000)
committercompudj <compudj@04897980-b3bd-0310-b5e0-8ef037075253>
Thu, 1 Dec 2005 18:05:05 +0000 (18:05 +0000)
git-svn-id: http://ltt.polymtl.ca/svn@1348 04897980-b3bd-0310-b5e0-8ef037075253

genevent-new/genevent.c
genevent-new/gentest.c
genevent-new/parser.c

index 124168d27efc51baeb7d12ef3d2e1ee7a96f6858..4042dafafdeda23986643873853d0e60e71b8c3b 100644 (file)
@@ -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;i<td->fields.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,
-                       &current_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,
-        &current_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;i<type->element_number;i++) {
-        preset_field_type_size(
-          current_offset, 
-          &current_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;i<type->element_number;i++) {
-        enum field_status current_child_status = FIELD_FIXED;
-        preset_field_type_size(
-          current_offset, 
-          &current_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;i<seqnum;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_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;i<field->field_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;i<type->element_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;i<type->element_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;i<td->fields.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;i<td->fields.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; i<obj->len; 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;i<td->fields.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; i<LTTNG_ARRAY_SIZE_%s; i++) {\n", basename);
+                                       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");
+                               }
+                               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;i<event->fields.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, &ltt_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;i<event->fields.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");
        }
index 67556797628c5f91476c439420bbd2016e480e27..753ac4d7895663e5d0b668ce059fde17e1d9ebbb 100644 (file)
@@ -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);
 
index a2a07e212c054adaca1dea3b9e95152b6a3f91aa..e5e64ab17d0564bcca8a18b0291f425370bceb7a 100644 (file)
@@ -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.
 
This page took 0.039501 seconds and 4 git commands to generate.