📄 profile.c
字号:
/*++THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OFANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TOTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR APARTICULAR PURPOSE.Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved.Module Name: profile.cAbstract: This file implements the NK kernel profiler supportFunctions: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 timerextern void OEMProfileTimerDisable(void); // platform routine to enable profiler timerextern 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 startHANDLE g_hProfileBuf;DWORD dwProfileCount; // total number of profiler callsDWORD dwPerProcess; // per process profiling flagvoid ClearProfileHits(void); // clear all profile counters#define PROFILE_BUFFER_MAX 4096*1024#define PAGES_IN_MAX_BUFFER PROFILE_BUFFER_MAX/PAGE_SIZEPPROFBUFENTRY g_pPBE[PAGES_IN_MAX_BUFFER];DWORD dwBufNumPages; // Total number of pagesDWORD dwBufNumEntries; // Total number of entriesDWORD 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;}//------------------------------------------------------------------------------//------------------------------------------------------------------------------BOOLProfilerFreeBuffer(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;}//------------------------------------------------------------------------------//------------------------------------------------------------------------------BOOLProfilerAllocBuffer(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.////------------------------------------------------------------------------------PPROFBUFENTRYGetEntryPointer( 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 + -