Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
resource.c
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 #ifdef _KEEP_RCS_ID
00037 static const char source_file[] = __FILE__;
00038 #endif
00039 
00040 #if (1)
00041 # include <sys/time.h>
00042 # include <sys/resource.h>
00043   typedef struct rusage time_buf_t;
00044 #else
00045 # include <sys/param.h>
00046 # include <sys/types.h>
00047 # include <sys/times.h>
00048 # include <time.h>
00049   typedef struct tms time_buf_t;
00050 #endif
00051 
00052 #include <unistd.h>
00053 #include <string.h>
00054 /* Hack: These were defined in sys/param.h and will be redefined in defs.h
00055  * if we don't prevent it.  TODO: Really defs.h should check to see if they are
00056  * defined before defining them.
00057  */
00058 #ifdef MAX
00059 #undef MAX
00060 #endif
00061 #ifdef MIN
00062 #undef MIN
00063 #endif
00064 
00065 #include "defs.h"
00066 #include "resource.h"
00067 
00068 
00069 /* ====================================================================
00070  *
00071  * Basic internal data structures:
00072  *
00073  * ====================================================================
00074  */
00075 
00076 /* The following structure may contain absolute or delta information: */
00077 struct resources {
00078     TIME_INFO   utime;  /* User cpu time */
00079     TIME_INFO   stime;  /* System cpu time */
00080     TIME_INFO   etime;  /* Elapsed time */
00081     INT memory;         /* Memory used (bytes) */
00082     INT freemem;        /* Free memory allocated */
00083 };
00084 
00085 /* The following structure contains the latest absolute and the
00086  * accumulated delta information.  It is the basic object exported
00087  * to the world, although they don't know it.
00088  */
00089 struct rstate {
00090     RESOURCES cur;      /* The latest absolute information */
00091     RESOURCES del;      /* The accumulated delta information */
00092     struct rstate *dad; /* The parent structure in hierarchy */
00093     char *name;         /* The resource record name */
00094 };
00095 
00096 static void Clear_Resource ( RESOURCES *r );
00097 static void Get_Resources ( RESOURCES *r );
00098 static void Get_Delta_Time ( TIME_INFO *current,
00099                         TIME_INFO *base,
00100                         TIME_INFO *delta );
00101 static void Get_Delta_Resource ( RESOURCES *current,
00102                             RESOURCES *base,
00103                             RESOURCES *delta );
00104 static void Accum_Delta_Time ( TIME_INFO *delta, TIME_INFO *summary );
00105 static void Accum_Delta_Resource ( RESOURCES *delta,
00106                               RESOURCES *summary );
00107 
00108 /* We need a few buffers for internal use: */
00109 static time_buf_t tbuf;
00110 static RESOURCES curtime, deltime;
00111 static RSTATE runtime;
00112 #if (1)
00113 static struct timeval start_time;
00114 #else
00115 static INT start_time;  /* Initial date/time */
00116 #endif
00117 static INT initialized = 0;
00118 
00119 /* ====================================================================
00120  *
00121  * Clear_Resource
00122  *
00123  * Clear all components of a resource structure.
00124  *
00125  * ====================================================================
00126  */
00127 
00128 static void
00129 Clear_Resource (
00130     RESOURCES *r
00131 )
00132 {
00133     r->utime.secs  = 0;
00134     r->utime.usecs = 0;
00135     r->stime.secs  = 0;
00136     r->stime.usecs = 0;
00137     r->etime.secs  = 0;
00138     r->etime.usecs = 0;
00139     r->memory      = 0;
00140     r->freemem     = 0;
00141 }
00142 
00143 /* ====================================================================
00144  *
00145  * Get_Resources
00146  *
00147  * Fill the RESOURCES structure passed with the current time/state.
00148  *
00149  * ====================================================================
00150  */
00151 
00152 static void
00153 Get_Resources (
00154     RESOURCES *r
00155 )
00156 {
00157 #if (1)
00158     struct timeval now;
00159 #else
00160     INT secs, frac;
00161 #endif
00162 
00163     /* Initialize if the user didn't: */
00164     if ( ! initialized ) Resource_Init ();
00165 
00166     /* Get the elapsed time: */
00167 #if (1)
00168 
00169 /* Solaris workaround */
00170 #if defined(_SOLARIS_SOLARIS) || defined(_LINUX_LINUX)
00171     gettimeofday(&now, NULL);
00172 #elif !defined(linux)
00173     gettimeofday(&now, NULL);
00174 #else
00175     gettimeofday(&now);
00176 #endif
00177 
00178     r->etime.secs  = now.tv_sec  - start_time.tv_sec;
00179     r->etime.usecs = now.tv_usec - start_time.tv_usec;
00180 #else
00181     r->etime.secs  = time (0) - start_time;
00182     r->etime.usecs = 0;
00183 #endif
00184 
00185     /* Get the CPU time information from the system: */
00186 #if (1)
00187     getrusage (RUSAGE_SELF, &tbuf);
00188 #else
00189     (void) times (&tbuf);
00190 #endif
00191 
00192     /* Transfer it to caller's structure: */
00193 #if (1)
00194     r->utime.secs  = tbuf.ru_utime.tv_sec;
00195     r->utime.usecs = tbuf.ru_utime.tv_usec;
00196     r->stime.secs  = tbuf.ru_stime.tv_sec;
00197     r->stime.usecs = tbuf.ru_stime.tv_usec;
00198 #else
00199     secs = tbuf.tms_utime / HZ;
00200     frac = tbuf.tms_utime - (secs*HZ);
00201     r->utime.secs  = secs;
00202     r->utime.usecs = frac * (1000000/HZ);
00203     secs = tbuf.tms_stime / HZ;
00204     frac = tbuf.tms_stime - (secs*HZ);
00205     r->stime.secs  = secs;
00206     r->stime.usecs = frac * (1000000/HZ);
00207 #endif
00208 
00209     /* Get the memory information */
00210     r->memory = (INT) sbrk(0);
00211     r->freemem = 0;
00212 }
00213 
00214 /* ====================================================================
00215  *
00216  * Get_Delta_Time
00217  *
00218  * Set delta to the time difference between current and base.
00219  *
00220  * ====================================================================
00221  */
00222 
00223 static void
00224 Get_Delta_Time (
00225     TIME_INFO *current, /* This is current time */
00226     TIME_INFO *base,    /* Calculate delta from this base */
00227     TIME_INFO *delta    /* Put delta here */
00228 )
00229 {
00230     delta->secs  = current->secs  - base->secs;
00231     delta->usecs = current->usecs - base->usecs;
00232     if ( delta->usecs < 0 ) {
00233         delta->usecs += 1000000;
00234         delta->secs --;
00235     }
00236 }
00237 
00238 
00239 /* ====================================================================
00240  *
00241  * Get_Delta_Resource
00242  *
00243  * Calculate the delta resource usage from a given base.
00244  *
00245  * ====================================================================
00246  */
00247 
00248 static void
00249 Get_Delta_Resource (
00250     RESOURCES *current, /* Put current state here */
00251     RESOURCES *base,    /* Calculate delta from this base */
00252     RESOURCES *delta    /* Put delta here */
00253 )
00254 {
00255     Get_Resources ( current );
00256 
00257     Get_Delta_Time ( &current->utime, &base->utime, &delta->utime );
00258     Get_Delta_Time ( &current->stime, &base->stime, &delta->stime );
00259     Get_Delta_Time ( &current->etime, &base->etime, &delta->etime );
00260     delta->memory  = current->memory  - base->memory;
00261     delta->freemem = current->freemem - base->freemem;
00262 }
00263 
00264 /* ====================================================================
00265  *
00266  * Accum_Delta_Time
00267  *
00268  * Accumulate a delta time into a summary record.
00269  *
00270  * ====================================================================
00271  */
00272 
00273 static void
00274 Accum_Delta_Time (
00275     TIME_INFO *delta,   /* Add this delta ... */
00276     TIME_INFO *summary  /* ... to this summary record */
00277 )
00278 {
00279     summary->secs  += delta->secs;
00280     summary->usecs += delta->usecs;
00281     if ( summary->usecs >= 1000000 ) {
00282         summary->usecs -= 1000000;
00283         summary->secs ++;
00284     }
00285 }
00286 
00287 
00288 /* ====================================================================
00289  *
00290  * Accum_Delta_Resource
00291  *
00292  * Accumulate a delta resource record into a summary record.
00293  *
00294  * ====================================================================
00295  */
00296 
00297 static void
00298 Accum_Delta_Resource (
00299     RESOURCES *delta,   /* Add this delta ... */
00300     RESOURCES *summary  /* ... to this summary record */
00301 )
00302 {
00303     Accum_Delta_Time ( &delta->utime, &summary->utime );
00304     Accum_Delta_Time ( &delta->stime, &summary->stime );
00305     Accum_Delta_Time ( &delta->etime, &summary->etime );
00306     summary->memory  = MAX(summary->memory,delta->memory);
00307     summary->freemem += delta->freemem;
00308 }
00309 
00310 /* ====================================================================
00311  *
00312  * Resource_Init
00313  *
00314  * Initialize the resource module.  Currently means just initializing
00315  * the start_time and runtime variables.
00316  *
00317  * ====================================================================
00318  */
00319 
00320 void
00321 Resource_Init ( void )
00322 {
00323     /* Initialize elapsed time base: */
00324 #if (1)
00325 
00326 #if defined(_SOLARIS_SOLARIS) || defined(_LINUX_LINUX)
00327     gettimeofday(&start_time, NULL);
00328 #elif !defined(linux)
00329     gettimeofday(&start_time, NULL);
00330 #else
00331     gettimeofday(&start_time);
00332 #endif 
00333 
00334 #else
00335     start_time = time (0);
00336 #endif
00337     initialized = 1;
00338 
00339     /* Initialize the process initialization structure: */
00340     runtime.name = "Process";
00341     Get_Resources ( &runtime.cur );
00342 }
00343 
00344 
00345 /* ====================================================================
00346  *
00347  * Resource_Alloc
00348  *
00349  * Allocate and initialize a resource structure.
00350  *
00351  * ====================================================================
00352  */
00353 
00354 RSTATE *
00355 Resource_Alloc (
00356     char *rname,
00357     RSTATE *parent
00358 )
00359 {
00360     RSTATE *r;
00361 
00362     r = (RSTATE *) calloc ( 1, sizeof(RSTATE) );
00363     r->name = rname;
00364     r->dad  = parent;
00365 
00366     return r;
00367 }
00368 
00369 /* ====================================================================
00370  *
00371  * Resource_Accum
00372  *
00373  * Accumulate resource information.  Valid requests are:
00374  *   RR_Clear:  Clear the delta information.
00375  *   RR_Start:  Start a new delta period (i.e. set current state).
00376  *   RR_Stop:   Add a delta period to the summary.
00377  *   RR_End:    Accumulate delta information to parent and clear.
00378  * The default for an unrecognized request is RR_Start.  Note that if
00379  * there is no parent, RR_End is equivalent to RR_Clear.  All of the
00380  * requests set current state.
00381  *
00382  * See Resource_Report and Resource_Time for reporting possibilities.
00383  *
00384  * ====================================================================
00385  */
00386 
00387 void
00388 Resource_Accum ( RSTATE *r, RES_REQUEST req )
00389 {
00390     /* If passed a NULL pointer, just return: */
00391     if ( ! r ) return;
00392 
00393     /* Get the current state: */
00394     Get_Delta_Resource ( &curtime, &r->cur, &deltime );
00395 
00396     /* Do the right thing: */
00397     switch ( req ) {
00398         case RR_Clear:  Clear_Resource ( &r->del );
00399                         break;
00400         case RR_Start:  break;
00401         case RR_Stop:   Accum_Delta_Resource ( &deltime, &r->del );
00402                         break;
00403         case RR_End:    if ( r->dad ) {
00404                             Accum_Delta_Resource ( &r->del, &r->dad->del );
00405                             Clear_Resource ( &r->del );
00406                         }
00407                         break;
00408     }
00409 
00410     /* Reset the current state: */
00411     r->cur = curtime;
00412 }
00413 
00414 /* ====================================================================
00415  *
00416  * Get_Time
00417  *
00418  * Return a pointer to the requesting timing structure.  Returns NULL
00419  * if the request is not recognized.
00420  *
00421  * ====================================================================
00422  */
00423 
00424 TIME_INFO *
00425 Get_Time (
00426     RSTATE *r,
00427     RES_REQUEST req
00428 )
00429 {
00430     switch ( req ) {
00431         case RR_Current_User:           return &(r->cur.utime);
00432         case RR_Current_System:         return &(r->cur.stime);
00433         case RR_Current_Elapsed:        return &(r->cur.etime);
00434         case RR_Delta_User:             return &(r->del.utime);
00435         case RR_Delta_System:           return &(r->del.stime);
00436         case RR_Delta_Elapsed:          return &(r->del.etime);
00437     }
00438     return 0;
00439 }
00440 
00441 
00442 /* ====================================================================
00443  *
00444  * Get_Timer_Name
00445  *
00446  * Return the name string for a resource record.
00447  *
00448  * ====================================================================
00449  */
00450 
00451 char *
00452 Get_Timer_Name (
00453     RSTATE *r
00454 )
00455 {
00456     return r->name;
00457 }
00458 
00459 /* ====================================================================
00460  *
00461  * Get_Memory
00462  *
00463  * Return the current or delta memory usage.
00464  *
00465  * ====================================================================
00466  */
00467 
00468 INT
00469 Get_Memory (
00470     RSTATE *r,
00471     RES_REQUEST req
00472 )
00473 {
00474     switch ( req ) {
00475         case RR_Current_Memory:         return r->cur.memory;
00476         case RR_Delta_Memory:           return r->del.memory;
00477     }
00478     return 0;
00479 }
00480 
00481 /* ====================================================================
00482  *
00483  * Resource_Report
00484  *
00485  * Report resource usage.  If the RSTATE structure pointer passed
00486  * is non-null, report its current or delta content, as requested.
00487  * If it is null, report the current process state.
00488  *
00489  * ====================================================================
00490  */
00491 
00492 void
00493 Resource_Report (
00494     FILE *file,
00495     RES_REQUEST func,
00496     RSTATE *r,
00497     char *title
00498 )
00499 {
00500     RESOURCES *res;
00501 
00502     /* Deal with NULL r: */
00503     if ( ! r ) {
00504         res = &curtime;
00505         Get_Resources (res);
00506 
00507     /* Otherwise select reportable structure using func: */
00508     } else {
00509         switch ( func ) {
00510             case RR_Report_Delta:       res = &(r->del);
00511                                         break;
00512             case RR_Report_Current:
00513             default:                    res = &(r->cur);
00514                                         break;
00515         }
00516     }
00517 
00518     /* Report: */
00519     if ( title && *title ) fprintf ( file, "%s\n", title );
00520     fprintf ( file,
00521 #if (1)
00522       "\tuser:\t%4d.%06d\n\tsystem:\t%4d.%06d\n\telapsed: %4d.%06d\n",
00523               res->utime.secs, res->utime.usecs,
00524               res->stime.secs, res->stime.usecs,
00525               res->etime.secs, res->etime.usecs );
00526 #else
00527       "\tuser:\t%4d.%03d\n\tsystem:\t%4d.%03d\n\telapsed: %4d.%02d\n",
00528               res->utime.secs, res->utime.usecs/1000,
00529               res->stime.secs, res->stime.usecs/1000,
00530               res->etime.secs, res->etime.usecs/10000 );
00531 #endif
00532     fprintf ( file, "\tmemory:\t%8x\n\tfree:\t%8x\n",
00533               res->memory, res->freemem );
00534 }
00535 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines