00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 # include <stdio.h>
00030 # include <stdlib.h>
00031 # include <sys/types.h>
00032 # include <fcntl.h>
00033 # include <unistd.h>
00034
00035 #ifndef NeXT
00036 # include <unistd.h>
00037 #endif
00038
00039 # include <string.h>
00040
00041 # define TRACING_ON
00042 # define PCXX_EVENT_SRC
00043
00044 # ifdef __PCXX__
00045 # include "Profile/pcxx_events_def.h"
00046 # else
00047 # include "Profile/pcxx_events.h"
00048 # endif
00049 # include "Profile/pcxx_ansi.h"
00050
00051 # ifndef TRUE
00052 # define FALSE 0
00053 # define TRUE 1
00054 # endif
00055
00056 # define F_EXISTS 0
00057
00058 # define CONTLEN (sizeof(PCXX_EV) - sizeof(long int))
00059
00060 # define STDOUT 1
00061
00062
00063 # define INMAX BUFSIZ
00064 # define OUTMAX BUFSIZ
00065
00066 int dynamic = TRUE ;
00067 extern "C" {
00068 int open_edf_file(char *prefix, int nodeid);
00069 int parse_edf_file(int node);
00070 int store_merged_edffile(char *filename);
00071 int GID(int node, long localEventId);
00072 }
00073
00074
00075 static struct trcdescr
00076 {
00077 int fd;
00078 char *name;
00079 int nid;
00080 int overflows;
00081 int contlen;
00082 long numrec;
00083 unsigned long lasttime;
00084 unsigned long offset;
00085
00086 PCXX_EV *buffer;
00087 PCXX_EV *erec;
00088 PCXX_EV *next;
00089 PCXX_EV *last;
00090 } *trcdes;
00091
00092
00093
00094
00095
00096 static PCXX_EV *get_next_rec(struct trcdescr *tdes)
00097 {
00098 long no;
00099
00100 if ( (tdes->last == NULL) || (tdes->next > tdes->last) )
00101 {
00102
00103 if ( (no = read (tdes->fd, tdes->buffer, INMAX * sizeof(PCXX_EV)))
00104 != (INMAX * sizeof(PCXX_EV)) )
00105 {
00106 if ( no == 0 )
00107 {
00108
00109 close (tdes->fd);
00110 tdes->fd = -1;
00111 return (NULL);
00112 }
00113 else if ( (no % sizeof(PCXX_EV)) != 0 )
00114 {
00115
00116 fprintf (stderr, "%s: read error\n", tdes->name);
00117 exit (1);
00118 }
00119 }
00120
00121
00122 tdes->next = tdes->buffer;
00123 tdes->last = tdes->buffer + (no / sizeof(PCXX_EV)) - 1;
00124 }
00125 return (tdes->erec = tdes->next++);
00126 }
00127
00128
00129
00130
00131
00132 static char outbuffer[OUTMAX];
00133 static int outidx = 0;
00134 static char *outptr = outbuffer;
00135
00136 static void output_flush(int fd)
00137 {
00138 if ( outidx > 0 )
00139 {
00140 if ( write (fd, outbuffer, outidx) != outidx )
00141 {
00142 perror ("write output");
00143 exit (1);
00144 }
00145 outidx = 0;
00146 outptr = outbuffer;
00147 }
00148 }
00149
00150 static void output(int fd, char *data, size_t l)
00151 {
00152 if ( outidx + l >= BUFSIZ )
00153 {
00154
00155 output_flush (fd);
00156 }
00157
00158 memcpy (outptr, data, l);
00159 outptr += l;
00160 outidx += l;
00161 }
00162
00163
00164
00165
00166
00167 #include <sys/time.h>
00168 #include <sys/resource.h>
00169
00170 int cannot_get_enough_fd(int need)
00171 {
00172 # if defined(__hpux) || defined(sun)
00173
00174 struct rlimit rlp;
00175
00176 getrlimit (RLIMIT_NOFILE, &rlp);
00177 if ( rlp.rlim_max < need )
00178 return (TRUE);
00179 else if ( rlp.rlim_cur < need )
00180 {
00181 rlp.rlim_cur = need;
00182 setrlimit (RLIMIT_NOFILE, &rlp);
00183 }
00184 return (FALSE);
00185 # else
00186 # if defined(_SEQUENT_) || defined(sequent)
00187
00188 int max = getdtablesize();
00189 return ( (max < need) && (setdtablesize (need) != need) );
00190 # else
00191
00192 int max = getdtablesize();
00193 return ( max < need );
00194 # endif
00195 # endif
00196 }
00197
00198
00199
00200
00201
00202 extern char *optarg;
00203 extern int optind;
00204
00205 int main(int argc, char *argv[])
00206 {
00207 int i, active, numtrc, source, outfd, errflag, first;
00208 int adjust, min_over, reassembly;
00209 unsigned long min_time, first_time;
00210 long numrec;
00211 char *trcfile;
00212 PCXX_EV *erec;
00213 # ifdef __ksr__
00214 int *sequence;
00215 int last_pthread, num_pthreads;
00216 # endif
00217 # if defined(__ksr__) || defined(__CM5__)
00218 unsigned long last_time;
00219 # endif
00220
00221 numtrc = 0;
00222 numrec = 0;
00223 errflag = FALSE;
00224 adjust = FALSE;
00225 reassembly = TRUE;
00226 first_time = 0L;
00227
00228 while ( (i = getopt (argc, argv, "ar")) != EOF )
00229 {
00230 switch ( i )
00231 {
00232 case 'a':
00233 adjust = TRUE;
00234 break;
00235
00236 case 'r':
00237 reassembly = FALSE;
00238 break;
00239
00240 default :
00241 errflag = TRUE;
00242 break;
00243 }
00244 }
00245
00246
00247
00248 active = argc - optind - 1;
00249 if ( cannot_get_enough_fd (active + 4) )
00250 {
00251 fprintf (stderr, "%s: too many input traces:\n", argv[0]);
00252 fprintf (stderr, " 1. merge half of the input traces\n");
00253 fprintf (stderr, " 2. merge other half and output of step 1\n");
00254 exit (1);
00255 }
00256 trcdes = (struct trcdescr *) malloc (active * sizeof(struct trcdescr));
00257
00258 for (i=optind; i<argc-1; i++)
00259 {
00260
00261 if ( (trcdes[numtrc].fd = open (argv[i], O_RDONLY)) < 0 )
00262 {
00263 perror (argv[i]);
00264 errflag = TRUE;
00265 }
00266 else
00267 {
00268 trcdes[numtrc].name = argv[i];
00269 trcdes[numtrc].buffer = (PCXX_EV *) malloc (INMAX * sizeof(PCXX_EV));
00270 trcdes[numtrc].erec = NULL;
00271 trcdes[numtrc].next = NULL;
00272 trcdes[numtrc].last = NULL;
00273 trcdes[numtrc].overflows = 0;
00274
00275
00276 if ( (erec = get_next_rec (trcdes + numtrc)) == NULL )
00277 {
00278
00279 fprintf (stderr, "%s: warning: trace empty - ignored\n",
00280 trcdes[numtrc].name);
00281 trcdes[numtrc].numrec = 0L;
00282 active--;
00283 }
00284
00285
00286 else if ( (erec->ev != PCXX_EV_INIT) && (erec->ev != PCXX_EV_INITM) )
00287 {
00288 fprintf (stderr, "%s: no valid event trace\n", trcdes[numtrc].name);
00289 exit (1);
00290 }
00291 else
00292 {
00293 if ( erec->nid > PCXX_MAXPROCS )
00294 fprintf (stderr,
00295 "%s: warning: node id %d too big for this machine (max. %d nodes)\n",
00296 trcdes[numtrc].name, erec->nid, PCXX_MAXPROCS);
00297
00298 trcdes[numtrc].numrec = 1L;
00299 if ( erec->ev == PCXX_EV_INIT )
00300 {
00301 if (!dynamic) {
00302 erec->ev = PCXX_EV_INITM;
00303 }
00304 trcdes[numtrc].nid = erec->nid;
00305 }
00306 else
00307 trcdes[numtrc].nid = -1;
00308
00309 trcdes[numtrc].lasttime = erec->ti;
00310 trcdes[numtrc].offset = 0L;
00311
00312 if(dynamic)
00313 {
00314
00315 open_edf_file("events", trcdes[numtrc].nid);
00316 parse_edf_file(trcdes[numtrc].nid);
00317 }
00318 numtrc++;
00319 }
00320 }
00321 }
00322 if (dynamic)
00323 {
00324
00325 store_merged_edffile("tau.edf");
00326 }
00327
00328 if ( (numtrc < 1) || errflag )
00329 {
00330 fprintf (stderr,
00331 "usage: %s [-a] [-r] inputtraces* (outputtrace|-)\n", argv[0]);
00332 fprintf(stderr,
00333 "Note: %s assumes edf files are named events.<nodeid>.edf and \n", argv[0]);
00334 fprintf(stderr," generates a merged edf file tau.edf\n");
00335
00336 exit (1);
00337 }
00338
00339
00340 if ( strcmp ((argv[argc-1]), "-") == 0 )
00341 {
00342 outfd = STDOUT;
00343 }
00344 else
00345 {
00346 trcfile = (char *) malloc ((strlen(argv[argc-1])+5) * sizeof(char));
00347 if ( strcmp ((argv[argc-1])+strlen(argv[argc-1])-4, ".trc") == 0 )
00348 strcpy (trcfile, argv[argc-1]);
00349 else
00350 sprintf (trcfile, "%s.trc", argv[argc-1]);
00351
00352 if ( access (trcfile, F_EXISTS) == 0 && isatty(2) )
00353 {
00354 fprintf (stderr, "%s exists; override [y]? ", trcfile);
00355 if ( getchar() == 'n' ) exit (1);
00356 }
00357 if ( (outfd = open (trcfile, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0 )
00358 {
00359 perror (trcfile);
00360 exit (1);
00361 }
00362 }
00363
00364 # if defined(__ksr__) && defined(__PCXX__)
00365
00366
00367
00368
00369 # define timestamp(i) \
00370 (trcdes[sequence[i]].erec->ti + trcdes[sequence[i]].offset)
00371 # define STEP 1
00372
00373 sequence = (int *) malloc (numtrc * sizeof(int));
00374 last_time = 0L;
00375 num_pthreads = numtrc;
00376 last_pthread = numtrc - 1;
00377
00378 do
00379 {
00380
00381
00382 for (i=0; i<numtrc; i++)
00383 {
00384 if ( trcdes[i].nid == (PCXX_MAXPROCS-1) )
00385 {
00386 num_pthreads = numtrc - 1;
00387 last_pthread = numtrc - 2;
00388 }
00389 else
00390 {
00391 do
00392 {
00393 erec = get_next_rec (trcdes + i);
00394 }
00395 while ( (erec != NULL) && (erec->ev != PCXX_IN_BARRIER) );
00396
00397 if ( erec == NULL )
00398 break;
00399 else
00400 sequence[erec->par] = i;
00401 }
00402 }
00403
00404 if ( erec != NULL )
00405 {
00406
00407
00408 if ( timestamp(0) <= last_time )
00409 {
00410 trcdes[sequence[0]].offset += last_time - timestamp(0) + STEP;
00411 }
00412
00413 for (i=1; i<num_pthreads; i++)
00414 {
00415 if ( timestamp(i) <= timestamp(i-1) )
00416 {
00417 trcdes[sequence[i]].offset += timestamp(i-1) - timestamp(i) + STEP;
00418 }
00419 }
00420 last_time = timestamp(last_pthread);
00421 }
00422 }
00423 while ( erec != NULL );
00424
00425
00426
00427 if ( i > (0 + (trcdes[0].nid == (PCXX_MAXPROCS - 1))) )
00428 {
00429 fprintf (stderr, "%s: missing barrier\n", trcdes[i].name);
00430 exit (1);
00431 }
00432
00433
00434 for (i=0; i<numtrc; i++)
00435 {
00436 if ( trcdes[i].offset )
00437 printf ("%s: offset %ld\n", trcdes[i].name, trcdes[i].offset);
00438
00439
00440 if ( trcdes[i].fd = -1 )
00441 {
00442 if ( (trcdes[i].fd = open (trcdes[i].name, O_RDONLY)) < 0 )
00443 {
00444 perror (argv[i]);
00445 exit (1);
00446 }
00447 }
00448
00449 else if ( lseek (trcdes[i].fd, 0, SEEK_SET) == -1 )
00450 {
00451 fprintf (stderr, "%s: cannot reset trace\n", trcdes[i].name);
00452 exit (1);
00453 }
00454 trcdes[i].erec = NULL;
00455 trcdes[i].next = NULL;
00456 trcdes[i].last = NULL;
00457
00458 erec = get_next_rec (trcdes + i);
00459 trcdes[i].numrec = 1L;
00460 if ( erec->ev == PCXX_EV_INIT )
00461 {
00462 if (!dynamic) {
00463 erec->ev = PCXX_EV_INITM;
00464 }
00465 trcdes[i].nid = erec->nid;
00466 }
00467 else
00468 trcdes[i].nid = -1;
00469
00470 trcdes[i].lasttime = erec->ti = erec->ti + trcdes[i].offset;
00471 }
00472 printf ("\n");
00473 # else
00474 # if defined(__CM5__) && defined(__PCXX__)
00475
00476
00477
00478
00479
00480
00481 last_time = 0L;
00482 for (i=0; i<numtrc; i++)
00483 {
00484 do
00485 {
00486 erec = get_next_rec (trcdes + i);
00487 }
00488 while ( (erec != NULL) && (erec->ev != PCXX_SYNC_MARK) );
00489
00490 if ( erec == NULL )
00491 {
00492 fprintf (stderr, "%s: cannot find sync marker\n", trcdes[i].name);
00493 exit (1);
00494 }
00495
00496 if ( erec->ti > last_time ) last_time = erec->ti;
00497 }
00498
00499
00500 for (i=0; i<numtrc; i++)
00501 {
00502 trcdes[i].offset = last_time - trcdes[i].erec->ti;
00503 printf ("%s: offset %ld\n", trcdes[i].name, trcdes[i].offset);
00504
00505
00506 if ( lseek (trcdes[i].fd, 0, SEEK_SET) == -1 )
00507 {
00508 fprintf (stderr, "%s: cannot reset trace\n", trcdes[i].name);
00509 exit (1);
00510 }
00511 trcdes[i].erec = NULL;
00512 trcdes[i].next = NULL;
00513 trcdes[i].last = NULL;
00514
00515 erec = get_next_rec (trcdes + i);
00516 trcdes[i].numrec = 1L;
00517 if ( erec->ev == PCXX_EV_INIT )
00518 {
00519 erec->ev = PCXX_EV_INITM;
00520 trcdes[i].nid = erec->nid;
00521 }
00522 else
00523 trcdes[i].nid = -1;
00524
00525 trcdes[i].lasttime = erec->ti = erec->ti + trcdes[i].offset;
00526 }
00527 printf ("\n");
00528 # endif
00529 # endif
00530
00531
00532
00533
00534 source = 0;
00535
00536 do
00537 {
00538
00539
00540 first = TRUE;
00541 for (i=0; i<numtrc; i++)
00542 {
00543 if ( trcdes[i].fd != -1 )
00544 {
00545 if ( first )
00546 {
00547 min_time = trcdes[i].lasttime;
00548 min_over = trcdes[i].overflows;
00549 source = i;
00550 first = FALSE;
00551 }
00552 else if ( trcdes[i].overflows < min_over )
00553 {
00554 min_time = trcdes[i].lasttime;
00555 min_over = trcdes[i].overflows;
00556 source = i;
00557 }
00558 else if ( (trcdes[i].overflows == min_over) &&
00559 (trcdes[i].lasttime < min_time) )
00560 {
00561 min_time = trcdes[i].lasttime;
00562 source = i;
00563 }
00564 }
00565 }
00566
00567 if ( adjust )
00568 {
00569 if ( numrec == 0 ) first_time = trcdes[source].erec->ti;
00570 trcdes[source].erec->ti -= first_time;
00571 }
00572
00573 #ifdef DEBUG
00574 printf("Before conv event %ld ", trcdes[source].erec->ev);
00575 #endif
00576
00577 trcdes[source].erec->ev = GID(trcdes[source].nid, trcdes[source].erec->ev);
00578
00579 #ifdef DEBUG
00580 printf("Output: node %d event %d\n", source, trcdes[source].erec->ev);
00581 #endif
00582
00583 output (outfd, (char *) trcdes[source].erec, sizeof(PCXX_EV));
00584 numrec++;
00585
00586 # if defined(__ksr__) && defined(__PCXX__)
00587 erec = trcdes[source].erec;
00588 if ( erec->ev == PCXX_IN_BARRIER )
00589 {
00590 if ( ((last_pthread + 1) % num_pthreads) != erec->par )
00591 fprintf (stderr, "pcxx_Barrier sequence error at %ld (%d -> %d)\n",
00592 erec->ti, last_pthread, erec->par);
00593 last_pthread = erec->par;
00594 }
00595 # endif
00596
00597
00598 do
00599 {
00600 if ( (erec = get_next_rec (trcdes + source)) == NULL )
00601 {
00602 active--;
00603 break;
00604 }
00605 else
00606 {
00607 trcdes[source].numrec++;
00608
00609 if ( erec->ev == PCXX_EV_CONT_EVENT )
00610 {
00611
00612
00613 erec->ev = GID(trcdes[source].nid, erec->ev);
00614 if ( reassembly )
00615 {
00616 output (outfd, ((char *) erec) + sizeof(short unsigned int),
00617 trcdes[source].contlen < CONTLEN ?
00618 trcdes[source].contlen : CONTLEN);
00619 trcdes[source].contlen -= CONTLEN;
00620 }
00621 else
00622 output (outfd, (char *) erec, sizeof(PCXX_EV));
00623 numrec++;
00624 }
00625 else
00626 {
00627
00628 if ( trcdes[source].nid != -1 ) erec->nid = trcdes[source].nid;
00629
00630
00631 erec->ti += trcdes[source].offset;
00632
00633
00634 if ( erec->ti < trcdes[source].lasttime ) trcdes[source].overflows++;
00635 trcdes[source].lasttime = erec->ti;
00636
00637
00638 trcdes[source].contlen = erec->par;
00639
00640 }
00641 }
00642 }
00643 while ( erec->ev == PCXX_EV_CONT_EVENT );
00644 }
00645 while ( active > 0 );
00646 for (i=0; i<numtrc; i++)
00647 {
00648 if (outfd != STDOUT)
00649 {
00650 fprintf (stderr, "%s: %ld records read.\n",
00651 trcdes[i].name, trcdes[i].numrec);
00652 }
00653 }
00654
00655 output_flush (outfd);
00656 close (outfd);
00657 exit (0);
00658 }
00659
00660
00661
00662
00663
00664
00665