source: proto/parabix2/pablo_template_multithreads.cpp @ 2211

Last change on this file since 2211 was 2142, checked in by ksherdy, 7 years ago

Added general description to multithreads template.

File size: 17.8 KB
Line 
1/*
2
3* OVERALL
4
5Coarse grained software pipeline implementation
6of xmlwf application using the pthreads library.
7
8xmlwf template logic manually partitioned into four hard coded stages. A stage
9implements a portion of the logic of the xmlwf application logic. A stage is broken
10into a number of segment size passes. A pass executes a number of blocks. 
11Passes are manually balanced and execute under separate threads.
12
13Circular queue implementation. Each queue entry contains a 'SEGMENT' of
14parallel data 'stream' structs. The source buffer is a member of the set of
15parallel data structs. Circular queue implemented as hard coded circular
16queue of size 8.
17
18* SYNCHRONIZATION
19
20A pass can progress up to the minimum of tail of the (8 segment) circular queue
21or the prior segment of the previous stage.
22
23BUFFER MANAGMENT / FILE MANAGEMENT
24
25Two buffers: Overlap buffer, Source buffer.
26
27Source Buffer Size: BLOCK_SIZE * (SEGMENT_BLOCKS+1) + OVERLAP_BUFSIZE*2
28
29Source Buffer Layout per Circular Queue Entry:
30
31| OVERLAP_BUFSIZE (16 bytes) | OVERLAP_BUFSIZE (16 bytes) | (BLOCK_SIZE * (SEGMENT_BLOCKS+1)) |
32^                            ^
33|                            |
34srcbuf                       srcptr 
35
36Overlap Buffer Layout:
37
38| OVERLAP_BUFSIZE * 2 (32 bytes)                          |
39
40
41* PROCESSING MODEL
42
43Slurps complete XML file.
44
45Counts the number of complete file segments.
46
47Creates thread for each stage.
48
49Threads process multiple segments as passes of a stage.
50
51*/
52
53
54#include <stdio.h>
55#include <stdlib.h>
56#include <errno.h>
57#include <sys/types.h>
58#include <sys/stat.h>
59#include <pthread.h>
60#include "../lib/lib_simd.h"
61#define BLOCK_SIZE 128
62#define SEGMENT_BLOCKS 128
63#define SEGMENT_SIZE (BLOCK_SIZE * SEGMENT_BLOCKS)
64#define OVERLAP_BUFSIZE 16
65
66#include "../lib/builtins.hpp"
67#include "../lib/carryQ.h"
68#include "xmldecl.h"
69#include "xml_error.c"
70#include "xmldecl.c"
71#include "namechars.h"
72
73#include "../lib/perflib/perfsec.h"
74#include "../lib/s2p.h"
75
76#include "TagMatcher_multithreads.h"
77#include "LineColTracker_multithreads.h"
78BitBlock EOF_mask = simd_const_1(1);
79
80#ifdef BUFFER_PROFILING
81        BOM_Table * parser_timer;
82#ifdef ANALYZE
83        BOM_Table * T1_total_timer;
84        BOM_Table * T2_total_timer;
85        BOM_Table * T3_total_timer;
86        BOM_Table * T4_total_timer;
87        BOM_Table * T1_work_timer;
88        BOM_Table * T2_work_timer;
89        BOM_Table * T3_work_timer;
90        BOM_Table * T4_work_timer;     
91#endif
92#endif
93LineColTracker tracker;
94TagMatcher matcher;
95
96int block_base=0;
97int buffer_base=0;
98char * source;
99
100static inline int StreamScan(ScanBlock * stream, int blk_count, int ProcessPos(int)) {
101        int blk;
102        int block_pos = 0;
103
104        for (blk = 0; blk < blk_count; blk++) {
105                scanword_t s = stream[blk];
106                while(s) {
107                        int code = (ProcessPos(scan_forward_zeroes(s) + block_pos));
108                        if (code) return code;
109                        s = s & (s-1);  // clear rightmost bit.
110                }
111                block_pos += 8 * sizeof(ScanBlock);
112        }
113        return 0;
114}
115
116static inline void ReportError(const char * error_msg, int error_pos_in_block) {
117  int error_line, error_column;
118  tracker.get_Line_and_Column(error_pos_in_block, error_line, error_column);
119  fprintf(stderr, "%s at line %i, column %i\n", error_msg, error_line, error_column);
120}
121
122
123static inline int NameStrt_check(int pos) {
124        int block_pos = block_base + pos;
125        if(XML_10_UTF8_NameStrt_bytes((unsigned char*)&source[block_pos]) == 0){
126              ReportError("name start error", pos);
127              exit(-1);
128        }
129        return 0;
130}
131
132static inline int Name_check(int pos) {
133        int block_pos = block_base + pos;
134        if(XML_10_UTF8_NameChar_bytes((unsigned char*)&source[block_pos]) == 0){
135              ReportError("name error", pos);
136              exit(-1);
137        }
138        return 0;
139}
140
141static inline int PIName_check(int pos) {
142        int block_pos = block_base + pos;
143        int file_pos = block_pos+buffer_base;
144        if (at_XxMmLll<ASCII>((unsigned char*)&source[block_pos]) && (source[block_pos+3]=='?' || source[block_pos+3]<= ' ')) {
145              // "<?xml" legal at start of file.
146              if ((file_pos == 2) && at_XmlDecl_start<ASCII>((unsigned char*)&source[0])) return 0;
147              ReportError("[Xx][Mm][Ll] illegal as PI name", pos);
148              exit(-1);
149        }
150        return 0;
151}
152
153static inline int CD_check(int pos) {
154        int block_pos = block_base + pos;
155        if (!at_CDATA1<ASCII>((unsigned char*)&source[block_pos])){
156              ReportError("CDATA error", pos);
157              exit(-1);
158        }
159        return 0;
160}
161
162static inline int GenRef_check(int pos) {
163        int block_pos = block_base + pos;
164        unsigned char* s = (unsigned char*)&source[block_pos];
165        if (!(at_Ref_gt<ASCII>(s)||at_Ref_lt<ASCII>(s)||at_Ref_amp<ASCII>(s)||at_Ref_quot<ASCII>(s)||at_Ref_apos<ASCII>(s))){
166              ReportError("Undefined reference", pos);
167              exit(-1);
168        }
169        return 0;
170}
171
172static inline int HexRef_check(int pos) {
173        int block_pos = block_base + pos;
174        unsigned char* s = (unsigned char*)&source[block_pos];
175        int ch_val = 0;
176        while(at_HexDigit<ASCII>(s)){
177          ch_val = HexVal<ASCII>(s[0]) + (ch_val<<4);
178          if (ch_val> 0x10FFFF ){
179            ReportError("Illegal character reference", pos);
180            exit(-1);
181          }
182          s++;
183        }
184        if ((ch_val == 0x0) || ((ch_val | 0x7FF) == 0xDFFF)|| ((ch_val | 0x1) == 0xFFFF)){
185          ReportError("Illegal character reference", pos);
186          exit(-1);
187        }
188        else if (((ch_val < 0x20) && (ch_val != 0x9) && (ch_val != 0xD) && (ch_val != 0xA))){
189          ReportError("Illegal XML 1.0 character reference", pos);
190          exit(-1);
191        }
192        return 0;
193}
194
195static inline int DecRef_check(int pos) {
196        int block_pos = block_base + pos;
197        unsigned char* s = (unsigned char*)&source[block_pos];
198        int ch_val = 0;
199        while(at_HexDigit<ASCII>(s)){
200          ch_val = DigitVal<ASCII>(s[0]) + ch_val*10;
201          if (ch_val> 0x10FFFF ){
202            ReportError("Illegal character reference", pos);
203            exit(-1);
204          }
205          s++;
206        }
207        if ((ch_val == 0x0) || ((ch_val | 0x7FF) == 0xDFFF)|| ((ch_val | 0x1) == 0xFFFF)){
208          ReportError("Illegal character reference", pos);
209          exit(-1);
210        }
211        else if (((ch_val < 0x20) && (ch_val != 0x9) && (ch_val != 0xD) && (ch_val != 0xA))){
212          ReportError("Illegal XML 1.0 character reference", pos);
213          exit(-1);
214        }
215        return 0;
216}
217
218static inline int AttRef_check(int pos) {
219        int block_pos = block_base + pos;
220        unsigned char* s = (unsigned char*)&source[block_pos];
221        int ch_val = 0;
222        if(s[0]=='#'){
223          s++;
224          if(s[0]=='x' || s[0]=='X'){
225            s++;
226            while(at_HexDigit<ASCII>(s)){
227              ch_val = HexVal<ASCII>(s[0]) + (ch_val<<4);
228              s++;
229            }
230          }
231          else{
232            while(at_HexDigit<ASCII>(s)){
233              ch_val = DigitVal<ASCII>(s[0]) + ch_val*10;
234              s++;
235            }
236          }
237          if (ch_val==60){
238            ReportError("Attribute values contain '<' characters after reference expansion", pos);
239            exit(-1);
240          }
241        }
242        else if(at_Ref_lt<ASCII>(s)){
243          ReportError("Attribute values contain '<' characters after reference expansion", pos);
244          exit(-1);
245        }
246        return 0;
247}
248
249
250
251@global
252
253static inline void s2p_do_block(BytePack U8[], Basis_bits & basis_bits) {
254  s2p(U8[0], U8[1], U8[2], U8[3], U8[4], U8[5], U8[6], U8[7],
255        basis_bits.bit_0, basis_bits.bit_1, basis_bits.bit_2, basis_bits.bit_3, basis_bits.bit_4, basis_bits.bit_5, basis_bits.bit_6, basis_bits.bit_7);
256}
257
258static inline void s2p_do_final_block(BytePack U8[], Basis_bits & basis_bits, BitBlock EOF_mask) {
259  s2p_do_block(U8, basis_bits);
260  basis_bits.bit_0 = simd_and(basis_bits.bit_0, EOF_mask);
261  basis_bits.bit_1 = simd_and(basis_bits.bit_1, EOF_mask);
262  basis_bits.bit_2 = simd_and(basis_bits.bit_2, EOF_mask);
263  basis_bits.bit_3 = simd_and(basis_bits.bit_3, EOF_mask);
264  basis_bits.bit_4 = simd_and(basis_bits.bit_4, EOF_mask);
265  basis_bits.bit_5 = simd_and(basis_bits.bit_5, EOF_mask);
266  basis_bits.bit_6 = simd_and(basis_bits.bit_6, EOF_mask);
267  basis_bits.bit_7 = simd_and(basis_bits.bit_7, EOF_mask);
268}
269
270static inline void s2p_do_segment(BytePack U8[], Basis_bits basis_bits[]) {
271  for (int i = 0; i < SEGMENT_BLOCKS; i++)
272           s2p_do_block(&U8[8*i], basis_bits[i]);
273}
274
275static inline void postprocess_do_block(Lex & lex, CtCDPI_Callouts & ctCDPI_Callouts, Ref_Callouts & ref_Callouts, Check_streams & check_streams, int chars_avail){
276            tracker.StoreNewlines(lex.LF);
277
278                if (bitblock_has_bit(simd_or(check_streams.non_ascii_name_starts, check_streams.non_ascii_names))) {
279                  StreamScan((ScanBlock *) &check_streams.non_ascii_name_starts, sizeof(BitBlock)/sizeof(ScanBlock), NameStrt_check);
280                  StreamScan((ScanBlock *) &check_streams.non_ascii_names, sizeof(BitBlock)/sizeof(ScanBlock), Name_check);
281                }
282
283                if (bitblock_has_bit(ctCDPI_Callouts.PI_name_starts)){
284                  StreamScan((ScanBlock *) &ctCDPI_Callouts.PI_name_starts, sizeof(BitBlock)/sizeof(ScanBlock), PIName_check);
285                }
286
287                if (bitblock_has_bit(ctCDPI_Callouts.CD_starts)){
288                  StreamScan((ScanBlock *) &ctCDPI_Callouts.CD_starts, sizeof(BitBlock)/sizeof(ScanBlock), CD_check);
289                }
290
291                if (bitblock_has_bit(ref_Callouts.GenRef_starts)){
292                  StreamScan((ScanBlock *) &ref_Callouts.GenRef_starts, sizeof(BitBlock)/sizeof(ScanBlock), GenRef_check);
293                }
294
295                if (bitblock_has_bit(ref_Callouts.DecRef_starts)){
296                  StreamScan((ScanBlock *) &ref_Callouts.DecRef_starts, sizeof(BitBlock)/sizeof(ScanBlock), DecRef_check);
297                }
298
299                if (bitblock_has_bit(ref_Callouts.HexRef_starts)){
300                  StreamScan((ScanBlock *) &ref_Callouts.HexRef_starts, sizeof(BitBlock)/sizeof(ScanBlock), HexRef_check);
301                }
302
303                if (bitblock_has_bit(check_streams.att_refs)){
304                  StreamScan((ScanBlock *) &check_streams.att_refs, sizeof(BitBlock)/sizeof(ScanBlock), AttRef_check);
305                }
306
307                if (bitblock_has_bit(check_streams.error_mask)) {
308                  int errpos = count_forward_zeroes(check_streams.error_mask);
309                  ReportError("error found", errpos);
310              exit(-1);
311                }
312
313                matcher.store_streams(check_streams.tag_marks, check_streams.name_follows, check_streams.misc_mask, chars_avail);
314                tracker.AdvanceBlock();
315}
316
317static inline void postprocess_do_segment(Lex lex[], CtCDPI_Callouts ctCDPI_Callouts[], Ref_Callouts ref_Callouts[], Check_streams check_streams[]){
318
319  for (int i = 0; i < SEGMENT_BLOCKS; i++){
320           postprocess_do_block(lex[i], ctCDPI_Callouts[i], ref_Callouts[i], check_streams[i], SEGMENT_SIZE);
321           block_base += BLOCK_SIZE;
322  }
323
324        matcher.StreamScan(SEGMENT_SIZE);
325        matcher.Advance_segment();
326        tracker.Advance_buffer();
327}
328
329struct Para_data{
330
331          char srcbuf[BLOCK_SIZE * (SEGMENT_BLOCKS+1) + OVERLAP_BUFSIZE*2];
332
333          struct U8 u8[SEGMENT_BLOCKS];
334
335          struct Lex lex[SEGMENT_BLOCKS];
336
337          struct Scope1 scope1[SEGMENT_BLOCKS];
338
339          struct CtCDPI_Callouts ctCDPI_Callouts[SEGMENT_BLOCKS];
340
341          struct Ref_Callouts ref_Callouts[SEGMENT_BLOCKS];
342
343          struct Tag_Callouts tag_Callouts[SEGMENT_BLOCKS];
344
345          struct Basis_bits basis_bits[SEGMENT_BLOCKS];
346
347          struct Check_streams check_streams[SEGMENT_BLOCKS];
348
349          struct Xml_names xml_names[SEGMENT_BLOCKS];
350};
351
352  Validate_utf8 validate_utf8;
353  Parse_refs parse_refs;
354  Parse_tags parse_tags;
355  Parse_CtCDPI parse_CtCDPI;
356  Do_check_streams do_check_streams;
357  Classify_bytes classify_bytes;
358  Add_scope_streams add_scope_streams;
359  Validate_xml_names validate_xml_names;
360
361
362int file_segs=0;
363FILE *infile;
364FILE *outfile;
365
366template<typename T>
367class spsc_queue
368{
369public:
370  spsc_queue()
371  {
372          head1_ =  head2_ = head3_ = head4_ = 1;
373      tail_ = 0;
374  }
375
376  ~spsc_queue()
377  {
378
379  }
380
381  bool pass1()
382  {
383          while(head1_==tail_)
384          __sync_synchronize();
385
386#ifdef ANALYZE
387PERF_SEC_START(T1_work_timer);
388#endif
389          char * srcptr = n[head1_].srcbuf + OVERLAP_BUFSIZE;
390          memmove(n[head1_].srcbuf, overlap_buffer, 2*overlap_bytes);
391          int chars_read = fread(&srcptr[overlap_bytes], 1, SEGMENT_SIZE + OVERLAP_BUFSIZE - overlap_bytes, infile);
392          memmove(overlap_buffer, &srcptr[SEGMENT_SIZE-OVERLAP_BUFSIZE], 2*OVERLAP_BUFSIZE);
393          overlap_bytes = OVERLAP_BUFSIZE;
394          s2p_do_segment((BytePack *) srcptr, n[head1_].basis_bits);
395          classify_bytes.do_segment(n[head1_].basis_bits, n[head1_].lex);
396
397#ifdef ANALYZE
398PERF_SEC_END(T1_work_timer, SEGMENT_SIZE);
399#endif
400          head1_ = (head1_+1)%8;
401
402  }
403
404  bool pass2()
405  {
406          while(head2_==head1_)
407          __sync_synchronize();
408
409#ifdef ANALYZE
410PERF_SEC_START(T2_work_timer);
411#endif
412          validate_utf8.do_segment(n[head2_].basis_bits, n[head2_].u8);
413          add_scope_streams.do_segment(n[head2_].lex, n[head2_].scope1);
414          parse_CtCDPI.do_segment(n[head2_].ctCDPI_Callouts, n[head2_].lex, n[head2_].scope1, n[head2_].check_streams);
415          parse_refs.do_segment(n[head2_].lex, n[head2_].scope1, n[head2_].ctCDPI_Callouts, n[head2_].ref_Callouts);
416
417#ifdef ANALYZE
418PERF_SEC_END(T2_work_timer, SEGMENT_SIZE);
419#endif
420          head2_ = (head2_+1)%8;
421
422  }
423
424  bool pass3()
425  {
426          while(head3_==head2_)
427          __sync_synchronize();
428
429#ifdef ANALYZE
430PERF_SEC_START(T3_work_timer);
431#endif
432         parse_tags.do_segment(n[head3_].lex, n[head3_].scope1, n[head3_].ctCDPI_Callouts, n[head3_].tag_Callouts);
433         validate_xml_names.do_segment(n[head3_].ctCDPI_Callouts, n[head3_].ref_Callouts, n[head3_].tag_Callouts, n[head3_].lex, n[head3_].u8, n[head3_].xml_names, n[head3_].check_streams);
434                  do_check_streams.do_segment(n[head3_].ctCDPI_Callouts, n[head3_].tag_Callouts, n[head3_].lex, n[head3_].u8, n[head3_].scope1, n[head3_].ref_Callouts, n[head3_].xml_names, n[head3_].check_streams);
435          head3_ = (head3_+1)%8;
436
437#ifdef ANALYZE
438PERF_SEC_END(T3_work_timer, SEGMENT_SIZE);
439#endif
440  }
441
442  bool pass4()
443  {
444          while(head4_==head3_)
445          __sync_synchronize();
446
447#ifdef ANALYZE
448PERF_SEC_START(T4_work_timer);
449#endif
450          source = n[head4_].srcbuf+OVERLAP_BUFSIZE;
451          matcher.setSrc(source);
452          postprocess_do_segment(n[head4_].lex, n[head4_].ctCDPI_Callouts, n[head4_].ref_Callouts, n[head4_].check_streams);
453          block_base = 0;
454
455#ifdef ANALYZE
456PERF_SEC_END(T4_work_timer, SEGMENT_SIZE);
457#endif
458          head4_ = (head4_+1)%8;
459          tail_ = (tail_+1)%8;
460
461  }
462
463  int overlap_bytes;
464
465  char overlap_buffer[2*OVERLAP_BUFSIZE];
466
467
468private:
469
470  int tail_; // tail of the queue
471  int head1_; // head of the queue
472  int head2_;
473  int head3_;
474  int head4_;
475  T  n[8];
476
477
478  spsc_queue(spsc_queue const&);
479  spsc_queue& operator = (spsc_queue const&);
480};
481
482spsc_queue<struct Para_data> q;
483
484void *stageOne(void *threadid)
485{
486   long tid = (long)threadid;
487   for(int i=0;i<file_segs;i++){
488#ifdef ANALYZE
489PERF_SEC_START(T1_total_timer);
490#endif
491           q.pass1();
492//         printf("thread %ld: %i\n",tid,i);
493#ifdef ANALYZE
494PERF_SEC_END(T1_total_timer, SEGMENT_SIZE);
495#endif
496   }
497   pthread_exit(NULL);
498}
499void *stageTwo(void *threadid)
500{
501   long tid = (long)threadid;
502   for(int i=0;i<file_segs;i++){
503#ifdef ANALYZE
504PERF_SEC_START(T2_total_timer);
505#endif
506           q.pass2();
507//         printf("thread %ld: %i\n",tid,i);
508#ifdef ANALYZE
509PERF_SEC_END(T2_total_timer, SEGMENT_SIZE);
510#endif
511   }
512   pthread_exit(NULL);
513}
514
515void *stageThree(void *threadid)
516{
517   long tid = (long)threadid;
518   for(int i=0;i<file_segs;i++){
519#ifdef ANALYZE
520PERF_SEC_START(T3_total_timer);
521#endif
522           q.pass3();
523//         printf("thread %ld: %i\n",tid,i);
524#ifdef ANALYZE
525PERF_SEC_END(T3_total_timer, SEGMENT_SIZE);
526#endif
527   }
528   pthread_exit(NULL);
529}
530void *stageFour(void *threadid)
531{
532   long tid = (long)threadid;
533   for(int i=0;i<file_segs;i++){
534#ifdef ANALYZE
535PERF_SEC_START(T4_total_timer);
536#endif
537           q.pass4();
538//         printf("thread %ld: %i\n",tid,i);
539#ifdef ANALYZE
540PERF_SEC_END(T4_total_timer, SEGMENT_SIZE);
541#endif
542   }
543   pthread_exit(NULL);
544}
545
546#define NUM_THREADS 4
547
548int
549main(int argc, char * argv[]) {
550        char * infilename, * outfilename;
551        FILE *tmpinfile, *tmpoutfile;
552        struct stat fileinfo;
553
554    pthread_t threads[NUM_THREADS];
555    int rc;
556    long t=0;
557    void *status;
558
559        if (argc < 2) {
560                printf("Usage: %s <filename> [<outputfile>]\n", argv[0]);
561                exit(-1);
562        }
563
564        infilename = argv[1];
565        stat(infilename, &fileinfo);
566        file_segs = fileinfo.st_size/SEGMENT_SIZE;
567        infile = fopen(infilename, "rb");
568        if (!infile) {
569                fprintf(stderr, "Error: cannot open %s for input.\n", infilename);
570                exit(-1);
571        }
572
573        if (argc < 3) outfile = stdout;
574        else {
575                outfilename = argv[2];
576                outfile = fopen(outfilename, "wb");
577                if (!outfile) {
578                        fprintf(stderr, "Error: cannot open %s for writing.\n", outfilename);
579                        exit(-1);
580                }
581        }
582
583        PERF_SEC_INIT(parser_timer);
584#ifdef ANALYZE
585        PERF_SEC_INIT(T1_total_timer);
586        PERF_SEC_INIT(T2_total_timer);
587        PERF_SEC_INIT(T3_total_timer);
588        PERF_SEC_INIT(T4_total_timer);
589        PERF_SEC_INIT(T1_work_timer);
590        PERF_SEC_INIT(T2_work_timer);
591        PERF_SEC_INIT(T3_work_timer);
592        PERF_SEC_INIT(T4_work_timer);
593#endif
594
595        PERF_SEC_START(parser_timer);
596
597
598          rc = pthread_create(&threads[t], NULL, stageOne, (void *)t);
599          if (rc){
600                  printf("ERROR; return code from pthread_create() is %d\n", rc);
601                  exit(-1);
602          }
603          t++;
604          rc = pthread_create(&threads[t], NULL, stageTwo, (void *)t);
605          if (rc){
606                  printf("ERROR; return code from pthread_create() is %d\n", rc);
607                  exit(-1);
608          }
609
610          t++;
611          rc = pthread_create(&threads[t], NULL, stageThree, (void *)t);
612          if (rc){
613                  printf("ERROR; return code from pthread_create() is %d\n", rc);
614                  exit(-1);
615          }
616
617          t++;
618          rc = pthread_create(&threads[t], NULL, stageFour, (void *)t);
619          if (rc){
620                  printf("ERROR; return code from pthread_create() is %d\n", rc);
621                  exit(-1);
622          }
623
624          for(t=0; t<NUM_THREADS; t++) {
625             rc = pthread_join(threads[t], &status);
626             if (rc) {
627                printf("ERROR; return code from pthread_join() is %d\n", rc);
628                exit(-1);
629             }
630//           printf("Main: completed join with thread %ld having a status of %ld\n",t,(long)status);
631          }
632
633
634        PERF_SEC_END(parser_timer, fileinfo.st_size/SEGMENT_SIZE*SEGMENT_SIZE);
635
636        PERF_SEC_DUMP(parser_timer);
637#ifdef ANALYZE
638printf("\nT1_total_timer\n");
639        PERF_SEC_DUMP(T1_total_timer);
640printf("\nT2_total_timer\n");
641        PERF_SEC_DUMP(T2_total_timer);
642printf("\nT3_total_timer\n");
643        PERF_SEC_DUMP(T3_total_timer);
644printf("\nT4_total_timer\n");
645        PERF_SEC_DUMP(T4_total_timer);
646printf("\nT1_work_timer\n");
647        PERF_SEC_DUMP(T1_work_timer);
648printf("\nT2_work_timer\n");
649        PERF_SEC_DUMP(T2_work_timer);
650printf("\nT3_work_timer\n");
651        PERF_SEC_DUMP(T3_work_timer);
652printf("\nT4_work_timer\n");
653        PERF_SEC_DUMP(T4_work_timer);
654#endif
655
656        PERF_SEC_DESTROY(parser_timer);
657#ifdef ANALYZE
658        PERF_SEC_DESTROY(T1_total_timer);
659        PERF_SEC_DESTROY(T2_total_timer);
660        PERF_SEC_DESTROY(T3_total_timer);
661        PERF_SEC_DESTROY(T4_total_timer);
662        PERF_SEC_DESTROY(T1_work_timer);
663        PERF_SEC_DESTROY(T2_work_timer);
664        PERF_SEC_DESTROY(T3_work_timer);
665        PERF_SEC_DESTROY(T4_work_timer);
666#endif
667//      printf("count = %i\n", q.count);
668
669        pthread_exit(NULL);
670
671        fclose(infile);
672        fclose(outfile);
673        return(0);
674}
Note: See TracBrowser for help on using the repository browser.