src/Profile/pcxx_events.cpp

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  * This program was prepared by PSI. 
00007  * All rights in the program are reserved by PSI.
00008  * Neither PSI nor the author(s)
00009  * makes any warranty, express or implied, or assumes any liability or
00010  * responsibility for the use of this software
00011  *
00012  * Visit http://www.acl.lanl.gov/POOMS for more details
00013  *
00014  ***************************************************************************/
00015 
00016 // -*- C++ -*-
00017 /***************************************************************************
00018  *
00019  * The IPPL Framework
00020  * 
00021  * This program was prepared by PSI. 
00022  * All rights in the program are reserved by PSI.
00023  * Neither PSI nor the author(s)
00024  * makes any warranty, express or implied, or assumes any liability or
00025  * responsibility for the use of this software
00026  *
00027  * Visit http://www.acl.lanl.gov/POOMS for more details
00028  *
00029  ***************************************************************************/
00030 
00031 /*********************************************************************/
00032 /*                  pC++/Sage++  Copyright (C) 1994                  */
00033 /*  Indiana University  University of Oregon  University of Rennes   */
00034 /*********************************************************************/
00035 
00036 /*
00037  * pcxx_event.c: simple SW monitor routines
00038  *
00039  * (c) 1994 Jerry Manic Saftware
00040  *
00041  * Version 3.0
00042  */
00043 
00044 # include <stdio.h>
00045 # include <stdlib.h>
00046 # include <string.h>
00047 # include <sys/types.h>
00048 # include <fcntl.h>
00049 # include <signal.h>
00050 # include <unistd.h>
00051 # include <Profile/Profiler.h>
00052 
00053 
00054 #   if ( !defined(__ksr__) || defined(UNIPROC) )
00055 #     define __private
00056 #   endif
00057 
00058 # define PCXX_EVENT_SRC
00059 # define TRACING_ON 1
00060 # include "pcxx_events.h"
00061 /* # include "TulipTimers.h"
00062 */
00063 
00064 
00065 extern time_t time(time_t * t);
00066 
00067 __private unsigned long int pcxx_ev_class = PCXX_EC_TRACER | PCXX_EC_TIMER;
00068 
00069 # ifndef TRUE
00070 # define FALSE 0
00071 # define TRUE  1
00072 # endif
00073 
00074 /* -- event record buffer ------------------------------------ */
00075 __private static PCXX_EV pcxx_buf[PCXX_BUFSIZE];
00076 
00077 /* -- pointer to next free element of event record buffer ---- */
00078 __private PCXX_EV *pcxx_ev_ptr = pcxx_buf;
00079 
00080 /* -- pointer to last available element of event record buffer */
00081 /* -- need one place for flush event => - 1 ------------------ */
00082 __private PCXX_EV *pcxx_ev_max = pcxx_buf + PCXX_BUFSIZE - 1;
00083 
00084 /* -- event trace file descriptor ---------------------------- */
00085 __private static int pcxx_fd;
00086 
00087 /* -- initialization status flags ---------------------------- */
00088 __private static int pcxx_num_init[PCXX_MAXPROCS];
00089 /*__private static int pcxx_not_first[PCXX_MAXPROCS]; */
00090 
00091 
00092 /* -- Use Profiling interface for time -- */
00093 long pcxx_GetUSecLong(void)
00094 {
00095   return (long) RtsLayer::getUSecD();
00096 }
00097 /* -- write event to buffer only [without overflow check] ---- */
00098 static void pcxx_EventOnly(long int ev,long int par)
00099 {
00100   pcxx_ev_ptr->ev   = ev;
00101   pcxx_ev_ptr->ti   = pcxx_GetUSecLong();
00102   pcxx_ev_ptr->par  = par;
00103   pcxx_ev_ptr->nid  = PCXX_MYNODE;
00104   pcxx_ev_ptr->tid  = PCXX_MYTHREAD;
00105   pcxx_ev_ptr++;
00106 }
00107 
00108 /* -- write event buffer to file ----------------------------- */
00109 void pcxx_EvFlush()
00110 {
00111   static PCXX_EV flush_end = { PCXX_EV_FLUSH_EXIT, 0, 0, 0L };
00112 
00113   if ( pcxx_ev_ptr != pcxx_buf )
00114   {
00115     if ( pcxx_ev_class & PCXX_EC_TRACER )
00116       pcxx_EventOnly (PCXX_EV_FLUSH_ENTER, pcxx_ev_ptr - pcxx_buf);
00117 
00118     write (pcxx_fd, pcxx_buf, (pcxx_ev_ptr - pcxx_buf) * sizeof(PCXX_EV));
00119     if ( pcxx_ev_class & PCXX_EC_TRACER )
00120     {
00121       flush_end.nid = PCXX_MYNODE;
00122       flush_end.ti  = pcxx_GetUSecLong();
00123       write (pcxx_fd, &flush_end, sizeof(PCXX_EV));
00124     }
00125     pcxx_ev_ptr = pcxx_buf;
00126   }
00127 }
00128 
00129 /* -- signal catching to flush event buffers ----------------- */
00130 # ifndef NSIG
00131 #   define NSIG 32
00132 # endif
00133 static SIGNAL_TYPE (*sighdlr[NSIG])(SIGNAL_ARG_TYPE);
00134 
00135 static void wrap_up(int sig)
00136 {
00137   fprintf (stderr, "signal %d on %d - flushing event buffer...\n", sig, PCXX_MYNODE);
00138   pcxx_EvFlush ();
00139   fprintf (stderr, "done.\n");
00140   if ( sighdlr[sig] != SIG_IGN ) (* sighdlr)(sig);
00141   exit (1);
00142 }
00143 
00144 static void init_wrap_up()
00145 {
00146 # ifdef SIGINT
00147   sighdlr[SIGINT ] = signal (SIGINT , wrap_up);
00148 # endif
00149 # ifdef SIGQUIT
00150   sighdlr[SIGQUIT] = signal (SIGQUIT, wrap_up);
00151 # endif
00152 # ifdef SIGILL
00153   sighdlr[SIGILL ] = signal (SIGILL , wrap_up);
00154 # endif
00155 # ifdef SIGFPE
00156   sighdlr[SIGFPE ] = signal (SIGFPE , wrap_up);
00157 # endif
00158 # ifdef SIGBUS
00159   sighdlr[SIGBUS ] = signal (SIGBUS , wrap_up);
00160 # endif
00161 # ifdef SIGTERM
00162   sighdlr[SIGTERM] = signal (SIGTERM, wrap_up);
00163 # endif
00164 # ifdef SIGABRT
00165   sighdlr[SIGABRT] = signal (SIGABRT, wrap_up);
00166 # endif
00167 # ifdef SIGSEGV
00168   sighdlr[SIGSEGV] = signal (SIGSEGV, wrap_up);
00169 # endif
00170 }
00171 
00172 /* -- initialize SW monitor and open trace file(s) ----------- */
00173 void pcxx_EvInit(char *name)
00174 {
00175   char *ptr;
00176   char *ptr1;
00177   PCXX_EV *pcxx_iter = pcxx_buf;
00178   
00179   static int first_time = 0; /* Sameer's fix to pcxx_num_init[] = 0 - 
00180                                 error on mpi in sgi8k*/
00181 
00182   if (first_time == 0)
00183   { 
00184     first_time = 1;
00185 # ifdef UNIPROC
00186     ptr = name;
00187 # else
00188     ptr = (char *) PCXX_MALLOC (strlen(name) + 1);
00189     strcpy (ptr, name);
00190     if ( ptr1 = strchr (ptr, '#') )
00191     {
00192       *ptr1++ = PCXX_MYNODE / 1000 + '0';
00193       *ptr1++ = PCXX_MYNODE % 1000 / 100 + '0';
00194       *ptr1++ = PCXX_MYNODE % 100 / 10 + '0';
00195       *ptr1   = PCXX_MYNODE % 10 + '0';
00196     }
00197     else
00198     {
00199       fprintf (stderr, "%s: trace file name does not contain '####'\n", name);
00200       exit (1);
00201     }
00202 # endif
00203 
00204       init_wrap_up ();
00205 
00206       if ((pcxx_fd = open (ptr, O_WRONLY|O_CREAT|O_TRUNC|O_APPEND, 0600)) < 0)
00207       {
00208         fprintf (stderr, "pcxx_EvInit[open]: ");
00209         perror (ptr);
00210         exit (1);
00211       }
00212 /* there may be some records in pcxx_ev_ptr already. Make sure that the
00213    first record has node id set properly */
00214       if ((&pcxx_buf[0])->ev == PCXX_EV_INIT) 
00215       { /* first record is init */
00216         for(pcxx_iter = pcxx_buf; pcxx_iter != pcxx_ev_ptr ; pcxx_iter++)
00217         { 
00218           pcxx_iter->nid = PCXX_MYNODE;
00219         }
00220       }
00221       else 
00222       { /* either the first record is blank - in which case we should 
00223            put INIT record, or it is an error */
00224         if (pcxx_ev_ptr == pcxx_buf) 
00225         { /* no records in here */
00226           pcxx_Event(PCXX_EV_INIT, pcxx_ev_class);
00227         }
00228         else 
00229         {
00230           printf("Warning: pcxx_EvInit(): First record is not INIT\n");
00231         }
00232       } 
00233 
00234     if ( pcxx_ev_class & PCXX_EC_TRACER )
00235       pcxx_Event (PCXX_EV_WALL_CLOCK, time((time_t *)0));
00236   }
00237   pcxx_num_init[PCXX_MYNODE]++;
00238   /* pcxx_not_first[PCXX_MYNODE] = TRUE; */
00239 }
00240 
00241 /* -- write event to buffer ---------------------------------- */
00242 void pcxx_Event(long int ev, long int par)
00243 {
00244   static int first_time = 0;
00245   if (first_time == 0) 
00246   { 
00247     if (ev != PCXX_EV_INIT) 
00248     {
00249       pcxx_ev_ptr = pcxx_buf;
00250         /* we need to ensure that INIT is the first event */
00251       pcxx_ev_ptr->ev = PCXX_EV_INIT; 
00252       pcxx_ev_ptr->ti   = pcxx_GetUSecLong();
00253       pcxx_ev_ptr->par  = pcxx_ev_class; /* init event */ 
00254       /* probably the nodeid is not set yet */
00255       pcxx_ev_ptr->nid  = PCXX_MYNODE;
00256       pcxx_ev_ptr->tid  = PCXX_MYTHREAD;
00257  
00258       pcxx_ev_ptr++; /* proceed to add this record, nodeid will be set later */
00259     } 
00260     first_time = 1;
00261   } 
00262         
00263   pcxx_ev_ptr->ev   = ev;
00264   pcxx_ev_ptr->ti   = pcxx_GetUSecLong();
00265   pcxx_ev_ptr->par  = par;
00266   pcxx_ev_ptr->nid  = PCXX_MYNODE;
00267   pcxx_ev_ptr->tid  = PCXX_MYTHREAD;
00268   pcxx_ev_ptr++;
00269 
00270   if ( pcxx_ev_ptr >= pcxx_ev_max ) pcxx_EvFlush (); 
00271 }
00272 
00273 /* -- terminate SW tracing ----------------------------------- */
00274 void pcxx_EvClose()
00275 {
00276   pcxx_num_init[PCXX_MYNODE]--;
00277   if ( pcxx_num_init[PCXX_MYNODE] == 0 )
00278   {
00279     if ( pcxx_ev_class & PCXX_EC_TRACER )
00280     {
00281       pcxx_Event (PCXX_EV_CLOSE, 0);
00282       pcxx_Event (PCXX_EV_WALL_CLOCK, time((time_t *)0));
00283     }
00284     pcxx_EvFlush ();
00285     close (pcxx_fd);
00286   }
00287 }
00288 
00289 /* -- write long event to buffer ----------------------------- */
00290 # define CONT_EV_LEN (sizeof(PCXX_EV) - sizeof(long int))
00291 
00292 void pcxx_LongEvent(long int ev, int ln, char *par)
00293 {
00294   char *buf;
00295   int i, j, cev_no;
00296 
00297   cev_no = ln / CONT_EV_LEN + ((ln % CONT_EV_LEN) > 0);
00298 
00299   /* -- inlined pcxx_Event (ev, cev_no); ----------------------- */
00300   pcxx_ev_ptr->ev   = ev;
00301   pcxx_ev_ptr->ti   = pcxx_GetUSecLong();
00302   pcxx_ev_ptr->par  = ln;
00303   pcxx_ev_ptr->nid  = PCXX_MYNODE;
00304   pcxx_ev_ptr->tid  = PCXX_MYTHREAD;
00305   pcxx_ev_ptr++;
00306   if ( pcxx_ev_ptr >= pcxx_ev_max ) pcxx_EvFlush (); 
00307 
00308   /* -- inlined pcxx_Event (ev, cev_no); ----------------------- */
00309   if ( ln )
00310   {
00311     for (i=0; i<cev_no; i++)
00312     {
00313       pcxx_ev_ptr->ev = PCXX_EV_CONT_EVENT;
00314       buf = ((char *) pcxx_ev_ptr) + sizeof(short unsigned int);
00315       for (j=0; j<CONT_EV_LEN; j++)
00316         *buf++ = (i*CONT_EV_LEN+j) < ln ? *par++ : '\0';
00317       pcxx_ev_ptr++;
00318       if ( pcxx_ev_ptr >= pcxx_ev_max ) pcxx_EvFlush (); 
00319     }
00320   }
00321 } 
00322 
00323 #if ( defined(TRACING_ON) && defined(ARIADNE_SUPPORT) )
00324 /* Function to trace the events of Ariadne. */
00325 void pcxx_AriadneTrace (long int event_class, long int event, int pid, int oid, int rwtype, int mtag, int par)
00326 {
00327 /* This routine writes the ariadne events to the trace file */
00328 long int trace_value = 0L; /* the first parameter to be traced */
00329 long int parameter = 0L; /* dummy to shift the par by 32 bits */ 
00330 /* Even for pC++ events we use U as the event rwtype and PCXX_... as the utag */
00331 /* This way we can keep the old format for tracing :
00332         parameter (32), pid (10), oid (10), rwtype (4) , utag (8) 
00333 for 64 bit long int */ 
00334   parameter = (long int) par; 
00335 
00336   if (sizeof (long int) == 8) 
00337   { /* This is true of SGI8K  */
00338 
00339     /* care has to be taken to ensure that mtag is 8 bits long */
00340   trace_value = (parameter << 32) | (pid << 22) | (oid << 12) | (rwtype << 8) | mtag;
00341 
00342   /*
00343   printf("Tracing ec = %lx, ev = %lx, pid = %d, oid = %d, mtag = %d, rwtype = %d, parameter = %d, trace_value = %ld\n", event_class, event, pid, oid, mtag, rwtype, parameter, trace_value);    
00344   */
00345 
00346   PCXX_EVENT(event_class, event, trace_value);
00347   } 
00348         
00349 }
00350 
00351 #endif  /* defined(TRACING_ON) && defined(ARIADNE_SUPPORT) */
00352 
00353 /* eof */
00354 
00355 /***************************************************************************
00356  * $RCSfile: addheaderfooter,v $   $Author: adelmann $
00357  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:17 $
00358  * IPPL_VERSION_ID: $Id: addheaderfooter,v 1.1.1.1 2003/01/23 07:40:17 adelmann Exp $ 
00359  ***************************************************************************/
00360 

Generated on Mon Jan 16 13:23:54 2006 for IPPL by  doxygen 1.4.6