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

📄 celog.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
//------------------------------------------------------------------------------
//
//  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.
//  
//------------------------------------------------------------------------------
//
//  Module Name:  
//  
//      celog.c
//  
//  Abstract:  
//
//      Implements the CeLog event logging functions.
//      
//------------------------------------------------------------------------------

#include <kernel.h>

#ifndef _PREFAST_
#pragma warning(disable: 4068) // Disable pragma warnings
#endif

#define MODNAME TEXT("CeLog")
#ifdef DEBUG
DBGPARAM dpCurSettings = { MODNAME, {
        TEXT("<unused>"), TEXT("<unused>"), TEXT("<unused>"), TEXT("<unused>"),
        TEXT("<unused>"), TEXT("<unused>"), TEXT("<unused>"), TEXT("<unused>"),
        TEXT("<unused>"), TEXT("<unused>"), TEXT("<unused>"), TEXT("<unused>"),
        TEXT("<unused>"), TEXT("<unused>"), TEXT("<unused>"), TEXT("<unused>") },
    0x00000000};
#endif

#define ZONE_VERBOSE 0


//------------------------------------------------------------------------------
// BUFFERS

typedef struct  __CEL_BUFFER {
    DWORD   dwMaskProcess;              // Process mask (1 bit per process slot)
    DWORD   dwMaskUser;                 // User zone mask
    DWORD   dwMaskCE;                   // Predefined zone mask (CELZONE_xxx)
    PDWORD  pWrite;                     // Pointer to next entry to be written
    DWORD   dwBytesLeft;                // Bytes left available in the buffer
    DWORD   dwSize;                     // Total number of bytes in the buffer
    PDWORD  pBuffer;                    // Start of the data
} CEL_BUFFER, *PCEL_BUFFER;

typedef struct _RINGBUFFER {
    HANDLE hMap;        // Used for RingBuf memory mapping
    PMAPHEADER pHeader; // Pointer to RingBuf map header
    LPBYTE pBuffer;
    LPBYTE pRead;
    LPBYTE pWrite;
    LPBYTE pWrap;
    DWORD  dwSize;
    DWORD  dwBytesLeft; // Calculated during flush for RingBuf, always valid for IntBuf
} RINGBUFFER, *PRINGBUFFER;

RINGBUFFER RingBuf;
RINGBUFFER IntBuf;
PCEL_BUFFER pCelBuf;

CEL_BUFFER CelBuf;

//------------------------------------------------------------------------------
// EXPORTED GLOBAL VARIABLES

#define SMALLBUF_MAX         4096*1024  // Maximum size an OEM can boost the small buffer to
#define PAGES_IN_MAX_BUFFER  (SMALLBUF_MAX/PAGE_SIZE)
#define RINGBUF_SIZE         128*1024   // Default size of large buffer

#ifndef CELOG_SIZE
#define SMALLBUF_SIZE        4*1024     // Default size of small buffer
#else
#define SMALLBUF_SIZE        CELOG_SIZE // Default size of small buffer
#endif                                                 


//------------------------------------------------------------------------------
// MISC

// RESERVED zones cannot be turned on, CELZONE_ALWAYSON cannot be turned off
#define VALIDATE_ZONES(dwVal)   (((dwVal) & ~(CELZONE_RESERVED1|CELZONE_RESERVED2)) | CELZONE_ALWAYSON)

#define MAX_ROLLOVER_MINUTES    30
#define MAX_ROLLOVER_COUNT      (0xFFFFFFFF / (MAX_ROLLOVER_MINUTES * 60))

HANDLE g_hFillEvent;  // Used to indicate the secondary buffer is getting full
BOOL   g_fInit;
DWORD  g_dwDiscardedInterrupts;
DWORD  g_dwPerfTimerShift;

// Inputs from kernel
CeLogImportTable    g_PubImports;
CeLogPrivateImports g_PrivImports;


#define DATAMAP_NAME      CELOG_DATAMAP_NAME
#define FILLEVENT_NAME    CELOG_FILLEVENT_NAME


//------------------------------------------------------------------------------
// Abstract accesses to imports

#define PUB_FUNC(Api, Args)     ((g_PubImports.p##Api) Args)
#define PUB_VAR(Var)            (g_PubImports.Var)
#define PRIV_FUNC(Api, Args)    ((g_PrivImports.p##Api) Args)
#define PRIV_VAR(Var)           (g_PrivImports.Var)

#define ISAPIREADY(hAPI)         ((UserKInfo[KINX_API_MASK] & (1 << (hAPI))) != 0)

// KData accesses are hidden in SWITCHKEY, SETCURKEY
#undef KData
#define KData                    (*PRIV_VAR(pKData))


#ifndef SHIP_BUILD
#undef RETAILMSG
#define RETAILMSG(cond, printf_exp) ((cond)?(PUB_FUNC(NKDbgPrintfW, printf_exp),1):0)
#endif // SHIP_BUILD

#ifdef DEBUG
#undef DEBUGMSG
#define DEBUGMSG                 RETAILMSG
#endif // DEBUG

#ifdef DEBUG
#undef DBGCHK
#undef DEBUGCHK
#define DBGCHK(module,exp)                                                     \
   ((void)((exp)?1                                                             \
                :(PUB_FUNC(NKDbgPrintfW, (TEXT("%s: DEBUGCHK failed in file %s at line %d\r\n"), \
                                          (LPWSTR)module, TEXT(__FILE__), __LINE__)), \
                  DebugBreak(),                                                \
	              0                                                            \
                 )))
#define DEBUGCHK(exp) DBGCHK(dpCurSettings.lpszName, exp)
#endif // DEBUG


//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
static void
INT_WriteRingBuffer(
    PRINGBUFFER pRingBuf,
    LPBYTE  lpbData,        // NULL = just move pointers/counters
    DWORD   dwBytes,
    LPDWORD lpdwBytesLeft1,
    LPDWORD lpdwBytesLeft2
    )
{
    DWORD dwSrcLen1, dwSrcLen2;

    dwSrcLen1 = min(dwBytes, *lpdwBytesLeft1);
    dwSrcLen2 = dwBytes - dwSrcLen1;
    
    // Write to middle or end of buffer
    if (dwSrcLen1) {
        if (lpbData) {
            memcpy(pRingBuf->pWrite, lpbData, dwSrcLen1);
            lpbData += dwSrcLen1;
        }
        pRingBuf->pWrite += dwSrcLen1;
        pRingBuf->dwBytesLeft -= dwSrcLen1;
        *lpdwBytesLeft1 -= dwSrcLen1;
        if (pRingBuf->pWrite >= pRingBuf->pWrap) {
            pRingBuf->pWrite = pRingBuf->pBuffer;
        }
    }
    
    // Write to front of buffer in case of wrap
    if (dwSrcLen2) {
        if (lpbData) {
            memcpy(pRingBuf->pWrite, lpbData, dwSrcLen2);
        }
        pRingBuf->pWrite += dwSrcLen2;
        pRingBuf->dwBytesLeft -= dwSrcLen2;
        *lpdwBytesLeft2 -= dwSrcLen2;
    }
}


//------------------------------------------------------------------------------
// FlushBuffer is interruptable but non-preemptible
//------------------------------------------------------------------------------
static void
INT_FlushBuffer()
{
    DWORD     dwSrcLen1, dwSrcLen2, dwSrcTotal;
    DWORD     dwDestLen1, dwDestLen2; // Locals instead of ringbuf members because temp.
    LPBYTE    pReadCopy, pWriteCopy;
    DWORD     dwBytesLeftCopy;
    ACCESSKEY akyOld;
    static DWORD dwTLBPrev = 0;
     
    SWITCHKEY(akyOld, 0x00000001); // Guarantee access to NK
    
    pReadCopy = RingBuf.pHeader->pRead;
    RingBuf.dwBytesLeft = (DWORD) pReadCopy - (DWORD) RingBuf.pWrite + RingBuf.dwSize;
    if (RingBuf.dwBytesLeft > RingBuf.dwSize) {
        // wrapped.
        RingBuf.dwBytesLeft -= RingBuf.dwSize;
    }
    
    if ((RingBuf.dwBytesLeft < RingBuf.dwSize / 4) && RingBuf.pHeader->fSetEvent) {
       // Signal that the secondary buffer is getting full
       RingBuf.pHeader->fSetEvent = FALSE;  // Block any more SetEvent calls
       PUB_FUNC(EventModify, (g_hFillEvent, EVENT_SET));  // SetEvent
    }
    
    dwSrcTotal = (DWORD) pCelBuf->pWrite - (DWORD) pCelBuf->pBuffer;
    if (RingBuf.dwBytesLeft <= dwSrcTotal) {
        RETAILMSG(ZONE_VERBOSE, (MODNAME TEXT(": ERROR, Secondary Buffer Overrun. Dropping %d bytes (%d available)\r\n"),
                                 dwSrcTotal, RingBuf.dwBytesLeft));
        RingBuf.pHeader->dwLostBytes += dwSrcTotal;

        // Reset primary buffer to the beginning
        pCelBuf->pWrite = pCelBuf->pBuffer;
        pCelBuf->dwBytesLeft = pCelBuf->dwSize;
        
        SETCURKEY(akyOld);
        return;
    }

    //
    // Determine where we can write into the large buffer
    //

    if (RingBuf.pWrite >= pReadCopy) {
        //          pRead            pWrap
        //          v                v
        //  +-----------------------+ 
        //  |   2  |XXXXXX|    1    | 
        //  +-----------------------+ 
        //  ^             ^
        //  pBuffer       pWrite
        dwDestLen1 = (DWORD) RingBuf.pWrap - (DWORD) RingBuf.pWrite;
        dwDestLen2 = (DWORD) pReadCopy - (DWORD) RingBuf.pBuffer;

    } else {
        //  pBuffer          pRead
        //  v                v
        //  +-----------------------+  
        //  |XXXXX|         |XXXXXXX|
        //  +-----------------------+  
        //        ^                 ^
        //        pWrite            pWrap
        dwDestLen1 = (DWORD) pReadCopy - (DWORD) RingBuf.pWrite;
        dwDestLen2 = 0;
    }
    
    
    // Copy the data
    INT_WriteRingBuffer(&RingBuf, (LPBYTE)pCelBuf->pBuffer, dwSrcTotal, &dwDestLen1, &dwDestLen2);
    RingBuf.pHeader->pWrite = RingBuf.pWrite; // Update map header
    pCelBuf->pWrite = pCelBuf->pBuffer;
    pCelBuf->dwBytesLeft = pCelBuf->dwSize;
    

    //--------------------------------------------------------------
    // Now copy in the interrupts that happened during this quantum
    //
    
    // Copy the counters because interrupts are still on (retry if interrupted)
    do {
        pWriteCopy = *(volatile LPBYTE*)&IntBuf.pWrite;
        dwBytesLeftCopy = *(volatile DWORD*)&IntBuf.dwBytesLeft;
    } while ((pWriteCopy != *(volatile LPBYTE*)&IntBuf.pWrite)
             || (dwBytesLeftCopy != *(volatile DWORD*)&IntBuf.dwBytesLeft));

    dwSrcTotal = IntBuf.dwSize - dwBytesLeftCopy;
    
    if (dwSrcTotal) {
        
        if (RingBuf.dwBytesLeft < (dwSrcTotal + 8)) {
            RETAILMSG(ZONE_VERBOSE, (MODNAME TEXT(": ERROR, Secondary Buffer Overrun. Dropping %d bytes (interrupts) (%d available)\r\n"),
                                     dwSrcTotal, RingBuf.dwBytesLeft));
            RingBuf.pHeader->dwLostBytes += dwSrcTotal + 8;

            // Reset interrupt buffer to the beginning
            IntBuf.pRead = pWriteCopy;
            IntBuf.dwBytesLeft += dwSrcTotal;
            
            SETCURKEY(akyOld);
            return;
        }
        
        // Write in the interrupt header
        *((PDWORD) RingBuf.pWrite) = CELID_INTERRUPTS << 16 | (WORD) (dwSrcTotal + 4);
        INT_WriteRingBuffer(&RingBuf, NULL, sizeof(DWORD), &dwDestLen1, &dwDestLen2);
        *((PDWORD) RingBuf.pWrite) = g_dwDiscardedInterrupts;
        INT_WriteRingBuffer(&RingBuf, NULL, sizeof(DWORD), &dwDestLen1, &dwDestLen2);

        // Determine where to copy from in the interrupt buffer
        if (pWriteCopy > IntBuf.pRead) {
            //         pRead            pWrap
            //         v                v
            //  +-----------------------+ 
            //  |      |XX 1 X|         | 
            //  +-----------------------+ 
            //  ^             ^
            //  pBuffer       pWrite
            dwSrcLen1 = (DWORD) pWriteCopy - (DWORD) IntBuf.pRead;
            dwSrcLen2 = 0;
    
        } else {
            //  pBuffer         pRead
            //  v               v
            //  +-----------------------+  
            //  |X 2 X|         |XX 1 XX|
            //  +-----------------------+  
            //        ^                 ^
            //        pWrite            pWrap
            dwSrcLen1 = (DWORD) IntBuf.pWrap  - (DWORD) IntBuf.pRead;
            dwSrcLen2 = (DWORD) pWriteCopy - (DWORD) IntBuf.pBuffer;
        }
    
        // Copy the data
        if (dwSrcLen1) {
            INT_WriteRingBuffer(&RingBuf, IntBuf.pRead, dwSrcLen1, &dwDestLen1, &dwDestLen2);
        }
        if (dwSrcLen2) {
            INT_WriteRingBuffer(&RingBuf, IntBuf.pBuffer, dwSrcLen2, &dwDestLen1, &dwDestLen2);
        }
        RingBuf.pHeader->pWrite = RingBuf.pWrite; // Update map header
        IntBuf.pRead = pWriteCopy;
        IntBuf.dwBytesLeft += dwSrcLen1 + dwSrcLen2;
        g_dwDiscardedInterrupts = 0;
    }


    //--------------------------------------------------------------
    // Now copy in the TLB Misses that happened in this quantum
    //
    if (PUB_VAR(pdwCeLogTLBMiss) && (*PUB_VAR(pdwCeLogTLBMiss) != dwTLBPrev)
        && (pCelBuf->dwMaskCE & CELZONE_TLB)) {
        
        if (RingBuf.dwBytesLeft < 2*sizeof(DWORD)) {
            RETAILMSG(ZONE_VERBOSE, (MODNAME TEXT(": ERROR, Secondary Buffer Overrun. Delaying TLB Miss Data report\r\n")));
            RingBuf.pHeader->dwLostBytes += 2*sizeof(DWORD);
            SETCURKEY(akyOld);
            return;
        }
        
        // Write in the TLB miss header
        *((PDWORD) RingBuf.pWrite) = CELID_SYSTEM_TLB << 16 | sizeof(CEL_SYSTEM_TLB);

⌨️ 快捷键说明

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