Dos32Profile API


Calling convention

APIRET rc = Dos32Profile(ULONG func,
			 PID   pid,
			 PRFCMD *profcmd,
			 PRFRET *profret);

Return codes

	0	NO ERROR		ok
	8	NOT_ENOUGH_MEMORY	couldn't allocate profile structures
	87	INVALID_PARAMETER	some parameter not ok
	111	BUFFER_OVERFLOW		not enough size in return buffer
	115	PROTECTION_VIOLATION	invalid return buffer data
	126	MOD_NOT_FOUND		requested module data not available
	303	INVALID_PROCID		parameter 2 is not a valid PID
	328	SYS_INTERNAL		profile data structure corrupted
	543	PRF_NOT_INITIALIZED	profiling was not initialized
	544	PRF_ALREADY_INITIALIZED	profiling is already initialized
	545	PRF_NOT_STARTED		cannot stop profiling without start
	546	PRF_ALREADY_STARTED	profiling is already started
	547	PRF_TIMER_OUT_OF_RANGE	invalid timer frequency
	548	PRF_TIMER_RESET		re-initialized with different timer.

Arguments

func:
#define	PRF_CM_INIT	0	/* initialize, must pass pid and profcmd */
#define	PRF_CM_START	1	/* start profiling (pid) */
#define	PRF_CM_STOP	2	/* stop profiling (pid) */
#define	PRF_CM_CLEAR	3	/* clear profile counters (pid) */
#define PRF_CM_DUMP	4	/* read out profiling data (pid, profret) */
#define PRF_CM_EXIT	5	/* exit profiling, delete profiling structures */
pid:
pid of process to be profiled
0 if kernel profiling
profcmd:
command buffer

struct {
	PRFSLOT	*cm_slots;	/* Virtual address slots */
	USHORT	cm_nslots;	/* # of VA slots < 256 (!) */
	USHORT	cm_flags;	/* command */
#define PRF_PROCESS_MT	0	/* profile proc+threads */
#define PRF_PROCESS_ST	1	/* profile proc only */
#define PRF_KERNEL	2	/* profile kernel */

#define PRF_VADETAIL	0	/* create detailed page counters */
#define PRF_VAHIT	4	/* create hit table */
#define PRF_VATOTAL	8	/* create total count for VA only */

#define PRF_FLGBITS	0x40	/* has a flgbits structure (?) */
#define PRF_WRAP	0x80	/* don't use: if hit table full, wrap */
				/* there is a bug in kernel, which */
				/* prevents this from correct working! */

/* status bits, don't ever set these (won't work, not masked, bug!) */
#define PRFS_RUNNING	0x100	/* profiling is active */
#define PRFS_THRDS	0x200	/* also profiling threads */
#define PRFS_HITOVFL	0x800	/* overflow in hit buffer */
#define PRFS_HEADER	0x1000	/* internally used */

	ULONG	cm_bufsz;	/* reserve # of bytes for buffers */
				/* e.g. for hit buffer or detailed */
				/* counters */
	USHORT	cm_timval;	/* timer resolution */
				/* if 0, use default == 1000 */
	/* valid if PRF_FLAGBITS set */
	PUCHAR	cm_flgbits;	/* vector of flag bits (?) */
	UCHAR	cm_nflgs;	/* # of flag bits >= 2 if present */
} PRFCMD;	/* 19 bytes */

typedef struct {
	ULONG	sl_vaddr;	/* start of VA segment to profile */
	ULONG	sl_size;	/* length of VA segment */
	ULONG	sl_mode;	/* !=0 use PRF_VA* flags, */
				/* =0, simple count */
} PRFSLOT;
profret:
typedef struct {
	UCHAR	us_cmd;		/* command */
#define PRF_RET_GLOBAL	0	/* return global data */
				/* set us_thrdno for specific thread */
				/* us_buf = struct PRFRET0 */
#define	PRF_RET_VASLOTS	1	/* return VA slot data (PRFRET1) */
#define PRF_RET_VAHITS	2	/* return hit table (PRFRET2) */
#define PRF_RET_VADETAIL 3	/* return detailed counters (PRFRET3) */
				/* specify us_vaddr */

	USHORT	us_thrdno;	/* thread requested for cmd=0 */
	ULONG	us_vaddr;	/* VA for cmd=3*/
	ULONG	us_bufsz;	/* length of return buffer */
	VOID	*us_buf;	/* return buffer */
} PRFRET;	/* 15 bytes */

typedef struct {
	USHORT	r0_flags;	/* profile flags */
				/* see PRF_* defines */
	USHORT	r0_shift;	/* shift factor */
				/* 2^N = length of a segment for */
				/* detailed counters */
	ULONG	r0_idle;	/* count if process is idle */
	ULONG	r0_vm86;	/* count if process is in VM mode */
	ULONG	r0_kernel;	/* count if process is in kernel */
	ULONG	r0_shrmem;	/* count if process is in shr mem */
	ULONG	r0_unknown;	/* count if process is elsewhere */
	ULONG	r0_nhitbufs;	/* # of dwords in hitbufs */
	ULONG	r0_hitbufcnt;	/* # of entries in hit table */
	ULONG	r0_reserved1;	/* internally used */
	ULONG	r0_reserved2;	/* internally used */
	USHORT	r0_timval;	/* timer resolution */
	UCHAR	r0_errcnt;	/* error count */
	USHORT	r0_nstruc1;	/* # of add structures 1 (?) */
	USHORT	r0_nstruc2;	/* # of add structures 2 (?) */
} PRFRET0;

typedef struct {
	UCHAR	r1_nslots;	/* # of slots (bug: prevents */
				/* correct # if #slots >255) */
	PRFVA	r1_slots[1];	/* slots */
} PRFRET1;

typedef struct {
	ULONG	r2_nhits;	/* # of entries in table */
	ULONG	r2_hits[1];	/* hit table */
} PRFRET2;

typedef struct {
	ULONG	r3_size;	/* size of segment */
	ULONG	r3_ncnts;	/* # of entries in table */
	ULONG	r3_cnts[1];	/* counters */
} PRFRET3;

typedef struct {
	ULONG	va_vaddr;	/* virtual address of segment */
	ULONG	va_size;	/* length of segment */
	ULONG	va_flags;	/* == 8, va_cnt is valid */
	ULONG	va_reserved;	/* internally used */
	ULONG	va_cnt;		/* profile count */
} PRFVA;

Notes

  1. Profiling is based on VA (virtual address) segments. The profiler can operate in the following modes:
  2. all structures are byte aligned and packed
  3. Several bugs in the logic seem to prevent certain functions.
  4. Apparently only one process may be profiled at a time, due to a difficulty of sharing the global internal _pmb structure.
  5. the flgbits structure seems to be a strange kind of clock divider: if there are flgbits, the profiling routine is only called from the profile interrupt, if the one of the bytes decrements to 0, e.g. flgbits[] = { 5,6,7,8 } profiling data will be accumulated after tick 8, 15, 21, 26, 34, 41, 47, 52,... I have no idea why this is available.

This page was accessed times since Jan 25th, 1996


Reply to: Holger.Veit@gmd.de