Starts and stops execution profiling using data areas defined in the function parameters.
#include <mon.h> int monitor (LowProgramCounter, HighProgramCounter, Buffer, BufferSize, NFunction) OR int monitor (NotZeroA, DoNotCareA, Buffer,-1, NFunction) OR int monitor((caddr_t)0) caddr_t LowProgramCounter, HighProgramCounter; HISTCOUNTER *Buffer; int BufferSize, NFunction; caddr_t NotZeroA, DoNotCareA;
The monitor subroutine initializes the buffer area and starts profiling, or else stops profiling and writes out the accumulated profiling data. Profiling, when started, causes periodic sampling and recording of the program location within the program address ranges specified. Profiling also accumulates function call count data compiled with the -p or -pg option.
Executable programs created with the cc -p or cc -pg command automatically include calls to the monitor subroutine (through the monstartup and exit subroutines) to profile the complete user program, including system libraries. In this case, you do not need to call the monitor subroutine.
The monitor subroutine is called by the monstartup subroutine to begin profiling and by the exit subroutine to end profiling. The monitor subroutine requires a global data variable to define which kind of profiling, -p or -pg, is in effect. The monitor subroutine initializes four global variables that are used as parameters to the profil subroutine by the moncontrol subroutine:
The monitor subroutine examines the global data and parameter data in this order:
The global variable is set to -1 in the mcrt0.o file and to +1 in the gcrt0.o file, and defaults to 0 when the crt0.o file is used.
If -p profiling was in effect, then the file is named mon.out. If -pg profiling was in effect, the file is named gmon.out. The function is complete.
When the BufferSize parameter is not -1, a single program address range is defined for profiling, and the first monitor definition in the syntax is used to define the single program range.
When the BufferSize parameter is -1, multiple program address ranges are defined for profiling, and the second monitor definition in the syntax is used to define the multiple ranges. In this case, the ProfileBuffer value is the address of an array of prof structures. The size of the prof array is denoted by a zero value for the HighProgramCounter (p_high) field of the last element of the array. Each element in the array, except the last, defines a single programming address range to be profiled. Programming ranges must be in ascending order of the program addresses with ascending order of the prof array index. Program ranges may not overlap.
The buffer space defined by the p_buff and p_bufsize fields of all of the prof entries must define a single contiguous buffer area. Space for the function-count data is included in the first range buffer. Its size is defined by the NFunction parameter. The p_scale entry in the prof structure is ignored. The prof structure is defined in the mon.h file. It contains the following fields:
caddr_t p_low; /* low sampling address */ caddr_t p_high; /* high sampling address */ HISTCOUNTER *p_buff; /* address of sampling buffer */ int p_bufsize; /* buffer size- monitor/HISTCOUNTERs,\ profil/bytes */ uint p_scale; /* scale factor */
The monitor subroutine returns 0 upon successful completion.
If an error is found, the monitor subroutine sends an error message to stderr and returns -1.
#include <sys/types.h> #include <mon.h> main() { extern caddr_t etext; /*system end of main module text symbol*/ extern int start(); /*first function in main program*/ extern struct monglobal _mondata; /*profiling global variables*/ struct desc { /*function descriptor fields*/ caddr_t begin; /*initial code address*/ caddr_t toc; /*table of contents address*/ caddr_t env; /*environment pointer*/ } ; /*function descriptor structure*/ struct desc *fd; /*pointer to function descriptor*/ int rc; /*monitor return code*/ int range; /*program address range for profiling*/ int numfunc; /*number of functions*/ HISTCOUNTER *buffer; /*buffer address*/ int numtics; /*number of program address sample counters*/ int BufferSize; /*total buffer size in numbers of HISTCOUNTERs*/ fd = (struct desc*)start; /*init descriptor pointer to start\ function*/ numfunc = 300; /*arbitrary number for example*/ range = etext - fd->begin; /*compute program address range*/ numtics =NUM_HIST_COUNTERS(range); /*one counter for each 4 byte\ inst*/ BufferSize = numtics + ( numfunc*sizeof (struct poutcnt) \ HIST_COUNTER_SIZE ); /*allocate buffer space*/ buffer = (HISTCOUNTER *) malloc (BufferSize * HIST_COUNTER_SIZE); if ( buffer == NULL ) /*didn't get space, do error recovery\ here*/ return(-1); _mondata.prof_type = _PROF_TYPE_IS_P; /*define -p profiling*/ rc = monitor( fd->begin, (caddr_t)etext, buffer, BufferSize, \ numfunc); /*start*/ if ( rc != 0 ) /*profiling did not start, do error recovery\ here*/ return(-1); /*other code for analysis*/ rc = monitor( (caddr_t)0); /*stop profiling and write data file\ mon.out*/ if ( rc != 0 ) /*did not stop correctly, do error recovery here*/ return (-1); }
low = d0300000 high = d0312244
These two values can be determined from the loadquery subroutine at execution time, or by using a debugger to view the loaded programs' execution addresses and the loader map.
#include <sys/types.h> #include <mon.h> main() { extern caddr_t etext; /*system end of text symbol*/ extern int start(); /*first function in main program*/ extern struct monglobal _mondata; /*profiling global variables*/ struct prof pb[3]; /*prof array of 3 to define 2 ranges*/ int rc; /*monitor return code*/ int range; /*program address range for profiling*/ int numfunc; /*number of functions to count (max)*/ int numtics; /*number of sample counters*/ int num4fcnt; /*number of HISTCOUNTERs used for fun cnt space*/ int BufferSize1; /*first range BufferSize*/ int BufferSize2; /*second range BufferSize*/ caddr_t liblo=0xd0300000; /*lib low address (example only)*/ caddr_t libhi=0xd0312244; /*lib high address (example only)*/ numfunc = 400; /*arbitrary number for example*/ /*compute first range buffer size*/ range = etext - *(uint *) start; /*init range*/ numtics = NUM_HIST_COUNTERS( range ); /*one counter for each 4 byte inst*/ num4fcnt = numfunc*sizeof( struct poutcnt )/HIST_COUNTER_SIZE; BufferSize1 = numtics + num4fcnt; /*compute second range buffer size*/ range = libhi-liblo; BufferSize2 = range / 12; /*counter for every 12 inst bytes for\ a change*/ /*allocate buffer space - note: must be single contiguous\ buffer*/ pb[0].p_buff = (HISTCOUNTER *)malloc( (BufferSize1 +BufferSize2)\ *HIST_COUNTER_SIZE); if ( pb[0].p_buff == NULL ) /*didn't get space - do error\ recovery here* ;/ return(-1); /*set up the first range values*/ pb[0].p_low = *(uint*)start; /*start of main module*/ pb[0].p_high = (caddr_t)etext; /*end of main module*/ pb[0].p_BufferSize = BufferSize1; /*prog addr cnt space + \ func cnt space*/ /*set up last element marker*/ pb[2].p_high = (caddr_t)0; _mondata.prof_type = _PROF_TYPE_IS_P; /*define -p\ profiling*/ rc = monitor( (caddr_t)1, (caddr_t)1, pb, -1, numfunc); \ /*start*/ if ( rc != 0 ) /*profiling did not start - do error recovery\ here*/ return (-1); /*other code for analysis ...*/ rc = monitor( (caddr_t)0); /*stop profiling and write data \ file mon.out*/ if ( rc != 0 ) /*did not stop correctly - do error recovery\ here*/ return (-1);
#include <sys/types.h> #include <mon.h> main() { extern zit(); /*first function to profile*/ extern zot(); /*upper bound function*/ extern struct monglobal _mondata; /*profiling global variables*/ int rc; /*monstartup return code*/ _mondata.prof_type = _PROF_TYPE_IS_PG; /*define -pg profiling*/ /*Note cast used to obtain function code addresses*/ rc = monstartup(*(uint *)zit,*(uint *)zot); /*start*/ if ( rc != 0 ) /*profiling did not start, do error recovery\ here*/ return(-1); /*other code for analysis ...*/ exit(0); /*stop profiling and write data file gmon.out*/ }
This subroutine is part of Base Operating System (BOS) Runtime.
The moncontrol subroutine, monstartup subroutine, profil subroutine.
The gprof command, prof command.
The _end, _etext, or _edata Identifier.
List of Memory Manipulation Services in AIX Version 4.3 General Programming Concepts: Writing and Debugging Programs.