⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 profile.c

📁 See Hanoi.cpp for the implementation of this cla
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved.

Module Name:  profile.c

Abstract:  
 This file implements the NK kernel profiler support

Functions:


Notes: 

--*/
#define C_ONLY
#include "kernel.h"	   
#include "romldr.h"
#include "xtime.h"

#define NUM_SYMBOLS 500					// max number of symbols to display in report

#define PROFILEMSG(cond,printf_exp)   \
   ((cond)?(NKDbgPrintfW printf_exp),1:0)

extern BOOL bProfileBuffer;				// profiling to buffer flag

										// platform routine to disable profiler timer
extern void OEMProfileTimerDisable(void);
										// platform routine to enable profiler timer
extern void OEMProfileTimerEnable(DWORD dwUSec);

typedef struct {
    DWORD ra;                           // Interrupt program counter
    TOCentry * pte;
} PROFBUFENTRY, *PPROFBUFENTRY;

#define ENTRIES_PER_PAGE    (PAGE_SIZE / sizeof(PROFBUFENTRY))

//
// The number of bits to shift is a page shift - log2(sizeof(PROFBUFENTRY))
//
#if PAGE_SIZE == 4096
  #define PROF_PAGE_SHIFT       9
#elif PAGE_SIZE == 2048
  #define PROF_PAGE_SHIFT       8
#elif PAGE_SIZE == 1024
  #define PROF_PAGE_SHIFT       7
#else
  #error "Unsupported Page Size"
#endif

#define PROF_ENTRY_MASK       ((2 << PROF_PAGE_SHIFT) - 1)

PDWORD g_pdwProfileBufStart;            // platform profile buffer start
HANDLE g_hProfileBuf;

DWORD dwProfileCount;					// total number of profiler calls
DWORD  dwPerProcess;					// per process profiling flag
void ClearProfileHits(void);			// clear all profile counters

#define PROFILE_BUFFER_MAX   4096*1024
#define PAGES_IN_MAX_BUFFER    PROFILE_BUFFER_MAX/PAGE_SIZE

PPROFBUFENTRY g_pPBE[PAGES_IN_MAX_BUFFER];
DWORD  dwBufNumPages;              // Total number of pages
DWORD  dwBufNumEntries;            // Total number of entries
DWORD  dwBufRecDropped;            // How many hits were not recorded?

/*
 *	ProfilerHit - record profiler interrupt call address
 *
 *	Input:	ra - interrupt return address
 *			tocexeptr - pCurProf.oe->tocexeptr at time of interrupt
 *
 *	Attempts to find symbol address for the interrupt call address and increments
 *  hit counts for module and symbol if found.
 */
void ProfilerSymbolHit(unsigned int ra, TOCentry *tocexeptr) {
	TOCentry 	*tocptr;				// table of contents entry pointer
	PROFentry	*profptr=NULL;			// profile entry pointer
	SYMentry	*symptr;				// profiler symbol entry pointer
	unsigned int iMod;					// module enty in TOC
	unsigned int iSym;					// symbol counter
    SYMentry    *pClosestSym;           // nearest symbol entry found

	if (ra & 0x80000000) {				// if high bit set, this is NK
		ra&=0xdfffffff;					// mask off uncached bit
										// profptr-> first entry= NK
		profptr= (PROFentry *)pTOC->ulProfileOffset;
										// if ra >= pTOC->dllfirst, the hit
										// is in a dll in the ROM
	}else if ((unsigned int)ra >= (unsigned int)pTOC->dllfirst) {
		profptr= (PROFentry *)pTOC->ulProfileOffset+1;
										// skip exe's which start at 0x10000
										// dll's are stored in descending addresses
		while (profptr->ulStartAddr == 0 || profptr->ulStartAddr == 0x10000 || (unsigned int)ra<(unsigned int)profptr->ulStartAddr)
			profptr++;
	} else {							// this is an exe in the ROM, something 
										// loaded in RAM or unknown
		tocptr=(TOCentry *)(pTOC+1);	// tocptr-> first entry in ROM
		if (tocexeptr < tocptr) {		// if tocexeptr at interrupt time < first entry
			return;						// we don't know what this is
		}
										// compute module number
		iMod= ((DWORD)tocexeptr-(DWORD)tocptr)/sizeof(TOCentry);
		if (!iMod) {
			return;
		}
		if (iMod > pTOC->nummods) {		// if module > number of modules in ROM
			return;						// this was loaded in RAM
		}
										// make profptr point to entry for this module
		profptr= (PROFentry *)pTOC->ulProfileOffset;
		profptr+=iMod;
	}

	profptr->ulHits++;					// increment hits for this module
	if (profptr->ulNumSym) {
		// look up the symbol if module found
		iSym= profptr->ulNumSym-1;
		symptr=(SYMentry*)profptr->ulHitAddress;
        pClosestSym = symptr;
            
        // Scan the whole list of symbols, looking for the closest match.
        while (iSym) {
            // Keep track of the closest symbol found
            if (((unsigned int)symptr->ulFuncAddress <= ra)
                && (symptr->ulFuncAddress > pClosestSym->ulFuncAddress)) {
                pClosestSym = symptr;
            }
            
            iSym--;
            symptr++;
        }
        
        pClosestSym->ulFuncHits++;		// inc hit count for this symbol
	}
	return;
}

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
ProfilerFreeBuffer(void)
{
    DWORD dwMemSize;
    BOOL fRet;

    dwMemSize = dwBufNumPages * PAGE_SIZE;

    fRet = SC_UnlockPages(g_pdwProfileBufStart, dwMemSize);
    ASSERT(fRet);
    fRet = UnmapViewOfFile(g_pdwProfileBufStart);
    ASSERT(fRet);
    fRet = CloseHandle(g_hProfileBuf);
    ASSERT(fRet);
    
    return TRUE;
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
BOOL
ProfilerAllocBuffer(void)
{
    DWORD dwMemRequest;
    BOOL fRet;
    DWORD i;

    //
    // Determine half the free RAM.
    //
    dwMemRequest = (UserKInfo[KINX_PAGEFREE] * PAGE_SIZE) / 2;
    //
    // Make an upper limit.
    //
    if (dwMemRequest > PROFILE_BUFFER_MAX) {
        dwMemRequest = PROFILE_BUFFER_MAX;
    }
    dwBufNumPages   = dwMemRequest / PAGE_SIZE;
    dwBufNumEntries = dwBufNumPages * ENTRIES_PER_PAGE;

    //
    // Create a shared memory-mapped object
    //
    g_hProfileBuf = CreateFileMapping((HANDLE) -1, NULL, 
                                     PAGE_READWRITE | SEC_COMMIT, 0,
                                     dwMemRequest, NULL);
    if (!g_hProfileBuf) {
        goto EXIT_FALSE;
    }
    
    // Map in the object
    g_pdwProfileBufStart = (PDWORD) MapViewOfFile(g_hProfileBuf, FILE_MAP_ALL_ACCESS, 0, 0, 0);

    if (g_pdwProfileBufStart == NULL) {
        CloseHandle(g_hProfileBuf);
        goto EXIT_FALSE;
    }

    //
    // Lock the pages and get the physical addresses.
    //
    fRet = SC_LockPages(g_pdwProfileBufStart, dwMemRequest, (PDWORD) g_pPBE, LOCKFLAG_READ | LOCKFLAG_WRITE);

    //
    // Convert the physical addresses to statically-mapped virtual addresses
    //
    for (i = 0; i < dwBufNumPages; i++) {
        g_pPBE[i] = Phys2Virt((DWORD) g_pPBE[i]);
    }

    if (fRet == FALSE) {
        UnmapViewOfFile(g_pdwProfileBufStart);
        CloseHandle(g_hProfileBuf);
        goto EXIT_FALSE;
    }

    PROFILEMSG(1, (TEXT("ProfileStart() : Allocated %d kB for Profiler Buffer (0x%08X)\r\n"), dwMemRequest >> 10, g_pdwProfileBufStart));
    return TRUE;
    
EXIT_FALSE:
    PROFILEMSG(1, (TEXT("ProfileStart() : Error allocating buffer... defaulting to symbol lookup in ISR.\r\n")));
    return FALSE;
}



//------------------------------------------------------------------------------
//
// Takes a raw index and looks up the tiered entry pointer.
//
//------------------------------------------------------------------------------
PPROFBUFENTRY
GetEntryPointer(
    DWORD dwIndex
    )
{
    DWORD dwPage, dwEntry;

    dwPage  = dwIndex >> PROF_PAGE_SHIFT;
    dwEntry = dwIndex & PROF_ENTRY_MASK;

    return (&(g_pPBE[dwPage][dwEntry]));
}



/*
 *	ProfilerHit - OEMProfilerISR calls this routine to record profile hit
 *
 *	Input:	ra - interrupt return address
 *
 *	if buffer profiling, save ra and pCurProc->oe.tocptr in buffer
 *	else do symbol lookup in ISR
 */
void ProfilerHit(unsigned int ra) {
    PPROFBUFENTRY pEntry;

    if (bProfileBuffer) {           
        //
        // If profiling to buffer and these is still room in the buffer
        //
        if (dwProfileCount < dwBufNumEntries) {
            
            if (ra & 0x80000000)    // if high bit set, this is NK
                ra &= 0xdfffffff;     // mask off uncached bit
            

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -