316f15b7a076bf8e44be56b2943a1deb94a1ccf9
[lttv.git] / genevent / genevent.c
1 /*
2
3 genevent.c: Generate helper declarations and functions to trace events
4 from an event description file.
5
6 Copyright (C) 2002, Xianxiu Yang
7 Copyright (C) 2002, Michel Dagenais
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 /* This program reads the ".event" event definitions input files
24 specified as command line arguments and generates corresponding
25 ".c" and ".h" files required to trace such events in the kernel.
26
27 The program uses a very simple tokenizer, called from a hand written
28 recursive descent parser to fill a data structure describing the events.
29 The result is a sequence of events definitions which refer to type
30 definitions.
31
32 A table of named types is maintained to allow refering to types by name
33 when the same type is used at several places. Finally a sequence of
34 all types is maintained to facilitate the freeing of all type
35 information when the processing of an ".event" file is finished. */
36
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include <stdio.h>
41 #include <stdarg.h>
42 #include <linux/errno.h>
43 #include <assert.h>
44
45 #include "parser.h"
46 #include "genevent.h"
47
48 #define max(a,b) ((a)<(b))?(b):(a)
49
50 /* Named types may be referenced from anywhere */
51
52 facility * fac;
53
54 unsigned alignment = 0;
55
56 int main(int argc, char** argv)
57 {
58 char *token;
59 parse_file in;
60 char buffer[BUFFER_SIZE];
61 int i;
62
63 if(argc < 2){
64 printf("At least one event definition file is needed\n");
65 printf("You may specify the default alignment for a facility with\n");
66 printf(" -a x , where x is the desired alignment in bytes.\n");
67 printf("The alignment value will affect all the following xml files.\n");
68 printf("i.e. genevent -a 8 core.xml -a 4 kernel.xml is valid.\n");
69 exit(1);
70 }
71
72 in.buffer = buffer;
73 in.error = error_callback;
74
75 for(i = 1 ; i < argc ; i++) {
76
77 if(strcmp("-a", argv[i])==0) {
78 if(i >= argc-1) {
79 printf("Error : missing argument to -a\n");
80 exit(1);
81 } else i++;
82 alignment = atoi(argv[i]);
83 } else {
84
85 in.lineno = 0;
86 in.name = allocAndCopy(argv[i]);
87
88 in.fp = fopen(in.name, "r");
89 if(!in.fp ){
90 in.error(&in,"cannot open facility input file");
91 }
92
93 while(1){
94 token = getToken(&in);
95 if(in.type == ENDFILE) break;
96
97 if(strcmp(token, "<")) in.error(&in,"not a facility file");
98 token = getName(&in);
99
100 if(strcmp("facility",token) == 0) {
101 fac = memAlloc(sizeof(facility));
102 fac->name = NULL;
103 fac->description = NULL;
104 sequence_init(&(fac->events));
105 table_init(&(fac->named_types));
106 sequence_init(&(fac->unnamed_types));
107
108 parseFacility(&in, fac);
109
110 //check if any namedType is not defined
111 checkNamedTypesImplemented(&fac->named_types);
112 }
113 else in.error(&in,"facility token was expected");
114
115 generateFile(argv[i]);
116
117 free(fac->name);
118 free(fac->description);
119 freeEvents(&fac->events);
120 sequence_dispose(&fac->events);
121 freeNamedType(&fac->named_types);
122 table_dispose(&fac->named_types);
123 freeTypes(&fac->unnamed_types);
124 sequence_dispose(&fac->unnamed_types);
125 free(fac);
126 }
127
128 free(in.name);
129 fclose(in.fp);
130 }
131 }
132 return 0;
133 }
134
135
136 /*****************************************************************************
137 *Function name
138 * generateFile : generate .c and .h file
139 *Input Params
140 * name : name of event definition file
141 ****************************************************************************/
142 void generateFile(char *name){
143 char *loadName, *hName, *hIdName, *cName, *tmp, *tmp2;
144 FILE * lFp, *hFp, *iFp, *cFp;
145 int nbEvent;
146 unsigned long checksum=0;
147
148 //remove .xml if it exists
149 tmp = &name[strlen(name)-4];
150 if(strcmp(tmp, ".xml") == 0){
151 *tmp = '\0';
152 }
153
154 tmp = strrchr(name,'/');
155 if(tmp){
156 tmp++;
157 }else{
158 tmp = name;
159 }
160
161 loadName = appendString("ltt-facility-loader-", tmp);
162 tmp2 = appendString(loadName,".h");
163 free(loadName);
164 loadName = tmp2;
165 hName = appendString("ltt-facility-", tmp);
166 tmp2 = appendString(hName,".h");
167 free(hName);
168 hName = tmp2;
169 hIdName = appendString("ltt-facility-id-", tmp);
170 tmp2 = appendString(hIdName,".h");
171 free(hIdName);
172 hIdName = tmp2;
173 cName = appendString("ltt-facility-loader-", tmp);
174 tmp2 = appendString(cName,".c");
175 free(cName);
176 cName = tmp2;
177 lFp = fopen(loadName,"w");
178 if(!lFp){
179 printf("Cannot open the file : %s\n",loadName);
180 exit(1);
181 }
182
183 hFp = fopen(hName,"w");
184 if(!hFp){
185 printf("Cannot open the file : %s\n",hName);
186 exit(1);
187 }
188
189 iFp = fopen(hIdName,"w");
190 if(!iFp){
191 printf("Cannot open the file : %s\n",hIdName);
192 exit(1);
193 }
194
195 cFp = fopen(cName,"w");
196 if(!cFp){
197 printf("Cannot open the file : %s\n",cName);
198 exit(1);
199 }
200
201 free(loadName);
202 free(hName);
203 free(hIdName);
204 free(cName);
205
206 generateChecksum(fac->name, &checksum, &(fac->events));
207
208 /* generate .h file, event enumeration then structures and functions */
209 fprintf(iFp, "#ifndef _LTT_FACILITY_ID_%s_H_\n",fac->capname);
210 fprintf(iFp, "#define _LTT_FACILITY_ID_%s_H_\n\n",fac->capname);
211 fprintf(iFp, "#ifdef CONFIG_LTT\n");
212 generateEnumEvent(iFp, fac->name, &nbEvent, checksum);
213 fprintf(iFp, "#endif //CONFIG_LTT\n");
214 fprintf(iFp, "#endif //_LTT_FACILITY_ID_%s_H_\n",fac->capname);
215
216
217 fprintf(hFp, "#ifndef _LTT_FACILITY_%s_H_\n",fac->capname);
218 fprintf(hFp, "#define _LTT_FACILITY_%s_H_\n\n",fac->capname);
219 //fprintf(hFp, "#ifdef CONFIG_LTT\n");
220 generateTypeDefs(hFp, fac->name);
221 generateStructFunc(hFp, fac->name,checksum);
222 //fprintf(hFp, "#endif //CONFIG_LTT\n");
223 fprintf(hFp, "#endif //_LTT_FACILITY_%s_H_\n",fac->capname);
224
225 /* generate .h file, calls to register the facility at init time */
226 generateLoaderfile(lFp,fac->name,nbEvent,checksum,fac->capname);
227
228 // create ltt-facility-loader-facname.c
229 generateCfile(cFp, tmp);
230
231 fclose(hFp);
232 fclose(iFp);
233 fclose(lFp);
234 fclose(cFp);
235
236 }
237
238
239 /*****************************************************************************
240 *Function name
241 * generateEnumEvent : output event enum to .h file
242 *Input Params
243 * fp : file to be written to
244 * facName : name of facility
245 *Output Params
246 * nbEvent : number of events in the facility
247 ****************************************************************************/
248 void generateEnumEvent(FILE *fp, char *facName, int * nbEvent, unsigned long checksum) {
249 int pos = 0;
250
251 fprintf(fp,"#include <linux/ltt-facilities.h>\n\n");
252
253 fprintf(fp,"/**** facility handle ****/\n\n");
254 fprintf(fp,"extern ltt_facility_t ltt_facility_%s_%X;\n",facName, checksum);
255 fprintf(fp,"extern ltt_facility_t ltt_facility_%s;\n\n\n",facName, checksum);
256
257 fprintf(fp,"/**** event type ****/\n\n");
258 fprintf(fp,"enum %s_event {\n",facName);
259
260 for(pos = 0; pos < fac->events.position;pos++) {
261 fprintf(fp,"\tevent_%s", ((event *)(fac->events.array[pos]))->name);
262 if(pos != fac->events.position-1) fprintf(fp,",\n");
263 }
264 fprintf(fp,"\n};\n\n\n");
265
266 // fprintf(fp,"/**** number of events in the facility ****/\n\n");
267 // fprintf(fp,"int nbEvents_%s = %d;\n\n\n",facName, fac->events.position);
268 *nbEvent = fac->events.position;
269 }
270
271
272 /*****************************************************************************
273 *Function name
274 * printStruct : Generic struct printing function
275 *Input Params
276 * fp : file to be written to
277 * len : number of fields
278 * array : array of field info
279 * name : basic struct name
280 * facName : name of facility
281 * whichTypeFirst : struct or array/sequence first
282 * hasStrSeq : string or sequence present?
283 * structCount : struct postfix
284 ****************************************************************************/
285
286 static void
287 printStruct(FILE * fp, int len, void ** array, char * name, char * facName,
288 int * whichTypeFirst, int * hasStrSeq, int * structCount,
289 type_descriptor *type)
290 {
291 int flag = 0;
292 int pos;
293 field * fld;
294 type_descriptor * td;
295
296 for (pos = 0; pos < len; pos++) {
297 fld = (field *)array[pos];
298 td = fld->type;
299 if( td->type == STRING || td->type == SEQUENCE ||
300 td->type == ARRAY) {
301 (*hasStrSeq)++;
302 }
303 // if (*whichTypeFirst == 0) {
304 // *whichTypeFirst = 1; //struct first
305 // }
306 if (flag == 0) {
307 flag = 1;
308
309 fprintf(fp,"struct %s_%s",name, facName);
310 if (structCount) {
311 fprintf(fp, "_%d {\n",++*structCount);
312 } else {
313 fprintf(fp, " {\n");
314 }
315 }
316 fprintf(fp, "\t%s %s; /* %s */\n",
317 getTypeStr(td),fld->name,fld->description );
318 #if 0
319 } else {
320 if (*whichTypeFirst == 0) {
321 //string or sequence or array first
322 *whichTypeFirst = 2;
323 }
324 (*hasStrSeq)++;
325 if(flag) {
326 fprintf(fp,"} __attribute__ ((packed));\n\n");
327 }
328 flag = 0;
329 }
330 #endif //0
331 }
332
333 if(flag) {
334 unsigned align = max(alignment, type->alignment);
335
336 if(align == 0)
337 fprintf(fp,"} __attribute__ ((packed));\n\n");
338 else {
339 if(align != 1 && align != 2
340 && align != 4 && align != 8) {
341 printf("Wrong alignment %i, using packed.\n", align);
342 fprintf(fp,"} __attribute__ ((packed));\n\n");
343 } else
344 fprintf(fp,"} __attribute__ ((aligned(%i)));\n\n", align);
345 }
346 }
347 }
348
349
350 /*****************************************************************************
351 *Function name
352 * generateHfile : Create the typedefs
353 *Input Params
354 * fp : file to be written to
355 ****************************************************************************/
356 void
357 generateTypeDefs(FILE * fp, char *facName)
358 {
359 int pos, tmp = 1;
360
361 fprintf(fp,"#include <linux/types.h>\n");
362 fprintf(fp,"#include <linux/spinlock.h>\n");
363 fprintf(fp,"#include <linux/ltt/ltt-facility-id-%s.h>\n\n", facName);
364 fprintf(fp,"#include <linux/ltt-core.h>\n");
365
366 #if 0 //broken
367 fprintf(fp, "/**** Basic Type Definitions ****/\n\n");
368
369 for (pos = 0; pos < fac->named_types.values.position; pos++) {
370 type_descriptor * type =
371 (type_descriptor*)fac->named_types.values.array[pos];
372 printStruct(fp, type->fields.position, type->fields.array,
373 "", type->type_name, &tmp, &tmp, NULL);
374 fprintf(fp, "typedef struct _%s %s;\n\n",
375 type->type_name, type->type_name);
376 }
377 #endif //0
378 }
379
380
381 /*****************************************************************************
382 *Function name
383 * generateEnumDefinition: generate enum definition if it exists
384 *Input Params
385 * fp : file to be written to
386 * fHead : enum type
387 ****************************************************************************/
388 void generateEnumDefinition(FILE * fp, type_descriptor * type){
389 int pos;
390
391 if(type->already_printed) return;
392
393 fprintf(fp,"enum {\n");
394 for(pos = 0; pos < type->labels.position; pos++){
395 fprintf(fp,"\tLTT_ENUM_%s", type->labels.array[pos]);
396 if (pos != type->labels.position - 1) fprintf(fp,",");
397 if(type->labels_description.array[pos] != NULL)
398 fprintf(fp,"\t/* %s */\n",type->labels_description.array[pos]);
399 else
400 fprintf(fp,"\n");
401 }
402 fprintf(fp,"};\n\n\n");
403
404 type->already_printed = 1;
405 }
406
407 /*****************************************************************************
408 *Function name
409 * generateStrucTFunc: output structure and function to .h file
410 *Input Params
411 * fp : file to be written to
412 * facName : name of facility
413 ****************************************************************************/
414 void generateStructFunc(FILE * fp, char * facName, unsigned long checksum){
415 event * ev;
416 field * fld;
417 type_descriptor * td;
418 int pos, pos1;
419 int hasStrSeq, flag, structCount, seqCount,strCount, whichTypeFirst=0;
420 int args_empty;
421
422 for(pos = 0; pos < fac->events.position; pos++){
423 ev = (event *) fac->events.array[pos];
424 //yxx if(ev->nested)continue;
425 fprintf(fp,"/**** structure and trace function for event: %s ****/\n\n",
426 ev->name);
427 //if(ev->type == 0){ // event without type
428 // fprintf(fp,"static inline void trace_%s_%s(void){\n",facName,ev->name);
429 // fprintf(fp,"\tltt_log_event(ltt_facility_%s_%X, event_%s, 0, NULL);\n",
430 // facName,checksum,ev->name);
431 // fprintf(fp,"};\n\n\n");
432 // continue;
433 //}
434
435 //if fields contain enum, print out enum definition
436 //MD : fixed in generateEnumDefinition to do not print the same enum
437 //twice.
438 if(ev->type != 0)
439 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
440 fld = (field *)ev->type->fields.array[pos1];
441 if(fld->type->type == ENUM) generateEnumDefinition(fp, fld->type);
442 }
443
444 //default: no string, array or sequence in the event
445 hasStrSeq = 0;
446 whichTypeFirst = 0;
447 structCount = 0;
448
449 //structure for kernel
450 if(ev->type != 0)
451 printStruct(fp, ev->type->fields.position, ev->type->fields.array,
452 ev->name, facName, &whichTypeFirst, &hasStrSeq, &structCount,
453 ev->type);
454
455
456 //trace function : function name and parameters : stub function.
457 seqCount = 0;
458 strCount = 0;
459 fprintf(fp, "#ifndef CONFIG_LTT\n");
460 fprintf(fp,"static inline void trace_%s_%s(",facName,ev->name);
461
462 args_empty = 1;
463
464 /* Does it support per trace tracing ? */
465 if(ev->per_trace) {
466 fprintf(fp, "struct ltt_trace_struct *dest_trace");
467 args_empty = 0;
468 }
469
470 /* Does it support per tracefile tracing ? */
471 if(ev->per_tracefile) {
472 if(!args_empty) fprintf(fp, ", ");
473 fprintf(fp, "unsigned int tracefile_index");
474 args_empty = 0;
475 }
476
477 if(ev->type != 0) {
478 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
479 fld = (field *)ev->type->fields.array[pos1];
480 td = fld->type;
481 if(!args_empty) fprintf(fp, ", ");
482 if(td->type == ARRAY ){
483 fprintf(fp,"%s * %s",getTypeStr(td), fld->name);
484 args_empty = 0;
485 }else if(td->type == STRING){
486 fprintf(fp,"short int strlength_%d, %s * %s",
487 ++strCount, getTypeStr(td), fld->name);
488 args_empty = 0;
489 }else if(td->type == SEQUENCE){
490 fprintf(fp,"%s seqlength_%d, %s * %s",
491 uintOutputTypes[td->size], ++seqCount,getTypeStr(td), fld->name);
492 args_empty = 0;
493 }else {
494 fprintf(fp,"%s %s",getTypeStr(td), fld->name);
495 args_empty = 0;
496 }
497 }
498 }
499 if(args_empty) fprintf(fp, "void");
500
501 fprintf(fp,")\n{\n");
502 fprintf(fp,"}\n");
503 fprintf(fp,"#else\n");
504
505 //trace function : function name and parameters
506 seqCount = 0;
507 strCount = 0;
508 fprintf(fp,"static inline void trace_%s_%s(",facName,ev->name);
509
510 args_empty = 1;
511
512 /* Does it support per trace tracing ? */
513 if(ev->per_trace) {
514 fprintf(fp, "struct ltt_trace_struct *dest_trace");
515 args_empty = 0;
516 }
517
518 /* Does it support per tracefile tracing ? */
519 if(ev->per_tracefile) {
520 if(!args_empty) fprintf(fp, ", ");
521 fprintf(fp, "unsigned int tracefile_index");
522 args_empty = 0;
523 }
524
525 if(ev->type != 0) {
526 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
527 fld = (field *)ev->type->fields.array[pos1];
528 td = fld->type;
529 if(!args_empty) fprintf(fp, ", ");
530 if(td->type == ARRAY ){
531 fprintf(fp,"%s * %s",getTypeStr(td), fld->name);
532 args_empty = 0;
533 }else if(td->type == STRING){
534 fprintf(fp,"short int strlength_%d, %s * %s",
535 ++strCount, getTypeStr(td), fld->name);
536 args_empty = 0;
537 }else if(td->type == SEQUENCE){
538 fprintf(fp,"%s seqlength_%d, %s * %s",
539 uintOutputTypes[td->size], ++seqCount,getTypeStr(td), fld->name);
540 args_empty = 0;
541 }else {
542 fprintf(fp,"%s %s",getTypeStr(td), fld->name);
543 args_empty = 0;
544 }
545 }
546 }
547 if(args_empty) fprintf(fp, "void");
548
549 fprintf(fp,")\n{\n");
550
551 //allocate buffer
552 // MD no more need. fprintf(fp,"\tchar buff[buflength];\n");
553 // write directly to the channel
554 fprintf(fp, "\tunsigned int index;\n");
555 fprintf(fp, "\tstruct ltt_channel_struct *channel;\n");
556 fprintf(fp, "\tstruct ltt_trace_struct *trace;\n");
557 fprintf(fp, "\tunsigned long _flags;\n");
558 fprintf(fp, "\tvoid *buff;\n");
559 fprintf(fp, "\tunsigned old_offset;\n");
560 fprintf(fp, "\tunsigned int header_length;\n");
561 fprintf(fp, "\tunsigned int event_length;\n"); // total size (incl hdr)
562 fprintf(fp, "\tunsigned int length;\n"); // Size of the event var data.
563 fprintf(fp, "\tunsigned char _offset;\n");
564 fprintf(fp, "\tstruct rchan_buf *buf;\n");
565 fprintf(fp, "\tstruct timeval delta;\n");
566 fprintf(fp, "\tu64 tsc;\n");
567 fprintf(fp, "\tchar *ptr;\n");
568
569 if(ev->type != 0)
570 fprintf(fp, "\tstruct %s_%s_1* __1;\n\n", ev->name, facName);
571
572 /* Warning : this is done prior to taking locks :
573 * setting this value must be done at the end of the trace activation.
574 * (we don't care for trace removal, as the list of traces is protected : it
575 * just won't iterate on any trace). */
576 fprintf(fp,
577 "\tif(ltt_traces.num_active_traces == 0) return;\n\n");
578
579 fprintf(fp, "\t/* Disable interrupts. */\n");
580 fprintf(fp, "\tlocal_irq_save(_flags);\n");
581 fprintf(fp, "\tpreempt_disable();\n\n");
582
583 fprintf(fp, "\tltt_nesting[smp_processor_id()]++;\n");
584 fprintf(fp, "\tbarrier();\n");
585 fprintf(fp, "\tif(ltt_nesting[smp_processor_id()] > 1) goto unlock;\n");
586 fprintf(fp, "\tspin_lock(&ltt_traces.locks[smp_processor_id()]);\n\n");
587
588 if(ev->per_tracefile) {
589 fprintf(fp, "\tindex = tracefile_index;\n");
590 } else {
591 fprintf(fp,
592 "\tindex = ltt_get_index_from_facility(ltt_facility_%s_%X,\n"\
593 "\t\t\t\tevent_%s);\n",
594 facName, checksum, ev->name);
595 }
596 fprintf(fp,"\n");
597
598 /* For each trace */
599 fprintf(fp, "\tlist_for_each_entry(trace, &ltt_traces.head, list) {\n");
600 fprintf(fp, "\t\tif(!trace->active) continue;\n\n");
601
602 if(ev->per_trace) {
603 fprintf(fp, "\t\tif(dest_trace != trace) continue;\n\n");
604 }
605 //length of buffer : length of all structures
606 // if(ev->type == 0) fprintf(fp, "0");
607
608 fprintf(fp, "\t\tchannel = ltt_get_channel_from_index(trace, index);\n");
609 fprintf(fp, "\t\tbuf = channel->rchan->buf[smp_processor_id()];\n");
610 fprintf(fp, "\n");
611 /* Warning : not atomic reservation : event size depends on the current
612 * address for alignment */
613 /* NOTE : using cmpxchg in reserve with repeat for atomicity */
614 // Replaces _offset
615 /* NOTE2 : as the read old address from memory must come before any
616 * protected event, let's add a memory barrier() to make sure the compiler
617 * will not reorder this read. */
618 fprintf(fp, "\t\tdo {\n");
619 fprintf(fp, "\t\t\told_offset = buf->offset;\n");
620 fprintf(fp, "\t\t\tbarrier();\n");
621 fprintf(fp, "\t\t\tptr = (char*)buf->data + old_offset;\n");
622
623
624 fprintf(fp, "\t\t\theader_length = ltt_get_event_header_data(trace, "
625 "channel,\n"
626 "\t\t\t\t\t\t\t\t\t\tptr, &_offset, &delta, &tsc);\n");
627
628 fprintf(fp, "\t\t\tptr += _offset + header_length;\n");
629
630 for(pos1=0;pos1<structCount;pos1++){
631
632 unsigned align = max(alignment, ev->type->alignment);
633 if(align > 1) {
634 fprintf(fp,"\t\t\tptr += (%u - ((unsigned int)ptr&(%u-1)))&(%u-1) ;\n",
635 align, align, align);
636 }
637 fprintf(fp,"\t\t\tptr += sizeof(struct %s_%s_%d);\n",ev->name,
638 facName,pos1+1);
639 // if(pos1 != structCount-1) fprintf(fp," + ");
640 }
641
642 //length of buffer : length of all arrays, sequences and strings
643 seqCount = 0;
644 strCount = 0;
645 flag = 0;
646 if(ev->type != 0)
647 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
648 fld = (field *)ev->type->fields.array[pos1];
649 td = fld->type;
650 if(td->type == SEQUENCE || td->type==STRING || td->type==ARRAY){
651 if(td->type == SEQUENCE) {
652
653 unsigned align = max(alignment, td->alignment);
654 if(align > 1) {
655 fprintf(fp,"\t\tptr+=(%u - ((unsigned int)ptr&(%u-1)))&(%u-1);\n",
656 align, align, align);
657 }
658 fprintf(fp,"\t\tptr += sizeof(%s);\n",uintOutputTypes[td->size]);
659 if(align > 1) {
660 fprintf(fp,"\t\tptr+=(%u - ((unsigned int)ptr&(%u-1)))&(%u-1);\n",
661 align, align, align);
662 }
663 fprintf(fp,"\t\tptr += sizeof(%s) * seqlength_%d;\n\n",
664 getTypeStr(td), seqCount);
665
666 } else if(td->type==STRING) {
667 unsigned align = max(alignment, td->alignment);
668 if(align > 1) {
669 fprintf(fp,"\t\t\tptr += (%u - ((unsigned int)ptr&(%u-1)))&(%u-1)) ;\n",
670 align, align, align);
671 }
672 fprintf(fp,"ptr += strlength_%d + 1;\n",
673 ++strCount);
674 }
675 else if(td->type==ARRAY) {
676 unsigned align = max(alignment, td->alignment);
677 if(align > 1) {
678 fprintf(fp,"\t\t\tptr += (%u - ((unsigned int)ptr&(%u-1)))&(%u-1);\n",
679 align, align, align);
680 }
681 fprintf(fp,"\t\t\tptr += sizeof(%s) * %d;\n",
682 getTypeStr(td),td->size);
683 if(structCount == 0) flag = 1;
684 }
685 }
686 }
687 fprintf(fp, "\t\t\tevent_length = (unsigned long)ptr -"
688 "(unsigned long)(buf->data + old_offset);\n");
689
690 /* let's put some protection before the cmpxchg : the space reservation and
691 * the get TSC are not dependant from each other. I don't want the compiler
692 * to reorder those in the wrong order. And relay_reserve is inline, so
693 * _yes_, the compiler could mess it up. */
694 fprintf(fp, "\t\t\tbarrier();\n");
695 fprintf(fp, "\t\t\tbuff = relay_reserve(channel->rchan, event_length, "
696 "old_offset);\n");
697 fprintf(fp, "\n");
698 fprintf(fp, "\t\t} while(PTR_ERR(buff) == -EAGAIN);\n");
699 fprintf(fp, "\n");
700
701
702 /* Reserve the channel */
703 //fprintf(fp, "\t\tbuff = relay_reserve(channel->rchan, event_length);\n");
704 fprintf(fp, "\t\tif(buff == NULL) {\n");
705 fprintf(fp, "\t\t\t/* Buffer is full*/\n");
706 fprintf(fp, "\t\t\t/* for debug BUG(); */\n"); // DEBUG!
707 fprintf(fp, "\t\t\tchannel->events_lost[smp_processor_id()]++;\n");
708 fprintf(fp, "\t\t\tbreak;\n"); /* don't commit a NULL reservation! */
709 fprintf(fp, "\t\t}\n");
710
711 /* DEBUG */
712 //fprintf(fp, "\t\tif(resret == 1) {\n");
713 //fprintf(fp, "printk(\"f%%lu e\%%u \", ltt_facility_%s_%X, event_%s);",
714 // facName, checksum, ev->name);
715 //fprintf(fp, "\t\t}\n");
716
717 /* Write the header */
718 fprintf(fp, "\n");
719 fprintf(fp,"\t\tlength = event_length - _offset - header_length;\n");
720 fprintf(fp, "\n");
721 fprintf(fp, "\t\tltt_write_event_header(trace, channel, buff, \n"
722 "\t\t\t\tltt_facility_%s_%X, event_%s, length, _offset,\n"
723 "\t\t\t\t&delta, &tsc);\n",
724 facName, checksum, ev->name);
725 fprintf(fp, "\n");
726
727 if(ev->type != 0)
728 fprintf(fp, "\t\tptr = (char*)buff + _offset + header_length;\n");
729
730 //copy struct, sequence and string to buffer
731 //FIXME : they always come before the structs.
732 seqCount = 0;
733 strCount = 0;
734 flag = 0;
735 structCount = 0;
736 if(ev->type != 0)
737 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
738 fld = (field *)ev->type->fields.array[pos1];
739 td = fld->type;
740 // if(td->type != STRING && td->type != SEQUENCE && td->type != ARRAY){
741 // if(flag == 0) structCount++;
742 // flag++;
743 // if((structCount > 1 || whichTypeFirst == 2) && flag == 1){
744 // assert(0); // MD : disabled !
745 // fprintf(fp,"\t//copy struct to buffer\n");
746 // fprintf(fp,"\tmemcpy(ptr, &__%d, sizeof(struct %s_%s_%d));\n",
747 // structCount, ev->name, facName,structCount);
748 // fprintf(fp,"\tptr += sizeof(struct %s_%s_%d);\n\n",
749 // ev->name, facName,structCount);
750 // }
751 // }
752 //else if(td->type == SEQUENCE){
753 if(td->type == SEQUENCE){
754 flag = 0;
755 fprintf(fp,"\t\t//copy sequence length and sequence to buffer\n");
756
757 unsigned align = max(alignment, td->alignment);
758 if(align > 1) {
759 fprintf(fp,"\t\tptr+=(%u - ((unsigned int)ptr&(%u-1)))&(%u-1);\n",
760 align, align, align);
761 }
762 fprintf(fp,"\t\t*ptr = seqlength_%d;\n",++seqCount);
763 fprintf(fp,"\t\tptr += sizeof(%s);\n",uintOutputTypes[td->size]);
764 if(align > 1) {
765 fprintf(fp,"\t\tptr+=(%u - ((unsigned int)ptr&(%u-1)))&(%u-1);\n",
766 align, align, align);
767 }
768 fprintf(fp,"\t\tmemcpy(ptr, %s, sizeof(%s) * seqlength_%d);\n",
769 fld->name, getTypeStr(td), seqCount);
770 fprintf(fp,"\t\tptr += sizeof(%s) * seqlength_%d;\n\n",
771 getTypeStr(td), seqCount);
772 }
773 else if(td->type==STRING){
774 flag = 0;
775 fprintf(fp,"\t\t//copy string to buffer\n");
776 fprintf(fp,"\t\tif(strlength_%d > 0){\n",++strCount);
777 unsigned align = max(alignment, td->alignment);
778 if(align > 1) {
779 fprintf(fp,"\t\tptr+=(%u - ((unsigned int)ptr&(%u-1)))&(%u-1);\n",
780 align, align, align);
781 }
782 fprintf(fp,"\t\t\tmemcpy(ptr, %s, strlength_%d + 1);\n",
783 fld->name, strCount);
784 fprintf(fp,"\t\t\tptr += strlength_%d + 1;\n",strCount);
785 fprintf(fp,"\t\t}else{\n");
786 fprintf(fp,"\t\t\t*ptr = '\\0';\n");
787 fprintf(fp,"\t\t\tptr += 1;\n");
788 fprintf(fp,"\t\t}\n\n");
789 }else if(td->type==ARRAY){
790 flag = 0;
791 fprintf(fp,"\t//copy array to buffer\n");
792 unsigned align = max(alignment, td->alignment);
793 if(align > 1) {
794 fprintf(fp,"\t\tptr+=(%u - ((unsigned int)ptr&(%u-1)))&(%u-1);\n",
795 align, align, align);
796 }
797 fprintf(fp,"\tmemcpy(ptr, %s, sizeof(%s) * %d);\n",
798 fld->name, getTypeStr(td), td->size);
799 fprintf(fp,"\tptr += sizeof(%s) * %d;\n\n", getTypeStr(td), td->size);
800 }
801 }
802 if(structCount + seqCount > 1) fprintf(fp,"\n");
803
804
805
806
807 //declare a char pointer if needed : starts at the end of the structs.
808 //if(structCount + hasStrSeq > 1) {
809 // fprintf(fp,"\t\tchar * ptr = (char*)buff + header_length");
810 // for(pos1=0;pos1<structCount;pos1++){
811 // fprintf(fp," + sizeof(struct %s_%s_%d)",ev->name, facName,pos1+1);
812 // }
813 // if(structCount + hasStrSeq > 1) fprintf(fp,";\n");
814 //}
815
816 // Declare an alias pointer of the struct type to the beginning
817 // of the reserved area, just after the event header.
818 if(ev->type != 0) {
819 unsigned align = max(alignment, td->alignment);
820 if(align > 1) {
821 fprintf(fp,"\t\tptr+=(%u - ((unsigned int)ptr&(%u-1)))&(%u-1);\n",
822 align, align, align);
823 }
824
825 fprintf(fp, "\t\t__1 = (struct %s_%s_1 *)(ptr);\n",
826 ev->name, facName);
827 }
828 //allocate memory for new struct and initialize it
829 //if(whichTypeFirst == 1){ //struct first
830 //for(pos1=0;pos1<structCount;pos1++){
831 // if(pos1==0) fprintf(fp,
832 // "\tstruct %s_%s_1 * __1 = (struct %s_%s_1 *)buff;\n",
833 // ev->name, facName,ev->name, facName);
834 //MD disabled else fprintf(fp,
835 // "\tstruct %s_%s_%d __%d;\n",
836 // ev->name, facName,pos1+1,pos1+1);
837 //}
838 //}else if(whichTypeFirst == 2){
839 // for(pos1=0;pos1<structCount;pos1++)
840 // fprintf(fp,"\tstruct %s_%s_%d __%d;\n",
841 // ev->name, facName,pos1+1,pos1+1);
842 //}
843 fprintf(fp,"\n");
844
845 if(structCount) fprintf(fp,"\t\t//initialize structs\n");
846 //flag = 0;
847 //structCount = 0;
848 if(ev->type != 0)
849 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
850 fld = (field *)ev->type->fields.array[pos1];
851 td = fld->type;
852 if(td->type != ARRAY && td->type != SEQUENCE && td->type != STRING){
853 //if(flag == 0){
854 // flag = 1;
855 // structCount++;
856 // if(structCount > 1) fprintf(fp,"\n");
857 //}
858 fprintf(fp, "\t\t__1->%s = %s;\n", fld->name, fld->name );
859
860 //if(structCount == 1 && whichTypeFirst == 1)
861 // fprintf(fp, "\t__1->%s = %s;\n",fld->name,fld->name );
862 //else
863 // fprintf(fp, "\t__%d.%s = %s;\n",structCount ,fld->name,fld->name);
864 }
865 //else flag = 0;
866 }
867 if(structCount) fprintf(fp,"\n");
868 //set ptr to the end of first struct if needed;
869 //if(structCount + hasStrSeq > 1){
870 // fprintf(fp,"\n\t\t//set ptr to the end of the first struct\n");
871 // fprintf(fp,"\t\tptr += sizeof(struct %s_%s_1);\n\n",ev->name, facName);
872 //}
873
874 fprintf(fp,"\n");
875 fprintf(fp, "\t\t/* Commit the work */\n");
876 fprintf(fp, "\t\trelay_commit(channel->rchan->buf[smp_processor_id()],\n"
877 "\t\t\t\tbuff, event_length);\n");
878 fprintf(fp, "\t\tltt_write_commit_counter("
879 "channel->rchan->buf[smp_processor_id()],\n"
880 "\t\t\t\tbuff);\n");
881
882 /* End of traces iteration */
883 fprintf(fp, "\t}\n\n");
884
885 fprintf(fp, "\n");
886 // The generated preempt_check_resched is not dangerous because
887 // interrupts are disabled.
888 fprintf(fp, "\tspin_unlock(&ltt_traces.locks[smp_processor_id()]);\n");
889
890 fprintf(fp, "unlock:\n");
891 fprintf(fp, "\tbarrier();\n");
892 fprintf(fp, "\tltt_nesting[smp_processor_id()]--;\n");
893 fprintf(fp, "\t/* Re-enable interrupts */\n");
894 fprintf(fp, "\tlocal_irq_restore(_flags);\n");
895 fprintf(fp, "\tpreempt_enable_no_resched();\n");
896 //fprintf(fp, "\tpreempt_check_resched();\n");
897
898 //call trace function
899 //fprintf(fp,"\n\t//call trace function\n");
900 //fprintf(fp,"\tltt_log_event(ltt_facility_%s_%X, %s, bufLength, buff);\n",facName,checksum,ev->name);
901 fprintf(fp,"}\n");
902 fprintf(fp, "#endif //CONFIG_LTT\n\n");
903 }
904
905 }
906
907 /*****************************************************************************
908 *Function name
909 * getTypeStr : generate type string
910 *Input Params
911 * td : a type descriptor
912 *Return Values
913 * char * : type string
914 ****************************************************************************/
915 char * getTypeStr(type_descriptor * td){
916 type_descriptor * t ;
917
918 switch(td->type){
919 case INT:
920 return intOutputTypes[td->size];
921 case UINT:
922 return uintOutputTypes[td->size];
923 case POINTER:
924 return "void *";
925 case LONG:
926 return "long";
927 case ULONG:
928 return "unsigned long";
929 case SIZE_T:
930 return "size_t";
931 case SSIZE_T:
932 return "ssize_t";
933 case OFF_T:
934 return "off_t";
935 case FLOAT:
936 return floatOutputTypes[td->size];
937 case STRING:
938 return "const char";
939 case ENUM:
940 return uintOutputTypes[td->size];
941 case ARRAY:
942 case SEQUENCE:
943 t = td->nested_type;
944 switch(t->type){
945 case INT:
946 return intOutputTypes[t->size];
947 case UINT:
948 return uintOutputTypes[t->size];
949 case POINTER:
950 return "void *";
951 case LONG:
952 return "long";
953 case ULONG:
954 return "unsigned long";
955 case SIZE_T:
956 return "size_t";
957 case SSIZE_T:
958 return "ssize_t";
959 case OFF_T:
960 return "off_t";
961 case FLOAT:
962 return floatOutputTypes[t->size];
963 case STRING:
964 return "const char";
965 case ENUM:
966 return uintOutputTypes[t->size];
967 default :
968 error_callback(NULL,"Nested struct is not supportted");
969 break;
970 }
971 break;
972 case STRUCT: //for now we do not support nested struct
973 error_callback(NULL,"Nested struct is not supportted");
974 break;
975 default:
976 error_callback(NULL,"No type information");
977 break;
978 }
979 return NULL;
980 }
981
982 /*****************************************************************************
983 *Function name
984 * generateLoaderfile: generate a facility loaded .h file
985 *Input Params
986 * fp : file to be written to
987 * facName : name of facility
988 * nbEvent : number of events in the facility
989 * checksum : checksum for the facility
990 ****************************************************************************/
991 void generateLoaderfile(FILE * fp, char * facName, int nbEvent, unsigned long checksum, char *capname){
992 fprintf(fp, "#ifndef _LTT_FACILITY_LOADER_%s_H_\n",capname);
993 fprintf(fp, "#define _LTT_FACILITY_LOADER_%s_H_\n\n",capname);
994 fprintf(fp,"#include <linux/ltt-facilities.h>\n", facName, checksum);
995 fprintf(fp,"ltt_facility_t\tltt_facility_%s;\n", facName, checksum);
996 fprintf(fp,"ltt_facility_t\tltt_facility_%s_%X;\n\n", facName, checksum);
997
998 fprintf(fp,"#define LTT_FACILITY_SYMBOL\t\t\t\t\t\t\tltt_facility_%s\n",
999 facName);
1000 fprintf(fp,"#define LTT_FACILITY_CHECKSUM_SYMBOL\t\tltt_facility_%s_%X\n",
1001 facName, checksum);
1002 fprintf(fp,"#define LTT_FACILITY_CHECKSUM\t\t\t\t\t\t0x%X\n", checksum);
1003 fprintf(fp,"#define LTT_FACILITY_NAME\t\t\t\t\t\t\t\t\"%s\"\n", facName);
1004 fprintf(fp,"#define LTT_FACILITY_NUM_EVENTS\t\t\t\t\t%d\n\n", nbEvent);
1005 fprintf(fp, "#endif //_LTT_FACILITY_LOADER_%s_H_\n",capname);
1006 }
1007
1008 void generateCfile(FILE * fp, char * filefacname){
1009
1010 fprintf(fp, "/*\n");
1011 fprintf(fp, " * ltt-facility-loader-%s.c\n", filefacname);
1012 fprintf(fp, " *\n");
1013 fprintf(fp, " * (C) Copyright 2005 - \n");
1014 fprintf(fp, " * Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca)\n");
1015 fprintf(fp, " *\n");
1016 fprintf(fp, " * Contains the LTT facility loader.\n");
1017 fprintf(fp, " *\n");
1018 fprintf(fp, " */\n");
1019 fprintf(fp, "\n");
1020 fprintf(fp, "\n");
1021 fprintf(fp, "#include <linux/ltt-facilities.h>\n");
1022 fprintf(fp, "#include <linux/module.h>\n");
1023 fprintf(fp, "#include <linux/init.h>\n");
1024 fprintf(fp, "#include <linux/config.h>\n");
1025 fprintf(fp, "#include \"ltt-facility-loader-%s.h\"\n", filefacname);
1026 fprintf(fp, "\n");
1027 fprintf(fp, "\n");
1028 fprintf(fp, "#ifdef CONFIG_LTT\n");
1029 fprintf(fp, "\n");
1030 fprintf(fp, "EXPORT_SYMBOL(LTT_FACILITY_SYMBOL);\n");
1031 fprintf(fp, "EXPORT_SYMBOL(LTT_FACILITY_CHECKSUM_SYMBOL);\n");
1032 fprintf(fp, "\n");
1033 fprintf(fp, "static const char ltt_facility_name[] = LTT_FACILITY_NAME;\n");
1034 fprintf(fp, "\n");
1035 fprintf(fp, "#define SYMBOL_STRING(sym) #sym\n");
1036 fprintf(fp, "\n");
1037 fprintf(fp, "static struct ltt_facility facility = {\n");
1038 fprintf(fp, "\t.name = ltt_facility_name,\n");
1039 fprintf(fp, "\t.num_events = LTT_FACILITY_NUM_EVENTS,\n");
1040 fprintf(fp, "\t.checksum = LTT_FACILITY_CHECKSUM,\n");
1041 fprintf(fp, "\t.symbol = SYMBOL_STRING(LTT_FACILITY_SYMBOL),\n");
1042 fprintf(fp, "\t.alignment = %u\n", alignment); /* default alignment */
1043 fprintf(fp, "};\n");
1044 fprintf(fp, "\n");
1045 fprintf(fp, "#ifndef MODULE\n");
1046 fprintf(fp, "\n");
1047 fprintf(fp, "/* Built-in facility. */\n");
1048 fprintf(fp, "\n");
1049 fprintf(fp, "static int __init facility_init(void)\n");
1050 fprintf(fp, "{\n");
1051 fprintf(fp, "\tprintk(KERN_INFO \"LTT : ltt-facility-%s init in kernel\\n\");\n", filefacname);
1052 fprintf(fp, "\n");
1053 fprintf(fp, "\tLTT_FACILITY_SYMBOL = ltt_facility_builtin_register(&facility);\n");
1054 fprintf(fp, "\tLTT_FACILITY_CHECKSUM_SYMBOL = LTT_FACILITY_SYMBOL;\n");
1055 fprintf(fp, "\t\n");
1056 fprintf(fp, "\treturn LTT_FACILITY_SYMBOL;\n");
1057 fprintf(fp, "}\n");
1058 fprintf(fp, "__initcall(facility_init);\n");
1059 fprintf(fp, "\n");
1060 fprintf(fp, "\n");
1061 fprintf(fp, "\n");
1062 fprintf(fp, "#else \n");
1063 fprintf(fp, "\n");
1064 fprintf(fp, "/* Dynamic facility. */\n");
1065 fprintf(fp, "\n");
1066 fprintf(fp, "static int __init facility_init(void)\n");
1067 fprintf(fp, "{\n");
1068 fprintf(fp, "\tprintk(KERN_INFO \"LTT : ltt-facility-%s init dynamic\\n\");\n", filefacname);
1069 fprintf(fp, "\n");
1070 fprintf(fp, "\tLTT_FACILITY_SYMBOL = ltt_facility_dynamic_register(&facility);\n");
1071 fprintf(fp, "\tLTT_FACILITY_SYMBOL_CHECKSUM = LTT_FACILITY_SYMBOL;\n");
1072 fprintf(fp, "\n");
1073 fprintf(fp, "\treturn LTT_FACILITY_SYMBOL;\n");
1074 fprintf(fp, "}\n");
1075 fprintf(fp, "\n");
1076 fprintf(fp, "static void __exit facility_exit(void)\n");
1077 fprintf(fp, "{\n");
1078 fprintf(fp, "\tint err;\n");
1079 fprintf(fp, "\n");
1080 fprintf(fp, "\terr = ltt_facility_dynamic_unregister(LTT_FACILITY_SYMBOL);\n");
1081 fprintf(fp, "\tif(err != 0)\n");
1082 fprintf(fp, "\t\tprintk(KERN_ERR \"LTT : Error in unregistering facility.\\n\");\n");
1083 fprintf(fp, "\n");
1084 fprintf(fp, "}\n");
1085 fprintf(fp, "\n");
1086 fprintf(fp, "module_init(facility_init)\n");
1087 fprintf(fp, "module_exit(facility_exit)\n");
1088 fprintf(fp, "\n");
1089 fprintf(fp, "\n");
1090 fprintf(fp, "MODULE_LICENSE(\"GPL\");\n");
1091 fprintf(fp, "MODULE_AUTHOR(\"Mathieu Desnoyers\");\n");
1092 fprintf(fp, "MODULE_DESCRIPTION(\"Linux Trace Toolkit Facility\");\n");
1093 fprintf(fp, "\n");
1094 fprintf(fp, "#endif //MODULE\n");
1095 fprintf(fp, "\n");
1096 fprintf(fp, "#endif //CONFIG_LTT\n");
1097 }
1098
1099
This page took 0.070062 seconds and 4 git commands to generate.