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

📄 profiler.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    } while ((dwNumFrames == PROFILER_MAX_STACK_FRAME)
             && (KGetLastError(pCurThread) == ERROR_INSUFFICIENT_BUFFER));

    // Restore thread LastError
    KSetLastError(pCurThread, dwLastError);

    return TRUE;
}
#endif  // defined(x86)


#endif  // NKPROF


//------------------------------------------------------------------------------
//  GetEPC - Get exception program counter
//
//  Output: returns EPC, zero if cpu not supported
//------------------------------------------------------------------------------
DWORD GetEPC(void) {
#if defined(x86) && defined(NKPROF)
    extern PTHREAD pthFakeStruct;
    PTHREAD pTh;

    if (KData.cNest < 0) {
        pTh = pthFakeStruct;
    } else {
        pTh = pCurThread;
    }
    return(GetThreadIP(pTh));

#elif defined(ARM)

    // -- NOT SUPPORTED ON ARM --
    // The address is not saved to the thread context on ARM, so GetEPC
    // cannot be used within an ISR.  Instead use the "ra" value that is
    // passed to OEMInterruptHandler.
    return 0;
 
#else

    return(GetThreadIP(pCurThread));

#endif
}


//------------------------------------------------------------------------------
// 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
    ) 
{
#ifdef NKPROF
    OEMProfilerData data;

    data.ra = ra;
    data.dwBufSize = 0;

        ProfilerHitEx(&data);
#endif // NKPROF
}


//------------------------------------------------------------------------------
// ProfilerHitEx - Generalized version of ProfilerHit.  A hardware-specific
// profiler ISR calls this routine to record a buffer of profiling data.
// No lookups done during this routine -- just copy the data into a buffer and
// return.
// Input:  pData - OEM-specified buffer of profiling information (RA may be fixed up)
//------------------------------------------------------------------------------
void 
ProfilerHitEx(
    OEMProfilerData *pData
    ) 
{
#ifdef NKPROF

    if (!RunList.pth && !RunList.pRunnable) {  // IDLE
        // CeLog should record idle hits, but other modes should just
        // increment a counter and exit.
        g_ProfilerState_dwSamplesInIdle++;
        if (!(g_dwProfilerFlags & PROFILE_CELOG)) {
            return;
        }
        pData->ra = (DWORD) IDLE_STATE;
    }
    
    if (g_dwProfilerFlags & PROFILE_CELOG) {
        if (IsCeLogStatus(CELOGSTATUS_ENABLED_PROFILE)) {
            // Fixup RA
            if (IsKernelVa(pData->ra)) {     // if high bit set, this is NK
                pData->ra &= 0xdfffffff;     // mask off uncached bit
            } else {
                pData->ra = (DWORD)MapPtrProc(pData->ra, pCurProc);
            }

            // Send data to celog
            if (g_dwProfilerFlags & PROFILE_OEMDEFINED) {
                g_pfnCeLogData(FALSE, CELID_OEMPROFILER_HIT, pData,
                               pData->dwBufSize + 2*sizeof(DWORD),  // dwBufSize does not include header; can't use sizeof(OEMProfilerData) because the 0-byte array has nonzero size
                               0, CELZONE_PROFILER, 0, FALSE);
            } else {
                g_pfnCeLogData(FALSE, CELID_MONTECARLO_HIT, &(pData->ra), sizeof(DWORD), 0,
                               CELZONE_PROFILER, 0, FALSE);
            }
        
#if defined(x86)  // Callstack capture is only supported on x86 right now
            // Send call stack data if necessary
            if ((g_dwProfilerFlags & PROFILE_CALLSTACK)
                && (RunList.pth || RunList.pRunnable)   // Not IDLE_STATE - idle has no stack
                && !(KData.cNest < 0)) {                // Not a nested interrupt or KCall - no way to get stack in those cases?
                LogCallStack();
            }
#endif
        }
        
    } else if (g_dwProfilerFlags & (PROFILE_BUFFER)) {
        //
        // If profiling to buffer and there is still room in the buffer
        //
        if (g_ProfilerState_dwSamplesRecorded < g_dwProfileBufNumEntries) {
            PPROFBUFENTRY pEntry;

            if (IsKernelVa(pData->ra))       // if high bit set, this is NK
                pData->ra &= 0xdfffffff;     // mask off uncached bit
  
            pEntry = GetEntryPointer(g_ProfilerState_dwSamplesRecorded);
            g_ProfilerState_dwSamplesRecorded++;
            //
            // Record an entry point
            //
            pEntry->ra = pData->ra;
            pEntry->pte = pCurProc->oe.tocptr;
        } else {
            //
            // No place to record this hit. Let's remember how many we dropped.
            //
            g_ProfilerState_dwSamplesDropped++;
            PROFILEMSG(ZONE_UNACCOUNTED, (TEXT("Hit dropped (buffer full), ra=0x%08x\r\n"), pData->ra));
        }

    } else {
        // No buffer. Just lookup the symbol now.
        //
        g_ProfilerState_dwSamplesRecorded++;
        ProfilerSymbolHit(pData->ra, pCurProc->oe.tocptr);
    }

#endif // NKPROF
}


//------------------------------------------------------------------------------
// SC_ProfileSyscall - Turns profiler on and off.  The workhorse behind
// ProfileStart(), ProfileStartEx(), ProfileStop() and ProfileCaptureStatus().
//------------------------------------------------------------------------------
void 
SC_ProfileSyscall(
    DWORD* lpdwArg
    )
{
#ifdef NKPROF
    static int   scPauseContinueCalls = 0;
    static BOOL  bStart = FALSE;
    static DWORD dwCeLogZoneUser, dwCeLogZoneCE, dwCeLogZoneProcess;
    const ProfilerControl* pControl = (const ProfilerControl*) lpdwArg;

    if (pControl
        && (pControl->dwVersion == 1)
        && (pControl->dwReserved == 0)) {

        if (pControl->dwOptions & PROFILE_START) {
            // ProfileStart() / ProfileStartEx()

            if (pControl->dwOptions & PROFILE_CONTINUE) {
                if (bStart && ((g_dwProfilerFlags & (PROFILE_OBJCALL | PROFILE_KCALL)) == 0)) {
                    ++scPauseContinueCalls;
                    // Start profiler timer on 0 to 1 transition
                    if (1 == scPauseContinueCalls) {
                        if (g_dwProfilerFlags & PROFILE_OEMDEFINED) {
                            // OEM-specific profiler
                            OEMIoControl(IOCTL_HAL_OEM_PROFILER,
                                         (ProfilerControl*) pControl,  // non-const
                                         sizeof(ProfilerControl) + pControl->OEM.dwControlSize,
                                         NULL, 0, NULL);

                        } else {
                            // Monte Carlo profiling
                            
                            // Set system state counters to running (total) values
                            g_ProfilerState_dwTLBCount  = dwCeLogTLBMiss - g_ProfilerState_dwTLBCount;
                            g_ProfilerState_dwTickCount = GetTickCount() - g_ProfilerState_dwTickCount;

                            OEMProfileTimerEnable(pControl->Kernel.dwUSecInterval);
                            bProfileTimerRunning = TRUE;
                        }
                    }
                }
            
            } else if (pControl->dwOptions & PROFILE_PAUSE) {
                if (bStart && ((g_dwProfilerFlags & (PROFILE_OBJCALL | PROFILE_KCALL)) == 0)) {
                    --scPauseContinueCalls;
                    // Stop profiler timer on 1 to 0 transition
                    if (!scPauseContinueCalls) {
                        if (g_dwProfilerFlags & PROFILE_OEMDEFINED) {
                            // OEM-specific profiler
                            OEMIoControl(IOCTL_HAL_OEM_PROFILER,
                                         (ProfilerControl*) pControl,  // non-const
                                         sizeof(ProfilerControl) + pControl->OEM.dwControlSize,
                                         NULL, 0, NULL);
                        } else {
                            // Monte Carlo profiling
                            OEMProfileTimerDisable();
                            bProfileTimerRunning = FALSE;

                            // Set system state counters to paused (elapsed) values
                            g_ProfilerState_dwTLBCount  = dwCeLogTLBMiss - g_ProfilerState_dwTLBCount;
                            g_ProfilerState_dwTickCount = GetTickCount() - g_ProfilerState_dwTickCount;
                        }
                    }
                }
            
            } else {
                // Protect against multiple starts
                if (bStart) {
                    PROFILEMSG(1, (TEXT("Kernel Profiler: Ignoring multiple profiler starts\r\n")));
                    return;
                }
                
                // Protect against running a profiling kernel on an unprofiled image
                if (((pTOC->ulProfileLen == 0) || (pTOC->ulProfileOffset == 0))
                    && ((pControl->dwOptions & PROFILE_CELOG) == 0)) { // Allow profiling with celog even if no symbols
                    PROFILEMSG(1, (TEXT("Kernel Profiler: Unable to start, PROFILE=OFF in config.bib!\r\n")));
                    return;
                }
                
                // Pre-compute information about all of the XIP regions for
                // faster access while profiling
                if ((g_dwNumROMModules == 0) || (g_dwFirstROMDLL == 0)) {
                    ROMChain_t *pROM = ROMChain;
                    g_dwFirstROMDLL = (DWORD)-1;
                    while (pROM) {
                        // Figure out the module index (wrt first XIP region) of nk.exe
                        // NK is the first module of the pTOC
                        if (pROM->pTOC == pTOC) {
                            g_dwNKIndex = g_dwNumROMModules;
                        }
                        
                        // Count the total number of modules
                        g_dwNumROMModules += pROM->pTOC->nummods;
                        
                        // Find the lowest ROM DLL address
                        if (pROM->pTOC->dllfirst < g_dwFirstROMDLL) {
                            g_dwFirstROMDLL = pROM->pTOC->dllfirst;
                        }
                        pROM = pROM->pNext;
                    }
                    DEBUGCHK(g_dwFirstROMDLL != (DWORD)-1);
                }

                if ((pControl->dwOptions & PROFILE_CELOG) && !IsCeLogStatus(CELOGSTATUS_ENABLED_ANY)) {
                    PROFILEMSG(1, (TEXT("Kernel Profiler: Unable to start, CeLog is not loaded!\r\n")));
                    return;
                }

                // Debug output so the user knows exactly what's going on
                if (pControl->dwOptions & PROFILE_KCALL) {
                    PROFILEMSG(1, (TEXT("Kernel Profiler: Gathering KCall data\r\n")));
                } else {
                    PROFILEMSG(1, (TEXT("Kernel Profiler: Gathering %s data in %s mode\r\n"),
                                   (pControl->dwOptions & PROFILE_OEMDEFINED) ? TEXT("OEM-Defined")
                                       : (pControl->dwOptions & PROFILE_OBJCALL) ? TEXT("ObjectCall")
                                       : TEXT("MonteCarlo"),
                                   (pControl->dwOptions & PROFILE_CELOG) ? TEXT("CeLog")
                                       : ((pControl->dwOptions & PROFILE_BUFFER) ? TEXT("buffered")
                                       : TEXT("unbuffered"))));
                }
                
                
                OEMProfileTimerDisable();   // disable profiler timer
                bProfileTimerRunning = FALSE;
                bStart = TRUE;
                ++scPauseContinueCalls;

                ClearProfileHits();         // reset all profile counts
                
                g_dwProfilerFlags = 0;

                //
                // Determine the storage mode for the data
                //
                if (pControl->dwOptions & PROFILE_CELOG) {

                                        
                    // Disable CeLog general logging; log only profile events
                    CeLogEnableStatus(CELOGSTATUS_ENABLED_PROFILE);

                    // Make sure the correct zones are turned on; save the
                    // old zone settings to restore later
                    SC_CeLogGetZones(&dwCeLogZoneUser, &dwCeLogZoneCE,
                                     &dwCeLogZoneProcess, NULL);
                    SC_CeLogSetZones(0xFFFFFFFF, CELZONE_PROFILER, 0xFFFFFFFF);
                    SC_CeLogReSync();

                    // Log the start event
                    if (pControl->dwOptions & PROFILE_OEMDEFINED) {
                        g_pfnCeLogData(TRUE, CELID_PROFILER_START, pControl,
                                       sizeof(ProfilerControl) + pControl->OEM.dwControlSize, 0,
                                       CELZONE_PROFILER, 0, FALSE);
                    } else {
                        g_pfnCeLogData(TRUE, CELID_PROFILER_START, pControl,
                                       sizeof(ProfilerControl), 0,
                                       CELZONE_PROFILER, 0, FALSE);
                    }

⌨️ 快捷键说明

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