/*static char *SCCSID = "@(#)proxport.h	6.1 90/11/17";*/
/*	SCCSID = "@(#)proxport.h  1.5 90/08/28" */


/*  PROXPORT.H:	 profiling routines Header File
 *
 *  Author:
 *	Wayne Johnson
 *
 *
 *  IBM/Microsoft Confidential
 *
 *  Copyright (c) IBM Corporation 1987, 1989
 *  Copyright (c) Microsoft Corporation 1987, 1989
 *
 *  All Rights Reserved
 *
 *
 *
 *  Dependencies:
 *	basedef.h	- standard type definitions
 *	tkptda.h	- for PPTDA Definition (not needed for external use )
 *	profuser.h	- for user flag specifications
 *
 *  History:
 *
 */




/***EK+ Flag Settings for Profiling options and Status
 *
 *	These are used by the profiler to keep track of status.
 *	These are in addtion to the constants in ProfUser.h used to specify
 *	different options.  All of these flags are used in the same word,
 *	so should not be in reused.
 */


/* Profiling Collection */

#define PROC_MODULE	(USHORT)0x0008	/* count per module */

#define PROC_FLAGS	(USHORT)(PROC_IP_COUNT|PROC_MODULE|PROC_IP_RECORD)


/* Other Profile settings */

#define PROO_CURRENT_MODULE   (USHORT)0x0010 /* add current module to module*/
#define PROO_MODULE_DATA      (USHORT)0x0020 /* keep counts per module for all
						modules linked to the profiled
						process */
#define PROO_IRREGULAR_SAMPLING	(USHORT)0x0040 /* use non-periodic sampling */
#define PROO_WRAP_RECORD      (USHORT)0x0080 /* Over write old data on buffer
						overflow for IP_RECORD */


/* Internal Profile status flags */

#define PROI_ENABLED	      (USHORT)0x0100 /* profiling is enabled */
#define PROI_EXISTING_THREAD  (USHORT)0x0200 /* thread exists at profinit time */
#define PROI_KILLED_THREAD    (USHORT)0x0400 /* thread killed before proDUMP */
#define PROI_IP_RECORD_FULL   (USHORT)0x0800 /* record buffer is full */
#define PROI_PCB_TMB	      (USHORT)0x1000 /* this block represents a
						PCB_TMB rather than a PCB */

#define PROI_STATUS_FLAGS     (USHORT)(PROI_ENABLED|PROI_EXISTING_THREAD|PROI_KILLED_THREAD|PROI_IP_RECORD_FULL|PROI_PCB_TMB)

/* Kernel Profiling sub-Functions */

#define PROF_CREATE	    0
#define PROF_START	    1
#define PROF_STOP	    2
#define PROF_CLEAR	    3
#define PROF_DUMP	    4
#define PROF_DESTROY	    5
#define PROF_INT_TEST	    6


/* proDUMP Requests - Different types of information that can be returned
 *		      by proDump
 */

#define PROD_PCB		0	/* get PCB and global information
					   (for specified thread) */
#define PROD_MPR_LIST		1	/* get MPR list */
#define PROD_IP_RECORD		2	/* get IP_RECORD buffer */
#define PROD_IP_COUNT		3	/* get IP_COUNT buffer for specified
					   mpr (and thread) */

/*end*/




/* other profiling constants */
#define PRO_PERIOD_DEFAULT	1000	/* default period for sampling */
#define PRO_PERIOD_MIN		1000	/* Minimum number of microseconds
					   between samplings */
#define PRO_PERIOD_MAX		54926	/* 14.318 Mhz/12, longest sample for
					   timer0 */


/* XLATOFF */
#define PRO_IP_COUNTER_SIZE	(sizeof (ULONG))




/***	proAssert - profiler assertion macro, turned on by MISCSTRICT
 *
 *	ENTRY:	expression
 *	EXIT:	halt kernel if expression is false, otherwise no effect
 */
#ifdef MISCSTRICT
#   define proAssert(exp) _assert(exp)
#else
#   define proAssert(exp)
#endif

/* XLATON */



/* Types */

typedef unsigned long LADDR;	/* laddr */


/* DATA STRUCTURES  */


/*  Kernal Data Collection Structures
 *
 *  these sturcures are used to collect data at interupt time.	There is a
 *  list of Module Profile records that represents all of the memory
 *  that is being profiled.
 */




/* Module Profile Record
 *
 * A list of module profile records represents all of the memory that
 * is being profiled.
 */

typedef struct _MPR *PMPR;

typedef struct _MPR {		/* mpr */
    LADDR  mpr_laddrModule;	/* beginning linear address */
    ULONG  mpr_cbModule;	/* length (in bytes) */
    ULONG  mpr_fbCollectType;	/* Type of Data collection for this Module */
    PMPR   mpr_pmprNext;	/* Next Record in Chain */
    ULONG  mpr_ulProfData;	/* Data Depends on colleciton type:
				    IP_Count = pointer to record buffer
				    Per Module = counter for this module */
    } MPR;



/* PROFILE Control Block
 * this is what wil be at the head of each process that gathers data
 * It will point to a linked list of Module Profile Records.
 */

typedef struct _PCB *PPCB;

typedef struct _PCB {		/* pcb */
    USHORT pcb_fsOptions;	/* flags to control profiling options */
    BYTE   pcb_bShiftValue;	/* number of bits to shift if in IP_COUNT */
    ULONG  pcb_cticIdle;	/* count of idle tics */
    ULONG  pcb_cticV86;		/* count of v86 mode tics */
    ULONG  pcb_cticSYS;		/* count of tics in system arena */
    ULONG  pcb_cticSHR;		/* count of tics in shared arena */
    ULONG  pcb_cticEXE;		/* count of tics in EXE space */
    ULONG  pcb_claddrSampled;	/* Size, in addresses, of Collection Buffer */
    ULONG  pcb_iladdrSampled;	/* Index to end of Sampled LADDRs */
    LADDR *pcb_aladdrSampled;	/* Array to store EIPs in IP_Record profiling*/
    PMPR   pcb_pmprHead;	/* Chain of Module Profile Records */
    } PCB;


#ifndef PRO_EXTERNAL

/* XLATOFF */


/* PROFILE Dead Thread Record
 *
 * this will store the pcb and tid of threads that get killed during
 * profiling.
 */

typedef struct _PDTR *PPDTR;

typedef struct _PDTR {		/* pdtr */
    TID		tid;		/* TID of this thread */
    PPCB	pPCB;		/* PCB used while alive	*/
    PPDTR	ppdtrNext;	/* Pointer to next pdtr in chain */
    } PDTR;



/* PROFILE CONTROL BLOCK - Thread Master Block
 *
 * this is what will be pointed to in the PTDA during thread level profiling
 * instead of a PCB.  It looks just like PCB as long as the only field
 * checked is the fsOption feild.  This allows it to be checked at int time
 * to determine if it is a PCB_TMB and thread profiling should be done, or a
 * PCB and process level profiling should be done.
 */

typedef struct _PCB_TMB *PPCB_TMB;

typedef struct _PCB_TMB {	/* pcb_tmb */
    USHORT	fsOptions;	/* flags to control profiling options */
    PPTDA	pPTDA;		/* ptda for this process */
    USHORT	cPDTR;		/* number of PDTRs stored here */
    PPDTR	ppdtrHead;	/* Chain of Module Profile Records */
    } PCB_TMB;

/* XLATON */



/* PROFILE MASTER BLOCK
 *
 * This is the master profile structure for the system.  It keeps track
 * of which processes are profiling, the type of profiling going on,
 * and the pointer to the system data area, if any.
 */

typedef struct _PMB *PPMB;

typedef struct _PMB {		/* pmb */
    INT		pmb_cSessionsCreated;	/* number of sessions Initialized */
    INT		pmb_cSessionsStarted;	/* number of sessions Started */
    struct vmlh_s pmb_hLock;		/* handle for locked int code */
    PPCB	pmb_ppcbSystem;		/* pointer to System PCB */
    USHORT	pmb_sSamplePeriod;	/* Period of sample in mSecs */
    BYTE	pmb_fInt0Clear;		/* =TRUE if int 0 disabled before profiling */
    BYTE	pmb_cProfErrors;	/* count of errors in in profiling */

    /* the followig fields are used to support random sampling */
    BYTE	pmb_fRandomSample;	/* TRUE = NON-Periodic Sampling */
    BYTE       *pmb_aRandomCount;	/* pointer to start of randomCount array */
    BYTE	pmb_cRandomCount;	/* count of elements in randomCount array */
    BYTE	pmb_iRandomCount;	/* index into array for next wait */
    BYTE	pmb_cRandomWait;	/* how many ticks left to wait */
    } PMB;


#endif

/* XLATOFF */


/*  Kernel entry parameter Data Structures.
 *
 *  These data structures are used to pass data to the kernel entry point.
 */


    /* Module address ranges */

    typedef struct _PROF_RANGE {
	LADDR  laddrRange;	/* beginning linear address */
	ULONG  cbRange;		/* length of range */
	ULONG  fFullCollection;	/* TRUE = detailed profiling */
	} PROF_RANGE;



   /***ET+ Profile Init Record
    *
    * This record is passed in to the API at Create time to configure
    * profiling session.
    */

    typedef struct _PIR {
	PROF_RANGE  *aRange;	/* array of ranges */
	USHORT	cRange;		/* count of ranges in array */
	USHORT	fsOptions;	/* flags to control profiling options */
	ULONG	cbRecordBuffer;	/* size of buffer to record data in */
	USHORT	sSamplePeriod;	/* sampling period in microSeconds */

	/* the followig fields are used to support random sampling */
	PBYTE	aRandomCount;	/* pointer to start of randomCount array */
	BYTE	cRandomCount;	/* count of elements in randomCount array */
	} PIR;

    /*end*/


   /***ET+ PROFILE DUMP RECORD
    *
    * This record is passed to the API at Dump time to request the type of
    * information to be dumped and where to put it.
    */

    typedef struct _PDR {
	BYTE   bFunc;		/* Dump Sub Funtion */
	USHORT iThread;		/* Thread to get data for.  First thread is
				   0, as in an array. (ignored if not
				   sampling at thread level) */
	LADDR  laddrModule;	/* laddr of module to return data for
				   PROD_IP_COUNT */
	ULONG  cbDumpData;	/* length of dump buffer (in bytes) */
	PBYTE  abDumpData;	/* buffer for returned info */
	} PDR;

    /*end*/


/*  Kernel Data Return Structures.
 *
 *  These data structures are used to return data to the calling function.
 *  They are request types returned by the proDump subfunction. Except for
 *  the first structure, PCBD, these structures contain two types each.
 *  The first is the structure that represents the header block.  This part
 *  contains information on the count of the entries.  The second structure
 *  is the framework structure.	  It contains the header struture and the
 *  first element in what will be an array of elements to follow.
 *
 *  The dump structures are set up this way because the header structure
 *  allows easy size determination of the header portion of the dump and the
 *  frame structure offers a starting point for the array
 *  of data that will be dumped through these strutures.
 */

   /***ET+ PROFILE CONTROL BLOCK DUMP
    *
    * This Record returns the PCB for the session (or thread if in thread
    * mode) as well as global profiling values.  The aladdrSampled and
    * pmprHead feilds of the PCB will be unused and will be zeroed before
    * being returned by the kernal.
    */

    typedef struct _PCBD *PPCBD;

    typedef struct _PCBD {
	PCB	pcb;		/* Profile control block */
	USHORT	sSamplePeriod;	/* Period of sample in uSecs */
	BYTE	cProfErrors;	/* count of errors in in profiling */
	USHORT	cThreads;	/* Count of threads for process (0 if not
				   in thread mode) */
	USHORT	TID;		/* Thread ID of requested thread (0 if not
				   in thread mode) */
	} PCBD;

    /*end*/


   /***ET+ MODULE PROFILE RECORD DUMP
    *
    * This structure forms the framework for dumping the MPR list.  It dumps
    * the MPRs as an array of MPRs, with aMPR[0] being mprFirst.
    * A MPRD Buffer is structured as follows:
    *
    *
    *		|----------------------|
    *		|	cMPR	       |
    *		|----------------------|
    *		|		       |
    *		|	aMPR[0]	       |
    *		|		       |
    *		|----------------------|
    *		|		       |
    *		|	aMPR[1]	       |
    *		|		       |
    *		|----------------------|
    *		|		       |
    *		|	aMPR[2]	       |
    *		|		       |
    *		|----------------------|
    *		|	   .	       |
    *		|	   .	       |
    *		|	   .	       |
    *		|		       |
    *		|----------------------|
    *		|		       |
    *		|	aMPR[cMPR-1]   |
    *		|		       |
    *		|----------------------|
    *
    * All pointers are zeroed in the returned MPR list.
    */

    /* Header */
    typedef struct _MPRDH {
	BYTE	cMPR;		/* count of number of MPRs in this array */
	} MPRDH;

    /* Frame */
    typedef struct _MPRDF *PMPRDF;

    typedef struct _MPRDF {
	MPRDH	Header;		/* this is the header info */
	MPR	mprFirst;	/* First MPR in array of mprs dumped */
	} MPRDF;

    /*end*/


   /***ET+ IP RECORD DUMP
    *
    * This structure forms the framework for dumping the sampled linear
    * addresses.  It dumps the LADDRs as an array of LADDRs, with aLADDR[0]
    * being laddrFirst.	A IPRD Buffer is structured as follows:
    *
    *
    *		|----------------------|
    *		|    cLADDR	       |
    *		|----------------------|
    *		|    aLADDR[0]	       |
    *		|----------------------|
    *		|    aLADDR[1]	       |
    *		|----------------------|
    *		|    aLADDR[2]	       |
    *		|----------------------|
    *		|	   .	       |
    *		|	   .	       |
    *		|	   .	       |
    *		|		       |
    *		|----------------------|
    *		|    aLADDR[cLADDR-1]  |
    *		|----------------------|
    *
    */

    /* Header */
    typedef struct _IPRDH {
	ULONG	cLADDR;		/* Size, in addresses, of Collection Buffer */
	} IPRDH;

    /* Frame */
    typedef struct _IPRDF *PIPRDF;

    typedef struct _IPRDF {
	IPRDH	Header;		/* this is the header info */
	LADDR	laddrFirst;	/* First LADDR in array dumped from
				   IP_Record profiling*/
	} IPRDF;

    /*end*/


   /***ET+ IP COUNT DUMP
    *
    * This will be updated when proDUMP is updated with run length encoded
    * output to save space in data files.
    */

    /* Header */
    typedef struct _IPCDH {
	ULONG	cbModule;	/* length (in bytes) */
	ULONG	cCount;		/* number of counters */
	} IPCDH;

    /* Frame */
    typedef struct _IPCDF *PIPCDF;

    typedef struct _IPCDF {
	IPCDH	Header;		/* this is the header info */
	ULONG	ulCountFirst;	/* first counter in array dumped from
				   IP_COUNT profiling */
	} IPCDF;

    /*end*/

/* XLATON */




/* don't include function prototypes for uses outside of the kernal */
#ifndef PRO_EXTERNAL

//	External interfaces

// XLATOFF

extern INT PROAllocThrdPCB( tsd_t * );
extern INT PROSaveThrdPCB( tsd_t * );
extern INT PRODestroyPCB( PPCB * );

// XLATON


#endif
