+ /* 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\n");
+ print_tabs(1, fd);
+ fprintf(fd, " * sizeof(void *) address. */\n");
+ fprintf(fd, "\n");
+
+ for(unsigned int i=0;i<event->fields.position;i++){
+ field_t *field = (field_t*)(event->fields.array[i]);
+ type_descriptor_t *type = field->type;
+ /* Set from */
+ print_tabs(1, fd);
+ switch(type->type) {
+ case SEQUENCE:
+ case UNION:
+ case ARRAY:
+ case STRUCT:
+ case STRING:
+ fprintf(fd, "*from = lttng_param_%s;\n", field->name);
+ break;
+ default:
+ fprintf(fd, "*from = <tng_param_%s;\n", field->name);
+ break;
+ }
+
+ if(print_type_write(type,
+ fd, 1, basename, field->name, "lttng_param_", 0)) return 1;
+ fprintf(fd, "\n");
+ }
+ print_tabs(1, fd);
+ fprintf(fd, "reserve_size = *to_base + *to + *len;\n");
+
+ print_tabs(1, fd);
+ fprintf(fd, "{\n");
+ print_tabs(2, fd);
+ fprintf(fd, "char stack_buffer[reserve_size];\n");
+ print_tabs(2, fd);
+ fprintf(fd, "buffer = stack_buffer;\n");
+ fprintf(fd, "\n");
+
+
+ //print_tabs(2, fd);
+ // for DEBUG only
+ // fprintf(fd, "goto commit; /* DEBUG : never actually write. */\n\n");
+ print_tabs(2, fd);
+ fprintf(fd, "*to_base = *to = *len = 0;\n");
+ fprintf(fd, "\n");
+
+ /* write data. */
+
+ for(unsigned int i=0;i<event->fields.position;i++){
+ field_t *field = (field_t*)(event->fields.array[i]);
+ type_descriptor_t *type = field->type;
+
+ /* Set from */
+ print_tabs(2, fd);
+ switch(type->type) {
+ case SEQUENCE:
+ case UNION:
+ case ARRAY:
+ case STRUCT:
+ case STRING:
+ fprintf(fd, "*from = lttng_param_%s;\n", field->name);
+ break;
+ default:
+ fprintf(fd, "*from = <tng_param_%s;\n", field->name);
+ break;
+ }
+
+
+ if(print_type_write(type,
+ fd, 2, basename, field->name, "lttng_param_", 0)) 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");
+ }
+
+do_syscall:
+ print_tabs(2, fd);
+ fprintf(fd, "ret = ltt_trace_generic(ltt_facility_%s_%X, event_%s_%s, buffer, reserve_size, LTT_BLOCKING);\n", fac->name, fac->checksum, fac->name, event->name);
+
+ print_tabs(1, fd);
+ fprintf(fd, "}\n\n");
+
+ print_tabs(1, fd);
+ fprintf(fd, "return ret;\n\n");
+
+ fprintf(fd, "}\n");
+ fprintf(fd,
+ "#endif //LTT_TRACE\n");
+ fprintf(fd, "#endif //!LTT_TRACE_FAST\n\n");
+
+ return 0;
+}
+
+/* print_event_logging_function_user_fast
+ * Print the logging function of an event for userspace tracing. This is the
+ * core of genevent */
+int print_event_logging_function_user_fast(char *basename, facility_t *fac,
+ event_t *event, FILE *fd)
+{
+ char *attrib;
+
+ fprintf(fd, "#ifdef LTT_TRACE_FAST\n");
+
+ if(event->no_instrument_function) {
+ attrib = "__attribute__((no_instrument_function)) ";
+ } else {
+ attrib = "";
+ }
+ fprintf(fd, "static inline %sint trace_%s(\n",attrib, basename);
+
+ int has_argument = 0;
+ int has_type_fixed = 0;
+
+ for(unsigned int j = 0; j < event->fields.position; j++) {
+ /* For each field, print the function argument */
+ field_t *f = (field_t*)event->fields.array[j];
+ type_descriptor_t *t = f->type;
+ if(has_argument) {
+ fprintf(fd, ",");
+ fprintf(fd, "\n");
+ }
+ if(print_arg(t, fd, 2, basename, f->name)) return 1;
+ has_argument = 1;
+ }
+ if(!has_argument) {
+ print_tabs(2, fd);
+ fprintf(fd, "void");
+ }
+ fprintf(fd,")\n");
+ fprintf(fd,
+ "#ifndef LTT_TRACE\n");
+ fprintf(fd, "{\n");
+ fprintf(fd, "}\n");
+ fprintf(fd,"#else\n");
+ fprintf(fd, "{\n");
+ /* Print the function variables */
+ print_tabs(1, fd);
+ fprintf(fd, "unsigned int index;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "struct ltt_trace_info *trace = thread_trace_info;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "struct ltt_buf *ltt_buf;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "void *buffer = NULL;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "size_t real_to_base = 0; /* The buffer is allocated on arch_size alignment */\n");
+ print_tabs(1, fd);
+ fprintf(fd, "size_t *to_base = &real_to_base;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "size_t real_to = 0;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "size_t *to = &real_to;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "size_t real_len = 0;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "size_t *len = &real_len;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "size_t reserve_size;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "size_t slot_size;\n");
+ print_tabs(1, fd);
+
+ if(event->fields.position > 0) {
+ for(unsigned int i=0;i<event->fields.position;i++){
+ /* Search for at least one child with fixed size. It means
+ * we need local variables.*/
+ field_t *field = (field_t*)(event->fields.array[i]);
+ type_descriptor_t *type = field->type;
+ has_type_fixed = has_type_local(type);
+ if(has_type_fixed) break;
+ }
+
+ if(has_type_fixed) {
+ fprintf(fd, "size_t align;\n");
+ print_tabs(1, fd);
+ }
+
+ fprintf(fd, "const void *real_from;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "const void **from = &real_from;\n");
+ print_tabs(1, fd);
+ }
+ fprintf(fd, "uint64_t tsc;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "size_t before_hdr_pad, after_hdr_pad, header_size;\n");
+ fprintf(fd, "\n");
+
+ print_tabs(1, fd);
+ fprintf(fd, "if(!trace) {\n");
+ print_tabs(2, fd);
+ fprintf(fd, "ltt_thread_init();\n");
+ print_tabs(2, fd);
+ fprintf(fd, "trace = thread_trace_info;\n");
+ print_tabs(1, fd);
+ fprintf(fd, "}\n\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\n");
+ print_tabs(1, fd);
+ fprintf(fd, " * sizeof(void *) address. */\n");
+ fprintf(fd, "\n");
+
+ for(unsigned int i=0;i<event->fields.position;i++){
+ field_t *field = (field_t*)(event->fields.array[i]);
+ type_descriptor_t *type = field->type;
+ /* Set from */
+ print_tabs(1, fd);
+ switch(type->type) {
+ case SEQUENCE:
+ case UNION:
+ case ARRAY:
+ case STRUCT:
+ case STRING:
+ fprintf(fd, "*from = lttng_param_%s;\n", field->name);
+ break;
+ default:
+ fprintf(fd, "*from = <tng_param_%s;\n", field->name);
+ break;
+ }
+
+ if(print_type_write(type,
+ fd, 1, basename, field->name, "lttng_param_", 0)) return 1;
+ fprintf(fd, "\n");
+ }
+ print_tabs(1, fd);
+ fprintf(fd, "reserve_size = *to_base + *to + *len;\n");
+
+ print_tabs(1, fd);
+ fprintf(fd, "trace->nesting++;\n");
+
+ /* Get facility index */
+
+ print_tabs(1, fd);
+ fprintf(fd,
+ "index = ltt_get_index_from_facility(ltt_facility_%s_%X,\n"\
+ "\t\t\t\t\t\tevent_%s_%s);\n",
+ fac->name, fac->checksum, fac->name, event->name);
+ fprintf(fd,"\n");
+
+
+ print_tabs(1, fd);
+ fprintf(fd, "{\n");
+
+ if(event->per_trace) {
+ print_tabs(2, fd);
+ fprintf(fd, "if(dest_trace != trace) continue;\n\n");
+ }
+
+ print_tabs(2, fd);
+ fprintf(fd, "ltt_buf = ltt_get_channel_from_index(trace, index);\n");
+ print_tabs(2, fd);
+
+
+ /* Relay reserve */
+ /* 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, ltt_buf,\n");
+ print_tabs(3, fd);
+ fprintf(fd, "reserve_size, &slot_size, &tsc,\n");
+ print_tabs(3, fd);
+ fprintf(fd, "&before_hdr_pad, &after_hdr_pad, &header_size);\n");
+ /* If error, return */
+ print_tabs(2, fd);
+ fprintf(fd, "if(!buffer) goto end; /* buffer full */\n\n");
+ //print_tabs(2, fd);
+ // for DEBUG only
+ // fprintf(fd, "goto commit; /* DEBUG : never actually write. */\n\n");
+ print_tabs(2, fd);
+ fprintf(fd, "*to_base = *to = *len = 0;\n");
+ fprintf(fd, "\n");
+
+ /* Write event header */
+ print_tabs(2, fd);
+ fprintf(fd, "ltt_write_event_header(trace, ltt_buf, buffer,\n");
+ print_tabs(3, fd);
+ fprintf(fd, "ltt_facility_%s_%X, event_%s_%s,\n", fac->name, fac->checksum,
+ fac->name, event->name);
+ print_tabs(3, fd);
+ fprintf(fd, "reserve_size, before_hdr_pad, tsc);\n");
+ print_tabs(2, fd);
+ fprintf(fd, "*to_base += before_hdr_pad + after_hdr_pad + header_size;\n");
+ fprintf(fd, "\n");
+
+ /* write data. */
+
+ for(unsigned int i=0;i<event->fields.position;i++){
+ field_t *field = (field_t*)(event->fields.array[i]);
+ type_descriptor_t *type = field->type;
+
+ /* Set from */
+ print_tabs(2, fd);
+ switch(type->type) {
+ case SEQUENCE:
+ case UNION:
+ case ARRAY:
+ case STRUCT:
+ case STRING:
+ fprintf(fd, "*from = lttng_param_%s;\n", field->name);
+ break;
+ default:
+ fprintf(fd, "*from = <tng_param_%s;\n", field->name);
+ break;
+ }
+
+
+ if(print_type_write(type,
+ fd, 2, basename, field->name, "lttng_param_", 0)) 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 */
+ // for DEBUG only.
+ //fprintf(fd, "commit:\n"); /* DEBUG! */
+ print_tabs(2, fd);
+ fprintf(fd, "ltt_commit_slot(ltt_buf, buffer, slot_size);\n\n");
+
+ fprintf(fd, "}\n\n");
+
+ fprintf(fd, "end:\n");
+ /* Release locks */
+ print_tabs(1, fd);
+ fprintf(fd, "trace->nesting--;\n");
+
+
+ fprintf(fd, "}\n");
+ fprintf(fd,
+ "#endif //LTT_TRACE\n");
+ fprintf(fd, "#endif //LTT_TRACE_FAST\n");
+
+ return 0;
+}
+
+
+
+
+
+
+/* ltt-facility-name.h : main logging header.
+ * log_header */
+
+void print_log_header_head(facility_t *fac, FILE *fd)
+{
+ fprintf(fd, "#ifndef _LTT_FACILITY_%s_H_\n", fac->capname);
+ fprintf(fd, "#define _LTT_FACILITY_%s_H_\n\n", fac->capname);
+ fprintf(fd, "#include <linux/types.h>\n");
+ if(!fac->arch)
+ fprintf(fd, "#include <linux/ltt/ltt-facility-id-%s.h>\n", fac->name);
+ else
+ fprintf(fd, "#include <asm/ltt/ltt-facility-id-%s_%s.h>\n",
+ fac->name,
+ fac->arch);
+ fprintf(fd, "#include <linux/ltt-core.h>\n");
+ fprintf(fd, "\n");
+}
+
+/* ltt-facility-name.h : main logging header.
+ * log_header */
+
+void print_log_header_head_user(facility_t *fac, FILE *fd)
+{
+ fprintf(fd, "#ifndef _LTT_FACILITY_%s_H_\n", fac->capname);
+ fprintf(fd, "#define _LTT_FACILITY_%s_H_\n\n", fac->capname);
+ fprintf(fd, "#include <sys/types.h>\n");
+ if(!fac->arch)
+ fprintf(fd, "#include <ltt/ltt-facility-id-%s.h>\n", fac->name);
+ else
+ fprintf(fd, "#include <asm/ltt/ltt-facility-id-%s_%s.h>\n",
+ fac->name,
+ fac->arch);
+ fprintf(fd, "#include <ltt/ltt-generic.h>\n");
+ fprintf(fd, "\n");
+}
+
+
+int print_log_header_types(facility_t *fac, FILE *fd)
+{
+ sequence_t *types = &fac->named_types.values;
+ fprintf(fd, "/* Named types */\n");
+ fprintf(fd, "\n");
+
+ for(unsigned int i = 0; i < types->position; i++) {
+ /* For each named type, print the definition */
+ if(print_type_declaration(types->array[i], fd,
+ 0, "", "")) return 1;
+ /* Print also the align function */
+ if(print_type_alignment_fct(types->array[i], fd,
+ 0, "", "")) return 1;
+ /* Print also the write function */
+ if(print_type_write_fct(types->array[i], fd,
+ 0, "", "")) return 1;
+ }
+ return 0;
+}
+
+int print_log_header_events(facility_t *fac, FILE *fd)
+{
+ sequence_t *events = &fac->events;
+ char basename[PATH_MAX];
+ unsigned int facname_len;
+
+ strncpy(basename, fac->name, PATH_MAX);
+ facname_len = strlen(basename);
+ strncat(basename, "_", PATH_MAX-facname_len);
+ facname_len = strlen(basename);
+
+ for(unsigned int i = 0; i < events->position; i++) {
+ event_t *event = (event_t*)events->array[i];
+ strncpy(&basename[facname_len], event->name, PATH_MAX-facname_len);
+
+ /* For each event, print structure, and then logging function */
+ fprintf(fd, "/* Event %s structures */\n",
+ event->name);
+ for(unsigned int j = 0; j < event->fields.position; j++) {
+ /* For each unnamed type, print the definition */
+ field_t *f = (field_t*)event->fields.array[j];
+ type_descriptor_t *t = f->type;
+ if(t->type_name == NULL) {
+ if((print_type_declaration(t, fd, 0, basename, f->name))) return 1;
+ /* Print also the align function */
+ if((print_type_alignment_fct(t, fd, 0, basename, f->name))) return 1;
+ /* Print also the write function */
+ if((print_type_write_fct(t, fd, 0, basename, f->name))) return 1;
+ }
+ }
+
+ fprintf(fd, "\n");
+
+ fprintf(fd, "/* Event %s logging function */\n",
+ event->name);
+
+ if(!fac->user) {
+ if(print_event_logging_function(basename, fac, event, fd)) return 1;
+ } else {
+ if(print_event_logging_function_user_generic(basename, fac, event, fd))
+ return 1;
+ if(print_event_logging_function_user_fast(basename, fac, event, fd))
+ return 1;
+ }
+
+ fprintf(fd, "\n");
+ }
+
+ return 0;
+}
+
+
+void print_log_header_tail(facility_t *fac, FILE *fd)
+{
+ fprintf(fd, "#endif //_LTT_FACILITY_%s_H_\n",fac->capname);
+}
+
+void print_log_header_tail_user(facility_t *fac, FILE *fd)