Starts and stops execution profiling using data areas defined in the function parameters.
Standard C Library (libc.a)
#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.
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 themon.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 */
Item | Description |
---|---|
LowProgramCounter (prof name: p_low) | Defines the lowest execution-time program address in the range to be profiled. The value of the LowProgramCounter parameter cannot be 0 when using themonitor subroutine to begin profiling. |
HighProgramCounter (prof name: p_high) | Defines the next address after the highest-execution time
program address in the range to be profiled. The program address parameters may be defined by function names or address expressions. If defined by a function name, then a function name expression must be used to dereference the function pointer to get the address of the first instruction in the function. This is required because the function reference in this context produces the address of the function descriptor. The first field of the descriptor is the address of the function code. See the examples for typical expressions to use. |
Buffer (prof name: p_buff) | Defines the beginning address of an array of BufferSize HISTCOUNTERs to be used for data collection. This buffer includes the space for the program address-sampling counters and the function-count data areas. In the case of a multiple range specification, the space for the function-count data area is included at the beginning of the first range in the BufferSize specification. |
BufferSize (prof name: p_bufsize) | Defines the size of the buffer in number of HISTCOUNTERs. Each counter is of type HISTCOUNTER (defined as short in the mon.h file). When the buffer includes space for the function-count data area (single range specification and first range of a multi-range specification) the NFunction parameter defines the space to be used for the function count data, and the remainder is used for program-address sampling counters for the range defined. The scale for the profil call is calculated from the number of counters available for program address-sample counting and the address range defined by the LowProgramCounter and HighProgramCounter parameters. See themon.h file. |
NFunction | Defines the size of the space to be used for the function-count
data area. The space is included as part of the first (or only) range
buffer. When -p profiling is defined, the NFunction parameter defines the maximum number of functions to be counted. The space required for each function is defined to be: sizeof(struct poutcnt) The poutcnt structure is defined in the mon.h file. The total function-count space required is: NFunction * sizeof(struct poutcnt) When -pg profiling is defined, the NFunction parameter defines the size of the space (in bytes) available for the function-count data structures, as follows: range = HighProgramCounter - LowProgramCounter; tonum = TO_NUM_ELEMENTS( range ); if ( tonum < MINARCS ) tonum = MINARCS; if ( tonum > TO_MAX-1 ) tonum = TO_MAX-1; tosize = tonum * sizeof( struct tostruct ); fromsize = FROM_STG_SIZE( range ); rangesize = tosize + fromsize + sizeof(struct gfctl); This is computed and summed for all defined ranges. In this expression, the functions and variables in capital letters as well as the structures are defined in the mon.h file. |
NotZeroA | Specifies a value of parameter 1, which is any value except 0. Ignored when it is not zero. |
DoNotCareA | Specifies a value of parameter 2, of any value, which is ignored. |
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*/
}
Item | Description |
---|---|
mon.out | Data file for -p profiling. |
gmon.out | Data file for -pg profiling. |
/usr/include/mon.h | Defines the _mondata.prof_type global variable in the monglobal data structure, the prof structure, and the functions referred to in the previous examples. |