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

📄 iorm.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.
//

#include <windows.h>
#include "iormif.h"
#include "devzones.h"

#ifdef _PREFAST_
#ifdef DEBUGCHK
#undef DEBUGCHK
#endif // DEBUGCHK
#define DEBUGCHK(exp) PREFAST_ASSUME(exp)
#endif // _PREFAST_


// More than this many distinct resources of a given type need to be represented by a
// sparse table; less than (or equal to) this many can be represented by a bit vector.
// This type of resource is typically used to represent IRQs -- a fixed table size of
// 64 should be sufficient since CE currently limits the number of SysIntrs.
#define DEF_TABLE_THRESHOLD 64

typedef struct {
    DWORD id;
    DWORD len;
} ResourceRange;

typedef struct SparseTableNode {
    ResourceRange res;
    struct SparseTableNode *pNext;
} SparseTableNode;

typedef struct {
    SparseTableNode *pFirst;
} SparseTable;

typedef struct {
    DWORD dwResMax;             // max resource index
    PDWORD prvValid;            // even dense resource lists can have holes
    PDWORD prvShareable;        // indicates which resources are shareable
    PDWORD prvExclusive;        // indicates resources that are requested for exclusive access
    PUSHORT pUseCount;          // records the number of resource users
} DenseTable;

typedef struct {
    DWORD dwSize;
    union {
        SparseTable st;
        DenseTable  dt;
    };
} ResourceTable;

typedef struct ResourceDomain {
    DWORD dwResId;              // identifies the resource type
    DWORD dwOffset;             // minimum value for dwId
    ResourceTable table;
    struct ResourceDomain *pNext;
} ResourceDomain;


// -- forward declarations --
#ifdef DEBUG
void ResourceDump (ResourceDomain *);
void ResourceDumpAll (void);
#endif

// A list of available resource domains from which resources can be allocated,
// and a way to protect it for thread-safety.
static ResourceDomain *g_DomainList;
static CRITICAL_SECTION gcsIORM;
static DWORD gdwMaxDenseResources;

// This routine initializes an array of resource bitmasks.  The bitmask vector
// is an array of 32-bit DWORDs.  The max value is 0-relative and inclusive, so
// we add one to get the number of elements.
static void
RBMInit(DWORD dwResMax, PDWORD pdwMask, BOOL fSet)
{
    DWORD dwSize;
    DEBUGCHK(pdwMask != NULL);

    // convert to byte count
    dwSize = (dwResMax + 1) / 8;

    // set or clear bits in the vector
    memset(pdwMask, fSet ? 0xFF : 0x00, dwSize);
}

// This routine tests whether a particular bit is set in a resource bitmask vector
// and returns TRUE if it is.
static BOOL
RBMIsSet(DWORD dwResMax, DWORD dwElement, PDWORD pdwMask)
{
    DWORD dwIndex;
    BOOL fIsSet;
    
    DEBUGCHK(dwElement <= dwResMax);
    DEBUGCHK(pdwMask != NULL);

    // convert the element into a bit and an offset
    dwIndex = dwElement / 32;
    dwElement %= 32;

    // is the bit set in the mask?
    if((pdwMask[dwIndex] & (1 << dwElement)) != 0) {
        fIsSet = TRUE;
    } else {
        fIsSet = FALSE;
    }

    return fIsSet;
}

// this routine sets a bit in a resource bitmask vector
static void
RBMSet(DWORD dwResMax, DWORD dwElement, PDWORD pdwMask)
{
    DWORD dwIndex;
    
    DEBUGCHK(dwElement <= dwResMax);
    DEBUGCHK(pdwMask != NULL);

    // convert the element into a bit and an offset
    dwIndex = dwElement / 32;
    dwElement %= 32;

    // is the bit set in the mask?
    pdwMask[dwIndex] |= (1 << dwElement);
}

// this routine clears a bit in a resource bitmask vector
static void
RBMClear(DWORD dwResMax, DWORD dwElement, PDWORD pdwMask)
{
    DWORD dwIndex;
    
    DEBUGCHK(dwElement <= dwResMax);
    DEBUGCHK(pdwMask != 0);

    // convert the element into a bit and an offset
    dwIndex = dwElement / 32;
    dwElement %= 32;

    // is the bit set in the mask?
    pdwMask[dwIndex] &= ~(1 << dwElement);
}

static ResourceDomain *FindDomain (DWORD dwResId)
{
    ResourceDomain *pdom;

    pdom = g_DomainList;

    for (; pdom; pdom = pdom->pNext)
        if (pdom->dwResId == dwResId)
            break;

    return pdom;
}

static DWORD SetDenseResources (DenseTable *ptab, DWORD dwId, DWORD dwLen, BOOL fClaim, DWORD dwFlags)
{
    DWORD dwTrav, dwCount;
    
    DEBUGCHK(ptab);
    DEBUGCHK(dwId >= 0);
    DEBUGCHK(dwLen > 0);
    DEBUGCHK(dwId <= ptab->dwResMax);
    DEBUGCHK((dwId + (dwLen - 1)) <= ptab->dwResMax);
    DEBUGCHK(dwFlags == 0 || fClaim);

    if(fClaim) {
        BOOL fExclusive;

        // are we requesting exclusive access to a shared resource?
        if((dwFlags & RREXF_REQUEST_EXCLUSIVE) != 0) {
            fExclusive = TRUE;
        } else {
            fExclusive = FALSE;
        }
        
        // make sure that nobody has claimed any non-shareable resources
        for(dwTrav = dwId, dwCount = 0; dwCount < dwLen; dwTrav++, dwCount++) {
            if(! RBMIsSet(ptab->dwResMax, dwTrav, ptab->prvValid)) {
                // resource isn't valid and can't be allocated
                return ERROR_INVALID_PARAMETER;
            }
            
            if(ptab->pUseCount[dwTrav] != 0) {
                if(! RBMIsSet(ptab->dwResMax, dwTrav, ptab->prvShareable)
                || fExclusive
                || RBMIsSet(ptab->dwResMax, dwTrav, ptab->prvExclusive)) {
                    // the resource is in use but it's (a) not shareable, or (b) we
                    // want it exclusively, or (c) whoever has it wants it exclusively.
                    return ERROR_BUSY;
                }
            }
        }

        // now allocate the resource
        for(dwTrav = dwId, dwCount = 0; dwCount < dwLen; dwTrav++, dwCount++) {
            ptab->pUseCount[dwTrav]++;
            if(fExclusive) {
                DEBUGCHK(ptab->pUseCount[dwTrav] == 1);
                RBMSet(ptab->dwResMax, dwTrav, ptab->prvExclusive);
            }
        }
    } else {
        // validate the resource or make sure it has been allocated -- do this 
        // in two passes so we don't get partially released resources
        for(dwTrav = dwId, dwCount = 0; dwCount < dwLen; dwTrav++, dwCount++) {
            if(!RBMIsSet(ptab->dwResMax, dwTrav, ptab->prvValid)) {
                DEBUGCHK(ptab->pUseCount[dwTrav] == 0xAFAF);
            } else {
                if(ptab->pUseCount[dwTrav] == 0) {
                    return ERROR_INVALID_PARAMETER;
                }
            }
        }

        // validate the resource and/or free it by reducing its reference count
        for(dwTrav = dwId, dwCount = 0; dwCount < dwLen; dwTrav++, dwCount++) {
            if(!RBMIsSet(ptab->dwResMax, dwTrav, ptab->prvValid)) {
                DEBUGCHK(!RBMIsSet(ptab->dwResMax, dwTrav, ptab->prvExclusive));
                RBMSet(ptab->dwResMax, dwTrav, ptab->prvValid);
                ptab->pUseCount[dwTrav] = 0;
            } else {
                DEBUGCHK(ptab->pUseCount[dwTrav] != 0);
                if(RBMIsSet(ptab->dwResMax, dwTrav, ptab->prvExclusive)) {
                    DEBUGCHK(ptab->pUseCount[dwTrav] == 1);
                    RBMClear(ptab->dwResMax, dwTrav, ptab->prvExclusive);
                }
                ptab->pUseCount[dwTrav]--;
            }
        }
    }

    return ERROR_SUCCESS;
}

static DWORD SetSparseResources (SparseTable *ptab, DWORD dwId, DWORD dwLen, BOOL fClaim, DWORD dwFlags)
{
    SparseTableNode **ppnod, *pnod;

    DEBUGCHK(dwFlags == 0 || fClaim);
    if(dwFlags != 0) {
        DEBUGMSG(ZONE_WARNING, (_T("SetSparseResources: flags value 0x%08x not supported\r\n"), dwFlags));
        return ERROR_NOT_SUPPORTED;
    }
    
    for (pnod = *(ppnod = &ptab->pFirst); pnod != NULL; pnod = *(ppnod = &pnod->pNext))
        if (fClaim) {
            if (pnod->res.id <= dwId && pnod->res.id + pnod->res.len - 1 >= dwId)
                break;
        }
        else {
            if (pnod->res.id + pnod->res.len > dwId && pnod->res.id < dwId + dwLen)
                return ERROR_INVALID_PARAMETER; // requested range includes available resources! (serious caller error)
            if (pnod->res.id >= dwId + dwLen || pnod->res.id + pnod->res.len == dwId)
                break;
        }

    if (fClaim) {
        // make sure the resources are free so we can claim them
        if (pnod == NULL)
            return ERROR_INVALID_PARAMETER;  // dwId is unavailable
        if (dwId + dwLen  > pnod->res.id + pnod->res.len)
            return ERROR_BUSY;  // some subset of the range is unavailable

        // OK, we can claim. Now adjust the list. There are several cases.
        ASSERT(pnod->res.len >= dwLen);
        if (pnod->res.len == dwLen) {
            // delete the entire current range
            ASSERT(pnod->res.id == dwId);
            *ppnod = pnod->pNext;
            LocalFree(pnod);
        }
        else if (pnod->res.id == dwId) {
            pnod->res.id += dwLen;
            pnod->res.len -= dwLen;
        }
        else if (pnod->res.id + pnod->res.len == dwId + dwLen) {
            pnod->res.len -= dwLen;
        }
        else {
            // we have to split the current resource range
            SparseTableNode *newnod = LocalAlloc(0, sizeof(*newnod));
            if (newnod == NULL)
                return ERROR_NOT_ENOUGH_MEMORY;  // OOM!
            newnod->res.id = dwId + dwLen;
            newnod->res.len = pnod->res.id + pnod->res.len - newnod->res.id;
            newnod->pNext = pnod->pNext;
            pnod->pNext = newnod;
            pnod->res.len -= dwLen + newnod->res.len;
        }
    }
    else {
        // make sure the resources are claimed so we can free them
        if (pnod == NULL) {
            // case 6 or 7 (same as case 1 or 3)
          mknew: {
            SparseTableNode *newnod = LocalAlloc(0, sizeof(*newnod));
            if (newnod == NULL)
                return ERROR_NOT_ENOUGH_MEMORY;  // OOM!
            newnod->res.id = dwId;
            newnod->res.len = dwLen;
            newnod->pNext = pnod;
            *ppnod = newnod;
          }}
        else if (pnod->res.id + pnod->res.len == dwId) {
            // case 2 or 5
            SparseTableNode *pnxt = pnod->pNext;
            if (pnxt && pnxt->res.id < dwId + dwLen)
                return ERROR_INVALID_PARAMETER;  // cannot free resources already available!
            pnod->res.len += dwLen;
            if (pnxt && pnxt->res.id == dwId + dwLen) {
                // case 5
                pnod->res.len += pnxt->res.len;
                pnod->pNext = pnxt->pNext;
                LocalFree(pnxt);
            }
        }
        else if (pnod->res.id == dwId + dwLen) {
            // case 4
            pnod->res.id -= dwLen;
            pnod->res.len += dwLen;
        }
        else {
            ASSERT(dwId + dwLen < pnod->res.id);
            // case 1 or 3
            goto mknew;  // see case 6 or 7
        }
    }

    return ERROR_SUCCESS;
}

BOOL IORM_ResourceMarkAsShareable(DWORD dwResId, DWORD dwId, DWORD dwLen, BOOL fShareable)
{
    ResourceDomain *pdom;
    DWORD size, min;
    DWORD dwTrav, dwCount;
    DWORD dwError = ERROR_INVALID_PARAMETER;
    BOOL fOk;

    DEBUGMSG(ZONE_RESMGR, (_T("IORM: marking 0x%x resources at 0x%08x as %s in list 0x%08x\r\n"), 
        dwLen, dwId, fShareable ? _T("shareable") : _T("unshareable"), dwResId));

⌨️ 快捷键说明

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