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

📄 profiler.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:

                    g_dwProfilerFlags |= PROFILE_CELOG;

#if defined(x86)  // Callstack capture is only supported on x86 right now
                    // CALLSTACK flag can only be used with CeLog & Monte Carlo right now
                    if ((pControl->dwOptions & PROFILE_CALLSTACK)
                        && !(pControl->dwOptions & (PROFILE_OBJCALL | PROFILE_KCALL))) {

                        g_dwProfilerFlags |= PROFILE_CALLSTACK;

                        // INPROC flag modifies the callstack flag
                        if (pControl->dwOptions & PROFILE_CALLSTACK_INPROC) {
                            g_dwProfilerFlags |= PROFILE_CALLSTACK_INPROC;
                        }
                    }
#endif  // defined(x86)

                } else if (pControl->dwOptions & PROFILE_BUFFER) {
                    // Attempt to alloc the buffer; skip buffering if the alloc fails
                    if (ProfilerAllocBuffer()) {
                        g_dwProfilerFlags |= PROFILE_BUFFER;
                    }
                }
                
                
                // Determine which type of data is being gathered
                if (pControl->dwOptions & PROFILE_OEMDEFINED) {
                    // OEM-specific profiler
                    if ((pControl->dwOptions & (PROFILE_OBJCALL | PROFILE_KCALL))
                        || !OEMIoControl(IOCTL_HAL_OEM_PROFILER,
                                         (ProfilerControl*) pControl,  // non-const
                                         sizeof(ProfilerControl) + pControl->OEM.dwControlSize,
                                         NULL, 0, NULL)) {
                        PROFILEMSG(1, (TEXT("Kernel Profiler: OEM Profiler start failed!\r\n")));
                        SetLastError(ERROR_NOT_SUPPORTED);
                        // Restore CeLog state
                        if (IsCeLogStatus(CELOGSTATUS_ENABLED_ANY)) {
                            SC_CeLogSetZones(dwCeLogZoneUser, dwCeLogZoneCE, dwCeLogZoneProcess);
                            CeLogEnableStatus(CELOGSTATUS_ENABLED_GENERAL);
                        }
                        g_dwProfilerFlags = 0;
                        bStart = FALSE;
                        return;
                    }
                    g_dwProfilerFlags |= PROFILE_OEMDEFINED;

                } else if (pControl->dwOptions & PROFILE_OBJCALL) {
                    // Object call profiling
                    g_dwProfilerFlags |= PROFILE_OBJCALL;
                
                } else if (pControl->dwOptions & PROFILE_KCALL) {
                    // Kernel call profiling
                    g_dwProfilerFlags |= PROFILE_KCALL;
                
                } else {
                    // Monte Carlo profiling
                    
                    // Initialize the system state counters that will not run
                    // whenever profiling is paused
                    g_ProfilerState_dwInterrupts = 0;
                    g_ProfilerState_dwProfilerIntsInTLB = 0;

                    if (pControl->dwOptions & PROFILE_STARTPAUSED) {
                        --scPauseContinueCalls;
                        
                        // Set elapsed values for system counters that will
                        // continue to run whenever profiling is paused
                        // (paused now)
                        g_ProfilerState_dwTLBCount  = 0;
                        g_ProfilerState_dwTickCount = 0;
                    } else {
                        // Set start values for system counters that will
                        // continue to run whenever profiling is paused
                        // (running now)
                        g_ProfilerState_dwTLBCount  = dwCeLogTLBMiss;
                        g_ProfilerState_dwTickCount = GetTickCount();
                        
                        // Start profiler timer
                        OEMProfileTimerEnable(pControl->Kernel.dwUSecInterval);
                        bProfileTimerRunning = TRUE;
                    }
                }
            }
        
        } else if (pControl->dwOptions & PROFILE_STOP) {
            // ProfileStop()
            
            if (bProfileTimerRunning) {
                OEMProfileTimerDisable();   // disable profiler timer
                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 if (g_dwProfilerFlags & PROFILE_OEMDEFINED) {
                // OEM-specific profiler
                ProfilerControl control;
                control.dwVersion = 1;
                control.dwOptions = PROFILE_STOP | PROFILE_OEMDEFINED;
                control.dwReserved = 0;
                control.OEM.dwControlSize = 0;    // no OEM struct passed to stop profiler
                control.OEM.dwProcessorType = 0;                  OEMIoControl(IOCTL_HAL_OEM_PROFILER, &control,
                             sizeof(ProfilerControl), NULL, 0, NULL);
                g_dwProfilerFlags &= ~PROFILE_OEMDEFINED;
            }

            scPauseContinueCalls = 0;
            
            if (g_dwProfilerFlags & PROFILE_CELOG) {
                // Resume general logging
                if (IsCeLogStatus(CELOGSTATUS_ENABLED_ANY)) {
                    // Log the stop event
                    g_pfnCeLogData(TRUE, CELID_PROFILER_STOP, NULL, 0, 0,
                                   CELZONE_PROFILER, 0, FALSE);
                    
                    // Restore the original zone settings
                    SC_CeLogSetZones(dwCeLogZoneUser, dwCeLogZoneCE, dwCeLogZoneProcess);

                    // Restore CeLog general logging
                    CeLogEnableStatus(CELOGSTATUS_ENABLED_GENERAL);
                }
                g_dwProfilerFlags &= ~(PROFILE_CELOG | PROFILE_CALLSTACK | PROFILE_CALLSTACK_INPROC);
                
                // The Monte Carlo report header can still be printed, though
                // the full report must be generated by desktop tools that parse
                // the log
                PROFILEMSG(1, (TEXT("Profiler data written to CeLog.\r\n")));
                if (!(g_dwProfilerFlags & PROFILE_OBJCALL)) {
                    ProfilerReportHeader();
                    PROFILEMSG(1, (TEXT("\r\nMODULES:  Written to CeLog\r\n")));
                    PROFILEMSG(1, (TEXT("\r\nSYMBOLS:  Written to CeLog\r\n")));
                }
            
            } else if (g_dwProfilerFlags & PROFILE_KCALL) {
                // Dump the KCall profile data
                SC_DumpKCallProfile(TRUE);
                g_dwProfilerFlags &= ~PROFILE_KCALL;
            
            } else {
                // Display profile hit report
                ProfilerReport();
            }
        
            if (g_dwProfilerFlags & PROFILE_BUFFER) {
                ProfilerFreeBuffer();
                g_dwProfilerFlags &= ~PROFILE_BUFFER;
            }

            g_dwProfilerFlags = 0;
            bStart = FALSE;
        
        } else if (pControl->dwOptions & PROFILE_OEM_QUERY) {
            // ProfileCaptureStatus()
            // Insert the current state of the OEM-defined profiler into the
            // CeLog data stream
            BYTE  Buf[1024];              DWORD dwBufSize = 1024;
            DWORD dwBufUsed;
            
            // Only supported via CeLog for now
            if ((g_dwProfilerFlags & PROFILE_OEMDEFINED)
                && (g_dwProfilerFlags & PROFILE_CELOG)
                && IsCeLogStatus(CELOGSTATUS_ENABLED_PROFILE)) {

                ProfilerControl control;
                control.dwVersion = 1;
                control.dwOptions = PROFILE_OEM_QUERY | PROFILE_OEMDEFINED;
                control.dwReserved = 0;
                control.OEM.dwControlSize = 0;    // no OEM struct being passed here
                control.OEM.dwProcessorType = 0;                  if (OEMIoControl(IOCTL_HAL_OEM_PROFILER, &control,
                                 sizeof(ProfilerControl), Buf, dwBufSize,
                                 &dwBufUsed)) {

                    // Clear the RA since it does not apply when the data is just being queried
                    ((OEMProfilerData*)Buf)->ra = 0;
        
                    // Now that we have the data, send it to CeLog
                    g_pfnCeLogData(FALSE, CELID_OEMPROFILER_HIT, Buf, dwBufUsed, 0,
                                   CELZONE_PROFILER, 0, FALSE);
                }
            }
        }
    }
#endif // NKPROF
}



//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
SC_TurnOnProfiling(void)
{
    DEBUGMSG(ZONE_ENTRY,(L"SC_TurnOnProfiling entry\r\n"));
    SET_PROFILE(pCurThread);
#if SHx
    ProfileFlag = 1;    // profile status
#endif
    DEBUGMSG(ZONE_ENTRY,(L"SC_TurnOnProfiling exit\r\n"));
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
SC_TurnOffProfiling(void)
{
    DEBUGMSG(ZONE_ENTRY,(L"SC_TurnOffProfiling entry\r\n"));
    CLEAR_PROFILE(pCurThread);
#if SHx
    ProfileFlag = 0;    // profile status
#endif
    DEBUGMSG(ZONE_ENTRY,(L"SC_TurnOffProfiling exit\r\n"));
}


#ifdef KCALL_PROFILE

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
GetKCallProfile(
    KPRF_t *pkprf,
    int loop,
    BOOL bReset
    )
{
    KCALLPROFON(26);
    memcpy(pkprf,&KPRFInfo[loop],sizeof(KPRF_t));
    if (bReset && (loop != 26))
        memset(&KPRFInfo[loop],0,sizeof(KPRF_t));
    KCALLPROFOFF(26);
    if (bReset && (loop == 26))
        memset(&KPRFInfo[loop],0,sizeof(KPRF_t));
}

#endif // KCALL_PROFILE


//
// Convert the number of ticks to microseconds.
//

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static DWORD 
local_ScaleDown(
    DWORD dwIn
    )
{
    LARGE_INTEGER liFreq;

    SC_QueryPerformanceFrequency(&liFreq);

    return ((DWORD) (((__int64) dwIn * 1000000) / liFreq.LowPart));
}


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void 
SC_DumpKCallProfile(
    DWORD bReset
    )
{
#ifdef KCALL_PROFILE
    extern DWORD local_ScaleDown(DWORD);
    int loop;
    KPRF_t kprf;
    DWORD min = 0xffffffff, max = 0, total = 0, calls = 0;

    TRUSTED_API_VOID (L"SC_DumpKCallProfile");
#ifdef NKPROF
    calls = local_ScaleDown(1000);
    PROFILEMSG(1, (L"Resolution: %d.%3.3d usec per tick\r\n", calls / 1000, calls % 1000));
    KCall((PKFN)GetKCallProfile, &kprf, KCALL_NextThread, bReset);
    PROFILEMSG(1, (L"NextThread: Calls=%u Min=%u Max=%u Ave=%u\r\n",
        kprf.hits, local_ScaleDown(kprf.min),
        local_ScaleDown(kprf.max), kprf.hits ? local_ScaleDown(kprf.total) / kprf.hits : 0));
    for (loop = 0; loop < MAX_KCALL_PROFILE; loop++) {
        if (loop != KCALL_NextThread) {
            KCall((PKFN)GetKCallProfile, &kprf, loop, bReset);
            if (kprf.max > max)
                max = kprf.max;
            total += kprf.total;
            calls += kprf.hits;
        }
    }
    PROFILEMSG(1, (L"Other Kernel calls: Max=%u Avg=%u\r\n", max, calls ? local_ScaleDown(total) / calls : 0));
#else  // NKPROF
    calls = local_ScaleDown(1000);
    PROFILEMSG(1, (L"Resolution: %d.%3.3d usec per tick\r\n", calls / 1000, calls % 1000));
    PROFILEMSG(1, (L"Index Entrypoint                        Calls      uSecs    Min    Max    Ave\r\n"));
    for (loop = 0; loop < MAX_KCALL_PROFILE; loop++) {
        KCall((PKFN)GetKCallProfile, &kprf, loop, bReset);
        PROFILEMSG(1, (L"%5d %-30s %8d %10d %6d %6d %6d\r\n",
            loop, pKCallName[loop], kprf.hits, local_ScaleDown(kprf.total), local_ScaleDown(kprf.min),
            local_ScaleDown(kprf.max), kprf.hits ? local_ScaleDown(kprf.total) / kprf.hits : 0));
        if (kprf.min && (kprf.min < min))
            min = kprf.min;
        if (kprf.max > max)
            max = kprf.max;
        calls += kprf.hits;
        total += kprf.total;
    }
    PROFILEMSG(1, (L"\r\n"));
    PROFILEMSG(1, (L"      %-30s %8d %10d %6d %6d %6d\r\n",
        L"Summary", calls, local_ScaleDown(total), local_ScaleDown(min), local_ScaleDown(max),calls ? local_ScaleDown(total) / calls : 0));
#endif  // NKPROF
#endif  // KCALL_PROFILE
}


#ifdef NKPROF  // TOC info available only in profiling builds

//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//
//  Functions used to look up symbol information included in the TOC in
//  profiling builds.
//
//  GetT

⌨️ 快捷键说明

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