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

📄 watchdog.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 2 页
字号:
//
// 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.
//

#include <kernel.h>

#define DEFAULT_WATCHDOG_PRIORITY   100

void FakedRefreshWatchDog (void)
{
}

//
// globals that can be updated by OEM 
//
void (* pfnOEMRefreshWatchDog) (void) = FakedRefreshWatchDog;
DWORD   dwOEMWatchDogPeriod;
DWORD   dwNKWatchDogThreadPriority = DEFAULT_WATCHDOG_PRIORITY;
extern CRITICAL_SECTION     WDcs;
extern LPDWORD              pIsExiting;

//
// watchdog structure
//
typedef struct _WatchDog {
    struct _WatchDog *pNext;        // next entry in the timer list
    struct _WatchDog *pPrev;        // previous entry in the timer list
    DWORD           dwExpire;       // time expired
    DWORD           dwState;        // current state
    HANDLE          hWDog;          // handle to the watchdog timer
    DWORD           dwPeriod;       // watchdog period
    DWORD           dwWait;         // time to wait before default action taken
    DWORD           dwDfltAction;   // default action
    DWORD           dwParam;        // parameter passed to IOCTL_HAL_REBOOT
    HANDLE          hProc;          // process to be watched
} WatchDog, *PWatchDog;

ERRFALSE(sizeof(WatchDog) <= sizeof(FULLREF));

//
// globals internal to watchdog support
//
static PWatchDog pWDList;
static HANDLE    hWDEvt;
static HANDLE    hWDThrd;

//
// watchdog states
//
#define WD_STATE_STOPPED            0
#define WD_STATE_STARTED            1
#define WD_STATE_SIGNALED           2


HANDLE KillOneThread (HANDLE hTh, DWORD dwRetVal);
BOOL KernelIoctl (DWORD dwIoControlCode, LPVOID lpInBuf, DWORD nInBufSize, LPVOID lpOutBuf, DWORD nOutBufSize, LPDWORD lpBytesReturned);

//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
static void WDenqueue (PWatchDog pWD)
{
    if (!pWDList || ((int) (pWD->dwExpire - pWDList->dwExpire) < 0)) {
        
        pWD->pNext = pWDList;
        pWD->pPrev = NULL;
        pWDList = pWD;
        
    } else {
        PWatchDog pPrev = pWDList, pNext;

        while ((pNext = pPrev->pNext) && ((int) (pNext->dwExpire - pWD->dwExpire) <= 0)) {
            pPrev = pNext;
        }
        pWD->pPrev = pPrev;
        pPrev->pNext = pWD;
        if (pWD->pNext = pNext) {
            pNext->pPrev = pWD;
        }
    }
}

//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
static void WDdequeue (PWatchDog pWD)
{
    PWatchDog pPrev = pWD->pPrev, pNext = pWD->pNext;
    if (pPrev) {
        pPrev->pNext = pNext;
    } else {
        // pWD is the head of the list
        pWDList = pNext;
    }

    if (pNext) {
        pNext->pPrev = pPrev;
    }
}

//--------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------
static void WDTakeDfltAction (PWatchDog pWD)
{
    PPROCESS pProc;
    LPDWORD  pProcExiting;
    switch (pWD->dwDfltAction) {
    case WDOG_KILL_PROCESS:
        // don't call SC_ProcTerminate because it'll block waiting for the process to exit
        if ((pProc = HandleToProc (pWD->hProc))
            && (pProcExiting = (LPDWORD)MapPtrProc (pIsExiting, pProc))
            && !*pProcExiting) {

            KillOneThread (pProc->pMainTh->hTh, 0);

            // can't safely make this call because the PSL might be the process being terminated
            // pPSLNotify (DLL_PROCESS_EXITING,(DWORD)pWD->hProc,(DWORD)NULL);
        }
        break;
    case WDOG_RESET_DEVICE:
        KernelIoctl (IOCTL_HAL_REBOOT, &pWD->dwParam, sizeof(DWORD), NULL, 0, NULL);
        break;
    default:
        // no default action
        break;
    }
}

//--------------------------------------------------------------------------------------------
// get the watchdog pointer from a watchdog handle
//--------------------------------------------------------------------------------------------
PWatchDog GetWatchDog (HANDLE hWDog)
{
    PWatchDog pWD = (PWatchDog) SC_EventGetData (hWDog);
    return (IsValidKPtr (pWD) && (hWDog == pWD->hWDog))? pWD : NULL;
}

//--------------------------------------------------------------------------------------------
// associate a watchdog pointer with a watchdog handle
//--------------------------------------------------------------------------------------------
static BOOL SetWatchDog (HANDLE hWDog, PWatchDog pWD)
{
    DEBUGCHK (!pWD || (pWD->hWDog == hWDog));
    
    return SC_EventSetData (hWDog, (DWORD) pWD);
}

//--------------------------------------------------------------------------------------------
// the watchdog timer thread
//--------------------------------------------------------------------------------------------
static DWORD WINAPI WatchDogTimerThrd (
    LPVOID   pParam)
{
    DWORD           dwTimeout, dwTick, dwDiff;
    PWatchDog       pWD;

    // the watchdog thread run with access to all processes so that it can set the watchdog event
    SWITCHKEY (dwTick, 0xffffffff);
    
    do {
        // refresh hardware watchdog if exist
        pfnOEMRefreshWatchDog ();

        // default timeout is either hardware watchdog period, or infinite when there is no
        // hardware watchdog
        dwTimeout = dwOEMWatchDogPeriod? dwOEMWatchDogPeriod : INFINITE;

        // look into the timer queue and see if there is any watchdog to be signaled. Also
        // calculate timeout if we need to wakeup before the watchdog period expired
        EnterCriticalSection (&WDcs);
        
        while (pWDList) {
                
            // get current time and diff
            dwTick = SC_GetTickCount ();
            dwDiff = pWDList->dwExpire - dwTick;
            
            if ((int) dwDiff > 0) {
                // No need to signal watchdog yet. But we need to
                // adjust timeout if we need to wakeup earlier.
                if (dwTimeout > dwDiff) {
                    dwTimeout = dwDiff;
                }
                break;
            }
            
            // there is at least one watchdog needs to be signaled

            // remove the watchdog from the list
            pWD = pWDList;
            if (pWDList = pWDList->pNext) {
                pWDList->pPrev = NULL;
            }

            // take action based on state
            switch (pWD->dwState) {
            case WD_STATE_STARTED:
                // signal the watchdog
                pWD->dwState = WD_STATE_SIGNALED;
                SetEvent (pWD->hWDog);

                // put ourself back to the timer queue if dwWait is specified
                if (pWD->dwWait) {
                    pWD->dwExpire = dwTick + pWD->dwWait;
                    WDenqueue (pWD);
                    break;
                }
                // fall through to take default action
                
            case WD_STATE_SIGNALED:
                // watchdog isn't refreshed after dwWait, take default action
                WDTakeDfltAction (pWD);
                pWD->dwState = WD_STATE_STOPPED;
                break;

            case WD_STATE_STOPPED:
                // watchdog is stopped, just remove ignore the entry
                break;
                
            default:
                // should not happen
                DEBUGCHK (0);
                break;
            }

        }
        LeaveCriticalSection (&WDcs);
    } while (SC_WaitForMultiple (1, &hWDEvt, FALSE, dwTimeout) != WAIT_FAILED);

    DEBUGCHK (0);
    SC_NKTerminateThread (0);
    return 0;
}

//--------------------------------------------------------------------------------------------
// create the watchdog timer thread
//--------------------------------------------------------------------------------------------
static HANDLE CreateWatchDogThread (void)
{
    if (!hWDThrd) {
        hWDThrd = CreateKernelThread (WatchDogTimerThrd, NULL, (WORD) dwNKWatchDogThreadPriority, 0);
        DEBUGMSG (1, (L"WatchDog Timer thread %8.8lx Created\r\n", hWDThrd));
    }

⌨️ 快捷键说明

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