出手无招

出手无招

0个粉丝

12

问答

0

专栏

0

资料

出手无招  发布于  2019-10-29 10:50:36
采纳率 0%
12个问答
2310

内存管理

   
[i=s] 本帖最后由 anwafs 于 2019-10-29 11:47 编辑 [/i]

[password]254431[/password]
/////////////////////////////////////////////////////////////////////////////////////
伙伴:
#ifndef BUDDYSYSTEM_H
#define BUDDYSYSTEM_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <osal.h>

typedef enum
{
     BUDDY_MEM_TYPE_MMZ = 0,
     BUDDY_MEM_TYPE_OS,
     BUDDY_MEM_TYPE_MAX
} BuddyMemType;

/* Buddy System 分配的内存地址 */
typedef struct  BuddyMem
{
    Int8    *pVirMem;        /* 伙伴系统返回的虚拟地址 */
    Sizet   pPhyAddr;        /* 伙伴系统返回的物理地址,os内存无效 ,mmz有效 */
    Int8   memType;
    Int8    res[3];
    Uint32  res1[32];
} BuddyMem;

typedef struct  BuddyNode
{
    struct  BuddyNode *prelink;   /* 指向前驱节点 */
    Int32    tag;                /* 块标志,0空闲,1占用 */
    Int32    kval;               /* 块大小,值为2的kval次幂 */
    struct  BuddyNode *nextlink;  /* 头部域,指向后继节点 */
    Sizet  phyAddr;              /* userSpace的物理地址 */
    Int8   *userSpace;           /* 用户可用地址 */
} BuddyNode;

typedef struct  BuddySets
{
    Uint32     memSize;          /* 伙伴系统总内存大小, memSize = blockSize * 2~blockNum */
    Uint32     blockSize;        /* 每块内存大小 */
    Int16      memType;          /* 内存类型,mmz or os,参考 BuddyMemType */
    Int16      blockNum;         /* 此值描述内存块个数,总个数为2的blockNum次幂,例 num = 7,则总个数为2的7次方 */
    Sizet      pBasePhyAddr;     /* 待管理地址的物理地址 */
    Int8       *pUserMem;        /* 待管理内存的虚拟地址 */
    Int8       beCache;          /* 只对mmz内存有效,内存是否为cache,0:否 1:是 */
    Int8       res0[3];
    Int32      res[32];
} BuddySets;

typedef struct 
{
     BuddyNode    *pNodeStart; /* 内存模块的起点 */
     BuddyNode    *pNodeEnd;   /* 内存模块的终点 */
     BuddySets    params;      /* 内存模块参数 */
    OSAL_MutexHandle lock;
} BuddySys;

typedef struct  BuddyHeadNode
{
    Int32           nodesize; /* 该链表的空闲块大小 */
     BuddyNode   *first;   /* 该链表的表头指针 */
     BuddySys     vdsBuddySys; /* 存放该内存模块的整体信息 */
} BuddyHeadNode;

Int32   buddyInit( BuddySets *pSets,  BuddyHeadNode **pBuddyHeadNode);
Int32   buddyDeinit( BuddyHeadNode *pBuddyHeadNode);
Int32  buddyAlloc( BuddyHeadNode *pBuddyHeadNode, Uint32 size,  BuddyMem *pBuddyMem);
Int32  buddyReclaim( BuddyHeadNode *pBuddyHeadNode,  BuddyMem *pBuddyMem);
void  buddyPrintLayout( BuddyHeadNode *pBuddyHeadNode);
Int32  buddyGetMmzPoolId( BuddyHeadNode *pBuddyHeadNode, Int32 *pPoolId);
Int32  buddyFlushMem( BuddyHeadNode *pBuddyHeadNode,  BuddyMem *pBuddyMem);
#endif

#ifndef BUDDYSYSTEM_C
#define BUDDYSYSTEM_C

#include " buddySys.h"
/* 返回p处内存块的伙伴内存地址 */
static  BuddyNode *  buddy( BuddyNode *p,  BuddyHeadNode *pBuddyHeadNode)
{
    int s = 0, m = 0, n = 0;

    s = p - pBuddyHeadNode[0].vdsBuddySys.pNodeStart;
    m = (int)pow(2, p->kval);
    n = (int)pow(2, p->kval + 1);

    if (0 == s % n)
    {
        return p + m;
    }

    if (m == s % n)
    {
        return p - m;
    }

    return NULL;
}

Int32   buddyInit( BuddySets *pSets,  BuddyHeadNode **ppBuddyHeadNode)    
{
    Int32             k  = 0;
    Int32             i  = 0;
    Int32             status = OSAL_OK;
    Sizet             pBasePhyAddr = 0;
    Int8              *pUserMem = NULL;
     BuddyNode     *pBuddyNode = NULL;
     BuddyHeadNode *pBuddyHeadNode = NULL;

    if (OSAL_isNull(ppBuddyHeadNode) || OSAL_isNull(pSets))
    {
        OSAL_ERROR("%s params err\n", __func__);
        return OSAL_FAIL;
    }


    if (pSets->blockNum <= 0 || pSets->memSize != pSets->blockSize * (Int32)pow(2, pSets->blockNum))
    {
        OSAL_ERROR("param err, blockNum:%d memSize:%d, and memSize should be equal to blockSize * 2~blockNum\n");
        return OSAL_FAIL;
    }

    pBuddyHeadNode = OSAL_memAlloc(sizeof( BuddyHeadNode) * (pSets->blockNum + 1));
    if (!pBuddyHeadNode)
    {
        OSAL_ERROR("mem over flow\n");
        return OSAL_FAIL;
    }

    for (k = 0; k <= pSets->blockNum; k++)
    {
        pBuddyHeadNode[k].nodesize = (int)pow(2, k) * pSets->blockSize;
        pBuddyHeadNode[k].first    = NULL;
    }

    pBuddyNode = ( BuddyNode *)OSAL_memAlloc((int)pow(2, pSets->blockNum) * sizeof( BuddyNode));
    if (!pBuddyNode)
    {
        OSAL_ERROR("over flow\n");
        status = OSAL_FAIL;
        goto exit;
    }
    else
    {
        pBuddyHeadNode[0].vdsBuddySys.pNodeStart = pBuddyNode;
        pBuddyHeadNode[0].vdsBuddySys.pNodeEnd   = pBuddyNode + pBuddyHeadNode[pSets->blockNum].nodesize / pSets->blockSize - 1;
    }

        pBuddyNode->prelink  = pBuddyNode;
    pBuddyNode->nextlink = pBuddyNode;
    pBuddyNode->tag = 0;
    pBuddyNode->kval = pSets->blockNum;

    /* 所有内存先挂到最大的内存管理链表上 */
    pBuddyHeadNode[pSets->blockNum].first = pBuddyNode;

    pUserMem     = pSets->pUserMem;
    pBasePhyAddr = pSets->pBasePhyAddr;
    for (i = 0; i < (int)pow(2, pSets->blockNum); i++, pBuddyNode++)
    {
        pBuddyNode->userSpace = pUserMem;
        pBuddyNode->phyAddr   = pBasePhyAddr;
        pUserMem             += pSets->blockSize;
        pBasePhyAddr         += pSets->blockSize;
    }

    status = OSAL_mutexCreate(OSAL_MUTEX_NORMAL, &pBuddyHeadNode[0].vdsBuddySys.lock);
    if (OSAL_isFail(status))
    {
        OSAL_ERROR("OSAL_mutexCreate err\n");
        goto exit;
    }

    OSAL_memCpySize(&pBuddyHeadNode[0].vdsBuddySys.params, pSets, sizeof(pBuddyHeadNode[0].vdsBuddySys.params));
    *ppBuddyHeadNode = pBuddyHeadNode;

    return status;
exit:

    if (pBuddyHeadNode)
    {
        OSAL_memFree(pBuddyHeadNode);
        pBuddyHeadNode = NULL;
    }

    if (pBuddyNode)
    {
        OSAL_memFree(pBuddyNode);
        pBuddyNode = NULL;
    }

    return status;
}

Int32   buddyDeinit( BuddyHeadNode *pBuddyHeadNode)
{
    if (OSAL_isNull(pBuddyHeadNode))
    {
        OSAL_ERROR(" buddyDeinit param err\n");
        return OSAL_FAIL;
    }

    OSAL_mutexDelete(pBuddyHeadNode[0].vdsBuddySys.lock);

    // 释放管理节点
    OSAL_memFree(pBuddyHeadNode[0].vdsBuddySys.pNodeStart);
    pBuddyHeadNode[0].vdsBuddySys.pNodeStart = NULL;

    OSAL_memFree(pBuddyHeadNode);
    pBuddyHeadNode = NULL;

    return OSAL_OK;
}

Int32  buddyAlloc( BuddyHeadNode *pBuddyHeadNode, Uint32 size,  BuddyMem *pBuddyMem)
{
    int k = 0; 
    int i = 0;
     BuddySys  *pObj = NULL;
     BuddyNode *pa = NULL, *pre = NULL, *suc = NULL, *pi = NULL;

    OSAL_assertNotNull(pBuddyHeadNode);
    OSAL_assertNotNull(pBuddyMem);

    pObj = &(pBuddyHeadNode[0].vdsBuddySys);

    OSAL_mutexLock(pObj->lock);
    for (k = 0; k <= pObj->params.blockNum && (pBuddyHeadNode[k].nodesize < size || !pBuddyHeadNode[k].first); k++)
        ; // 查找满足分配

    if (k > pObj->params.blockNum)
    {
        OSAL_ERROR("malloc err\n");
        OSAL_mutexUnlock(pObj->lock);
        return OSAL_FAIL;
    }
        else
    {
        pa = pBuddyHeadNode[k].first; // 指向可分配子表的第一个节点
        pre = pa->prelink;     // 分别指向前驱和后继
        suc = pa->nextlink;

        if(pa == suc)
        {
            /* k上就一个节点,k节点要被拆开,此节点不复存在 */
            pBuddyHeadNode[k].first = NULL;
        }
        else
        {
            /* 删除pa,修改双向指针关系 */
            pre->nextlink = suc;
            suc->prelink = pre;
            pBuddyHeadNode[k].first = suc;
        }

        /* 处理伙伴拆分后的节点 */
        for (i = 1; k - i >= 0 && pBuddyHeadNode[k - i].nodesize >= size; i++)
        {
            pi = pa + (int)pow(2, k - i);
            pi->nextlink = pi;
            pi->prelink = pi;
            pi->tag   = 0;
            pi->kval  = k - i;
            pBuddyHeadNode[k - i].first = pi;
        }

        pa->tag = 1;
        pa->kval = k - (--i);
    }
    pBuddyMem->pVirMem = pa->userSpace;
    pBuddyMem->pPhyAddr = pa->phyAddr;
    pBuddyMem->memType  = pObj->params.memType;

    OSAL_mutexUnlock(pObj->lock);
    return OSAL_OK;
}

Int32  buddyReclaim( BuddyHeadNode *pBuddyHeadNode,  BuddyMem *pBuddyMem)
{
    Int32         i  = 0;
     BuddyNode *pTmp = NULL;
     BuddyNode *s = NULL;
     BuddySys  *pObj = NULL;
    pObj = &(pBuddyHeadNode[0].vdsBuddySys);

    pTmp = pObj->pNodeStart;

    /* check p 合法性 */
    for (i = 0; i < (int)pow(2, pObj->params.blockNum); i++)
    {
        if (pTmp->userSpace == pBuddyMem->pVirMem)
        {
            break;
        }
        pTmp++;
    }

    if (i >= (int)pow(2, pObj->params.blockNum))
    {
        OSAL_ERROR("%p err, not in the buddy system\n", pBuddyMem->pVirMem);
        return OSAL_FAIL;
    }

    OSAL_mutexLock(pObj->lock);

        s =  buddy(pTmp, pBuddyHeadNode); // s指向p的伙伴的地址
    while(s >= pObj->pNodeStart && s <= pObj->pNodeEnd && (!s->tag) && s->kval == pTmp->kval)
    {
        if (s->prelink == s && s->nextlink == s) // 链表上仅一个节点
        {
            pBuddyHeadNode[s->kval].first = NULL;
        }
        else
        {
            s->prelink->nextlink = s->nextlink;
            s->nextlink->prelink = s->prelink;

            if (pBuddyHeadNode[s->kval].first == s) // s是链表的首节点
            {
                pBuddyHeadNode[s->kval].first = s->nextlink;
            }
        }

        if ((int)(pTmp - pObj->pNodeStart) % (int)pow(2, pTmp->kval + 1) == 0) // pTmp为前块
        {
            pTmp->kval++;
        }
        else
        {
            s->kval = pTmp->kval + 1;
            pTmp = s;
        }

        s =  buddy(pTmp, pBuddyHeadNode);
    }

pTmp->tag = 0;
    if (!pBuddyHeadNode[pTmp->kval].first)
    {
        pBuddyHeadNode[pTmp->kval].first = pTmp->prelink = pTmp->nextlink = pTmp;
    }
    else
    {
        pTmp->nextlink = pBuddyHeadNode[pTmp->kval].first;
        pTmp->prelink = pTmp->nextlink->prelink;
        pTmp->nextlink->prelink = pTmp;
        pTmp->prelink->nextlink = pTmp;
        pBuddyHeadNode[pTmp->kval].first = pTmp;
    }

    OSAL_mutexUnlock(pObj->lock);

    return OSAL_OK;
}

void  buddyPrintLayout( BuddyHeadNode *pBuddyHeadNode)
{
    Int32         k    = 0;
    Int32         mark = 0;
     BuddyNode *r   = NULL;    
     BuddySys  *pObj = NULL;
    pObj = &(pBuddyHeadNode[0].vdsBuddySys);

    for (k = 0, mark = 0; k <= pObj->params.blockNum; k++) //判断内存是否被沾满
    {
        if (pBuddyHeadNode[k].first)
        {
            mark = 1;
            break;
        }
    }

    if (!mark)
    {
        OSAL_INFO("buddy system is full\n");
    }
    else
    {
        OSAL_INFO("empty mem:\n");

        for (k = 0; k <= pObj->params.blockNum; k++)
        {
            r = pBuddyHeadNode[k].first;
            if (r)
            {
                OSAL_INFO("|%d <-->%d", r - pObj->pNodeStart + 1, r + (int)pow(2, r->kval) - pObj->pNodeStart);
                while (r->nextlink != pBuddyHeadNode[k].first)
                {
                    r = r->nextlink;
                    OSAL_INFO("|%d <-->%d", r - pObj->pNodeStart + 1, r + (int)pow(2, r->kval) - pObj->pNodeStart);
                }
            }
        }
    }

    OSAL_INFO("\n");
}

Int32  buddyGetMmzPoolId( BuddyHeadNode *pBuddyHeadNode, Int32 *pPoolId)
{
    OSAL_assertNotNull(pBuddyHeadNode);
    OSAL_assertNotNull(pPoolId);

     BuddySys  *pObj = NULL;
    pObj = &(pBuddyHeadNode[0].vdsBuddySys);

    if ( BUDDY_MEM_TYPE_MMZ == pObj->params.memType)
    {
        //*pPoolId = pObj->poolBaseInfo.poolId;
    }
    else
    {
        OSAL_ERROR("memType :%d, don't have poolId\n", pObj->params.memType);
        return OSAL_FAIL;
    }

    return OSAL_OK;
}
#endif

///////////////////////////////////////////////////////////////////////////////
预分配:
#ifndef __VDS_PBMM_H__
#define __VDS_PBMM_H__

#include <osal.h> 

#ifdef __cplusplus
extern "C" {
#endif

typedef Handle VDS_pbmmHndl;

typedef struct
{
    Uint32 virtAddr;
    Uint32 bufSize;

}VDS_pbmmInfo;

//每个图片比特流的缓冲区描述
typedef struct
{
    Uint32 virtAddr;
    Uint32 phyAddr;
    Uint32 bufSize;
    Uint32 usedSize;
    Uint32 offset;
    Uint32 privData;

}VDS_picBitBuf;


//创建图片比特流缓冲区管理的创建参数
typedef struct 
{
    Uint32 align;

    Uint32 bitStartAddr;    ///< 图片比特流区域首地址
    Uint32 bitEndAddr;      ///< 图片比特流区域首地址
    Uint32 bitSz;           ///< 图片比特流区域首地址    
} VDS_pbmmCreate;

/*******************************************************************************
* 函数名  : VDS_pbmmDumpInfo
*******************************************************************************/
void VDS_pbmmDumpInfo(void);

/*******************************************************************************
* 函数名  : VDS_pbmmPreAlloc
* 描  述  : 不用的内存还到总的缓冲池

*******************************************************************************/
Int32 VDS_pbmmPreAlloc(VDS_pbmmHndl hEfmCmb, Uint32 length, VDS_picBitBuf *pBuf);

/*******************************************************************************
* 函数名  : VDS_pbmmReportLength
* 描  述  : 不用的内存还到总的缓冲池
*******************************************************************************/
Int32 VDS_pbmmReportLength(VDS_pbmmHndl hEfmCmb, Uint32 length);
/*******************************************************************************
* 函数名  : VDS_pbmmFree
* 描  述  : 释放缓冲区接口
*******************************************************************************/
Int32 VDS_pbmmFree(VDS_pbmmHndl hEfmCmb, Uint32 privData);

/*******************************************************************************
* 函数名  : VDS_pbmmInit
*******************************************************************************/
Int32 VDS_pbmmInit(VDS_pbmmCreate *pCreate, VDS_pbmmHndl *phEfmCmb);
Int32 VDS_pbmmDeInit(VDS_pbmmHndl phEfmCmb);

/*******************************************************************************
* 函数名  : VDS_pbmmGetInfo
* 描  述  : 得到图片比特流缓冲区的物理地址信息
*******************************************************************************/
Int32 VDS_pbmmGetInfo(VDS_pbmmInfo *pInfo);
#ifdef __cplusplus
}
#endif
#endif /* __VDS_PBMM_H__ */

/// .c
//////////////////// .c

#include <vds_pbmm.h>
#include <vds_pymm.h>
#include <vds_comapi.h>
#include <vds_frmShare.h>

#define VDS_PBMM_MAX_BLOCK   (16)

typedef enum
{
    VDS_PBMM_BUF_EMPTY = 0,
    VDS_PBMM_BUF_ALLOCED,
    VDS_PBMM_BUF_RELEASED,
    VDS_PBMM_BUF_RECLAIMED = VDS_PBMM_BUF_EMPTY
}Vds_pbmmtatus;

typedef struct
{
    Uint32 virtAddr;
    Uint32 phyAddr;
    Uint32 bufLen;
    Uint32 index;
    Uint32 status;                              ///<参考 IVS_CMB_STATUS
}Vds_pbmmPrivBlock;

typedef struct
{
    Uint32 init;
    Uint32 virtAddr;                           //连续内存的虚拟起始地址
    Uint32 phyAddr;                            //连续内存的物理地址
    Uint32 bufSize;                             //连续内存的长度

    Uint32 align;    
    Uint32 usedEndOffset;
    Uint32 usedStartOffset;
    Uint32 lastAllocOffset;
    Int32 fd;

    Uint32 lastAllocIndex;
    Vds_pbmmPrivBlock blockArray[VDS_PBMM_MAX_BLOCK];
    Uint32 lastReclaimIndex;

}Vds_pbmmObj;

static Vds_pbmmObj  gPbmmObj;

Int32 VDS_pbmmPreAlloc(VDS_pbmmHndl hEfmCmb, Uint32 length, VDS_picBitBuf *pBuf)
{
    Int32 status = OSAL_FAIL;
    Vds_pbmmObj *pObj = hEfmCmb;
    Vds_pbmmPrivBlock *pBlock = NULL;

    Uint32 bufLeft = 0;

    if (pObj == NULL)
    {
        OSAL_ERROR("hEfmCmb is null\n");
        return OSAL_FAIL;
    }
    do
    {
        if(pObj->usedEndOffset >= pObj->usedStartOffset)
        {
            bufLeft = pObj->bufSize - pObj->usedEndOffset;
            if(bufLeft >= length)
            {
                pBuf->bufSize   = length;
                pBuf->usedSize  = 0;
                pBuf->phyAddr   = pObj->phyAddr + pObj->usedEndOffset;
                pBuf->virtAddr  = pObj->virtAddr + pObj->usedEndOffset;
                pBuf->offset    = pObj->usedEndOffset;

                pObj->lastAllocOffset = pObj->usedEndOffset;

                status = OSAL_OK;
                break;
            }
        else
            {
                bufLeft = pObj->usedStartOffset;
                if(bufLeft > length)
                {
                    pBuf->bufSize   = length;
                    pBuf->usedSize  = 0;
                    pBuf->phyAddr   = pObj->phyAddr ;
                    pBuf->virtAddr  = pObj->virtAddr ;
                    pBuf->offset    = 0;

                    pObj->lastAllocOffset = 0;
                    status = OSAL_OK;
                    break;
                }
            }
        }
    else
        {
            bufLeft = pObj->usedStartOffset - pObj->usedEndOffset;
            if(bufLeft >= length)
            {
                pBuf->bufSize   = length;
                pBuf->usedSize  = 0;
                pBuf->phyAddr   = pObj->phyAddr + pObj->usedEndOffset;
                pBuf->virtAddr  = pObj->virtAddr + pObj->usedEndOffset;
                pBuf->offset    = pObj->usedEndOffset;

                pObj->lastAllocOffset = pObj->usedEndOffset;
                status = OSAL_OK;
                break;
            }
        }

    } while(0);
if (status == OSAL_OK)
    {
        pBlock = &pObj->blockArray[pObj->lastAllocIndex];

        if (pBlock->status != VDS_PBMM_BUF_EMPTY)
        {
            OSAL_ERROR("block's status=%d,allocIndex=%d\n",
                    pBlock->status,
                    pObj->lastAllocIndex);
            status = OSAL_FAIL;
        }
        else
        {
            pBlock->phyAddr = pBuf->phyAddr;
            pBlock->virtAddr = pBuf->virtAddr;

            pBuf->privData = pObj->lastAllocIndex;
#ifdef VDS_PBMM_DEBUG      
            OSAL_INFOCYAN("privData=%d is Malloc!\n", pBuf->privData);
#endif
        }
    }

    return status;
}

Int32 VDS_pbmmReportLength(VDS_pbmmHndl hEfmCmb, Uint32 length)
{
    Vds_pbmmObj *pObj = hEfmCmb;

    length = OSAL_align(length, pObj->align);

    pObj->usedEndOffset = pObj->lastAllocOffset + length;

    pObj->blockArray[pObj->lastAllocIndex].bufLen = length;
    pObj->blockArray[pObj->lastAllocIndex].status = VDS_PBMM_BUF_ALLOCED;

    pObj->lastAllocIndex = (pObj->lastAllocIndex + 1 ) & (VDS_PBMM_MAX_BLOCK - 1);

    return OSAL_OK;
}

Int32 VDS_pbmmFree(VDS_pbmmHndl hEfmCmb, Uint32 privData)
{
    Vds_pbmmObj *pObj = hEfmCmb;
    Uint32 index = 0;
    Uint32 i = 0;

    if (privData >= VDS_PBMM_MAX_BLOCK)
    {
        OSAL_ERROR("privData=%d,out of range\n",privData);
        return OSAL_FAIL;
    }

    Vds_pbmmPrivBlock *pBlock = &pObj->blockArray[privData];
    if (pBlock->status != VDS_PBMM_BUF_ALLOCED)
    {
        OSAL_ERROR("pBlock->status =%d\n",pBlock->status);
        return OSAL_FAIL;
    }

    pBlock->status = VDS_PBMM_BUF_RELEASED;

    index = pObj->lastReclaimIndex;
#ifdef VDS_PBMM_DEBUG
    OSAL_INFOCYAN("privData=%d is Free, lastReclaimIndex %u\n"
    , privData
    , pObj->lastReclaimIndex);
#endif

    for (i = 0; i < VDS_PBMM_MAX_BLOCK; i++)
    {

        pBlock = &pObj->blockArray[index];

        if (pBlock->status != VDS_PBMM_BUF_RELEASED)
        {
            break;
        }
        else //reclaim
        {
            pObj->usedStartOffset =
                        (pBlock->virtAddr - pObj->virtAddr) + pBlock->bufLen;

            pBlock->virtAddr = 0;
            pBlock->phyAddr  = 0;
            pBlock->bufLen   = 0;
            pBlock->index    = 0;
            pBlock->status   = VDS_PBMM_BUF_RECLAIMED;

            pObj->lastReclaimIndex =
                        (pObj->lastReclaimIndex + 1 ) & (VDS_PBMM_MAX_BLOCK - 1);
        }

        index = (index + 1) & (VDS_PBMM_MAX_BLOCK - 1);
    }

#ifdef VDS_PBMM_DEBUG
    OSAL_INFOCYAN("lastReclaimIndex %u\n"
        , pObj->lastReclaimIndex);
#endif

    return OSAL_OK;
}

Int32 VDS_pbmmInit(VDS_pbmmCreate *pCreate, VDS_pbmmHndl *phEfmCmb)
{
    Int32 status = OSAL_FAIL;
    Vds_pbmmObj *pObj =  &gPbmmObj;
    Uint32 *mapVirAddr = OSAL_NULL;

    if(pCreate == NULL)
    {
        OSAL_ERROR("pCreate is null\n");
        return OSAL_FAIL;
    }

    OSAL_clear(pObj);

    pObj->fd = open(PICMEM_DEV_NAME, O_RDWR);

    if (pObj->fd < 0)
    {
       OSAL_ERROR("open()\n");
       return status;
    }

pObj->phyAddr = pCreate->bitStartAddr;
    pObj->bufSize = pCreate->bitSz;

    OSAL_INFO("mmap: baseaddr %p, size %x\n", pObj->phyAddr, pObj->bufSize);

    mapVirAddr = (Uint32 *)mmap(OSAL_NULL, pObj->bufSize, 
                                    PROT_READ | PROT_WRITE, 
                                    MAP_SHARED, 
                                    pObj->fd, 
                                    pObj->phyAddr);
    if (mapVirAddr == MAP_FAILED)
    {
        OSAL_ERROR("Failed to mmap buffer (%s)\n", strerror(errno));
        close(pObj->fd);
        return OSAL_FAIL;
    }

    OSAL_clearSize(mapVirAddr, pObj->bufSize);

    pObj->align = pCreate->align !=0 ? pCreate->align : 1;
pObj->virtAddr  = OSAL_align((Uint32)mapVirAddr, pObj->align);
    pObj->phyAddr   = pObj->phyAddr + ((Uint32)mapVirAddr - pObj->virtAddr);
    pObj->bufSize   = pObj->bufSize - ((Uint32)mapVirAddr - pObj->virtAddr);

    OSAL_INFO("[PicBmm] Init Ok! mapVirAddr %p, pObj->virtAddr %p, size %x\n"
        , mapVirAddr, pObj->virtAddr, pObj->bufSize);

    pObj->init = OSAL_TRUE;

    *phEfmCmb = pObj;

    return OSAL_OK;
}

Int32 VDS_pbmmDeInit(VDS_pbmmHndl phEfmCmb)
{
    Vds_pbmmObj *pObj =  phEfmCmb;

    munmap((void *)pObj->virtAddr, pObj->bufSize);

   return OSAL_OK;
}

Int32 VDS_pbmmGetInfo(VDS_pbmmInfo *pInfo)
{
    Int32 status = OSAL_FAIL;
    Vds_pbmmObj *pObj =  &gPbmmObj;

    if (OSAL_TRUE == pObj->init)
    {
        pInfo->virtAddr = pObj->virtAddr;
        pInfo->bufSize  = pObj->bufSize;
        status = OSAL_OK;
    }

    return status;
}

void VDS_pbmmDumpInfo(void)
{
    Int32 i = 0;
    Vds_pbmmObj *pObj = &gPbmmObj;
    Vds_pbmmPrivBlock *pBlock = NULL;

    OSAL_INFO("usedStartOffset=%u,usedEndOffset=%u,"
    "lastAllocOffset=%u,lastAllocIndex=%u,lastReclaimIndex=%u\n",
        pObj->usedStartOffset, pObj->usedEndOffset,
        pObj->lastAllocOffset, pObj->lastAllocIndex, pObj->lastReclaimIndex);

    for(i = 0; i< VDS_PBMM_MAX_BLOCK; i++)
    {
        pBlock = &pObj->blockArray[i];

        OSAL_INFO("index=%d, virtAddr=%x,phyAddr=%x,bufLen=%u,index=%u,status=%u\n",
            i, pBlock->virtAddr, pBlock->phyAddr,
            pBlock->bufLen, pBlock->index, pBlock->status);

    }

}

///////////////////////////////////////////////////////////////////////////
ruffer buf:

#ifndef _VDS_RINGBUFFER_H_
#define _VDS_RINGBUFFER_H_
#include <osal.h>

#ifdef __cplusplus
extern "C"{
#endif /* __cplusplus */

#define MAXRINGCHN  4
#define BF_CHANNEL  0
#define MERGE_CHANNEL 1
#define IVS_CHANNEL 2
#define DEC_CHANNEL 3

typedef struct tagVDS_ringBufSets
{
    Uint32 size;    /* ringBuf 申请大小 */
    Uint8  alignValue; /* 若需要对齐,对齐字节数,采用向上对齐 */
    Uint8  res[3];
}VDS_ringBufSets;

typedef struct VDS_ringBuffer
{
    Ptr    basePhyAddr;   
    Ptr    baseVirtAddr;
    Uint32  totalSize;
    Uint32  wrOfst;
    Uint32  rdOfst;
    Int32   encodedStreamCount;
    OSAL_MutexHandle  bufferLock;
    Uint32   getCnt;
    Uint32   rlsCnt;
    VDS_ringBufSets sets;    
} VDS_ringBuffer;

typedef VDS_ringBuffer* VDS_ringBufferHndl;
Int32 VDS_ringBufferInit(VDS_ringBufferHndl ringBufferHnl, VDS_ringBufSets *pSets);
Bool VDS_ringBufferiIsFull(VDS_ringBufferHndl ringBufferHnl);
Bool VDS_ringBufferIsEmpty(VDS_ringBufferHndl ringBufferHnl);
Bool VDS_ringBufferPrintInfo(VDS_ringBufferHndl ringBufferHnl);
Int32 VDS_ringBufferUpdateRdOfst(VDS_ringBufferHndl ringBufferHnl, Uint32 length);
Int32 VDS_ringBufferUpdateWrOfst(VDS_ringBufferHndl ringBufferHnl, Uint32 length);
Int32 VDS_ringBufferUpdateEncodedStreamCount(VDS_ringBufferHndl ringBufferHnl, Bool increment);
Int32 VDS_ringBufferDeInit(VDS_ringBufferHndl ringBufferHnl);
VDS_ringBufferHndl VDS_ringBufferOpen(Int32 chId);
Int32 VDS_ringBufferGetBuf(VDS_ringBufferHndl rbHndl,Sizet* addr,Uint32 size);
Int32 VDS_ringBufferRls(Handle Hndl,Sizet addr,Uint32 size);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif

///////////////////////////////// .c 
#include <vds_ringBuffer.h>
#include "mpi_sys.h"
VDS_ringBuffer gringBuffer[MAXRINGCHN];
VDS_ringBufferHndl VDS_ringBufferOpen(Int32 chId)
{
    if((chId < 0)||(chId > MAXRINGCHN))
    {
        OSAL_ERROR("chId[%d] is not right\n",chId);
        return NULL;
    }

    return &gringBuffer[chId];
}

Int32 VDS_ringBufferInit(VDS_ringBufferHndl ringBufferHnl, VDS_ringBufSets *pSets)
{
    Int32 status = 0;
    Sizet pBasePhyAddr=0;
    Ptr pBaseVirtAddr = 0;

    if (OSAL_isNull(pSets) || OSAL_isNull(ringBufferHnl))
    {
        OSAL_ERROR("VDS_ringBufferInit param err\n");
        return OSAL_FAIL;
    }

    memset(ringBufferHnl, 0, sizeof(*ringBufferHnl));
    status = HI_MPI_SYS_MmzAlloc((HI_U32*)&pBasePhyAddr,&pBaseVirtAddr,
        "SYSMEM", OSAL_NULL, pSets->size);
    if(status < 0)
    {       
        OSAL_ERROR("malloc failed size=%u\n", pSets->size);
        return -1;
    }
    OSAL_assert(pBaseVirtAddr != NULL);
ringBufferHnl->baseVirtAddr = pBaseVirtAddr; 
    ringBufferHnl->basePhyAddr= (Ptr)pBasePhyAddr;
    ringBufferHnl->encodedStreamCount = 0;
    ringBufferHnl->rdOfst = 0;
    ringBufferHnl->wrOfst = 0;
    ringBufferHnl->totalSize = pSets->size;
    status = OSAL_mutexCreate(OSAL_MUTEX_NORMAL,&ringBufferHnl->bufferLock);
    if(status < 0)
    {
        OSAL_ERROR("create mutex error\n");
        return -1; 
    }

    OSAL_memCpySize(&ringBufferHnl->sets, pSets, sizeof(ringBufferHnl->sets));

    return 0;
}

Bool VDS_ringBufferIsFull(VDS_ringBufferHndl ringBufferHnl)
{
    if ((ringBufferHnl->wrOfst == ringBufferHnl->rdOfst) &&
            (ringBufferHnl->encodedStreamCount !=0))
        return OSAL_TRUE;
    else 
        return OSAL_FALSE;

}
Bool VDS_ringBufferIsEmpty(VDS_ringBufferHndl ringBufferHnl)
{
    if ((ringBufferHnl->wrOfst == ringBufferHnl->rdOfst)
            && (ringBufferHnl->encodedStreamCount ==0))
        return OSAL_TRUE;
    else 
        return OSAL_FALSE;
}
Bool VDS_ringBufferPrintInfo(VDS_ringBufferHndl ringBufferHnl)
{
     OSAL_INFO("\n******************ring buffer info *********************\n");
     OSAL_INFO ("ring buffer info ringBufferHnl->baseAddr:0x%x\n" ,ringBufferHnl->baseVirtAddr);
     OSAL_INFO ("ring buffer info ringBufferHnl->totalSize:0x%x\n" ,ringBufferHnl->totalSize);
     OSAL_INFO ("ring buffer info ringBufferHnl->wrOfst:0x%x\n" ,ringBufferHnl->wrOfst);
     OSAL_INFO ("ring buffer info ringBufferHnl->rdOfst:0x%x\n" ,ringBufferHnl->rdOfst);
     OSAL_INFO ("ring buffer info ringBufferHnl->encodedStreamCount:%d\n" ,ringBufferHnl->encodedStreamCount);
     OSAL_INFO ("ring buffer info ringBufferHnl->ringBufferLock:0x%x\n" ,ringBufferHnl->bufferLock);
     return OSAL_TRUE;
}

Int32 VDS_ringBufferUpdateRdOfst(VDS_ringBufferHndl ringBufferHnl, Uint32 length)
{
    length = OSAL_align(length, ringBufferHnl->sets.alignValue);

    OSAL_mutexLock(ringBufferHnl->bufferLock);

    ringBufferHnl->rdOfst = length % ringBufferHnl->totalSize;

    OSAL_mutexUnlock(ringBufferHnl->bufferLock);
    return 0;
}

Int32 VDS_ringBufferUpdateWrOfst(VDS_ringBufferHndl ringBufferHnl, Uint32 length)
{
    length = OSAL_align(length, ringBufferHnl->sets.alignValue);    

    OSAL_mutexLock(ringBufferHnl->bufferLock);
    ringBufferHnl->wrOfst = (ringBufferHnl->wrOfst + length)%ringBufferHnl->totalSize;
    OSAL_mutexUnlock(ringBufferHnl->bufferLock);

    return 0;
}
Int32 VDS_ringBufferUpdateEncodedStreamCount(VDS_ringBufferHndl ringBufferHnl,
    Bool increment)
{

    OSAL_mutexLock(ringBufferHnl->bufferLock);    
    if(increment)
        ringBufferHnl->encodedStreamCount++;
    else
        ringBufferHnl->encodedStreamCount--;

    OSAL_mutexUnlock(ringBufferHnl->bufferLock);    

    return 0;
}

Int32 VDS_ringBufferGetBuf(VDS_ringBufferHndl rbHndl,Sizet* addr,Uint32 size)
{
    Uint32 rbLength = 0;
    Sizet rbAddr = 0;

    size = OSAL_align(size, rbHndl->sets.alignValue);
    if(rbHndl->wrOfst > rbHndl->rdOfst) // case1
    {
        rbAddr = ((Sizet)rbHndl->baseVirtAddr+  rbHndl->wrOfst);
        rbLength = rbHndl->totalSize - rbHndl->wrOfst;
        if(rbLength < size)
        {
            Uint32 tmpSize = rbHndl->rdOfst;
            if(tmpSize > size)
            {
                VDS_ringBufferUpdateWrOfst(rbHndl,rbLength);
                rbAddr = (Sizet)rbHndl->baseVirtAddr + rbHndl->wrOfst;             
                rbLength = rbHndl->rdOfst - rbHndl->wrOfst;
            }
            else
            {
                OSAL_ERROR("buffer is not enough,rbLength is %d,"\
                        "size is %d,getCnt is %d,rlsCnt is %d baseVirtAddr %p totalSize %d wrOfst %d rdOfst %d\n",
                        rbLength,size,rbHndl->getCnt,rbHndl->rlsCnt
                        ,rbHndl->baseVirtAddr,rbHndl->totalSize,rbHndl->wrOfst,rbHndl->rdOfst);
            }
        }        
    }
else if(rbHndl->wrOfst == rbHndl->rdOfst)
    {
        if(rbHndl->rlsCnt == rbHndl->getCnt)
        {
            rbAddr = ((Sizet)rbHndl->baseVirtAddr+    rbHndl->wrOfst);
            rbLength = rbHndl->totalSize - rbHndl->wrOfst;
            if(rbLength < size)
            {
                Uint32 tmpSize = rbHndl->rdOfst;
                if(tmpSize > size)
                {
                    VDS_ringBufferUpdateWrOfst(rbHndl,rbLength);
                    rbAddr = (Sizet)rbHndl->baseVirtAddr + rbHndl->wrOfst;               
                    rbLength = rbHndl->rdOfst - rbHndl->wrOfst;
                }
                else
                {
                    OSAL_ERROR("buffer is not enough,rbLength is %d,"\
                            "size is %d,getCnt is %d,rlsCnt is %d baseVirtAddr %p totalSize %d wrOfst %d rdOfst %d\n",
                            rbLength,size,rbHndl->getCnt,rbHndl->rlsCnt
                            ,rbHndl->baseVirtAddr,rbHndl->totalSize,rbHndl->wrOfst,rbHndl->rdOfst);
                }
            }         
        }
        else
        {
            OSAL_ERROR("rb buff is full\n");
        }
    }
else
    {
        rbAddr = (Sizet)rbHndl->baseVirtAddr + rbHndl->wrOfst;
        rbLength = rbHndl->rdOfst - rbHndl->wrOfst;
    }

    if(rbLength < size)
    {
        OSAL_ERROR("buffer is not enough,rbLength is %d,"\
        "size is %d,getCnt is %d,rlsCnt is %d baseVirtAddr %p totalSize %d wrOfst %d rdOfst %d\n",
        rbLength,size,rbHndl->getCnt,rbHndl->rlsCnt
        ,rbHndl->baseVirtAddr,rbHndl->totalSize,rbHndl->wrOfst,rbHndl->rdOfst);
        *addr = 0;
        return -1;
    }
    else
    {
        *addr = rbAddr;
        rbHndl->getCnt++;
        return 0;
    }
}

Int32 VDS_ringBufferRls(Handle Hndl,Sizet addr,Uint32 size)
{
    VDS_ringBufferHndl pHndl = (VDS_ringBufferHndl)Hndl;
    OSAL_assert(pHndl != NULL);

    size = OSAL_align(size, pHndl->sets.alignValue);

    pHndl->rlsCnt++;
    VDS_ringBufferUpdateRdOfst(pHndl,
        (addr - (Sizet)pHndl->baseVirtAddr) + size);
    VDS_ringBufferUpdateEncodedStreamCount(pHndl, OSAL_FALSE);
    return 0;

}
Int32 VDS_ringBufferDeInit(VDS_ringBufferHndl ringBufferHnl)
{

    HI_MPI_SYS_MmzFree((Sizet)ringBufferHnl->basePhyAddr, ringBufferHnl->baseVirtAddr);

    ringBufferHnl->baseVirtAddr                = NULL;   
    ringBufferHnl->basePhyAddr                = NULL;
    ringBufferHnl->totalSize                 = 0;
    ringBufferHnl->wrOfst                    = 0;
    ringBufferHnl->rdOfst                     = 0;
    ringBufferHnl->encodedStreamCount        = 0;
    ringBufferHnl->rlsCnt                   = 0;
    ringBufferHnl->getCnt                   = 0;

    OSAL_mutexDelete(&ringBufferHnl->bufferLock);

    return 0;
}
我来回答
回答0个
时间排序
认可量排序
易百纳技术社区暂无数据
或将文件直接拖到这里
悬赏:
E币
网盘
* 网盘链接:
* 提取码:
悬赏:
E币

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
+ 添加网盘链接/附件

Markdown 语法

  • 加粗**内容**
  • 斜体*内容*
  • 删除线~~内容~~
  • 引用> 引用内容
  • 代码`代码`
  • 代码块```编程语言↵代码```
  • 链接[链接标题](url)
  • 无序列表- 内容
  • 有序列表1. 内容
  • 缩进内容
  • 图片![alt](url)
相关问答
更多相似问答
举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

易百纳技术社区