?? os_mem.c
字號:
/*********************************************************************************************************
** Small RTOS(51)
** The Real-Time Kernel(For Keil c51)
**
** (c) Copyright 2002-2003, chenmingji
** All Rights Reserved
**
** V1.20.0
**
**
**--------------文件信息--------------------------------------------------------------------------------
**文 件 名: OS_mem.c
**創(chuàng) 建 人: 陳明計
**最后修改日期: 2003年8月3日
**描 述: 內(nèi)存動態(tài)分配模塊,可以在非Small RTOS(51)下使用。在Small RTOS(51)
** 下必須配置為支持重入棧。
**--------------歷史版本信息----------------------------------------------------------------------------
** 創(chuàng)建人: 陳明計
** 版 本: V1.20.0
** 日 期: 2003年8月3日
** 描 述: 原始版本
**
**------------------------------------------------------------------------------------------------------
**--------------當前版本修訂------------------------------------------------------------------------------
** 修改人:
** 日 期:
** 描 述:
**
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
#define IN_OS_MEM
#include "config.h"
#ifndef EN_OS_MEM
#define EN_OS_MEM 0
#endif
#if EN_OS_MEM > 0
static struct _FreeMem xdata *OSFreeMem; /* 自由內(nèi)存塊的雙向鏈表的頭 */
/*********************************************************************************************************
** 函數(shù)名稱: UserMemChkErr
** 功能描述: 內(nèi)存回收時出錯處理函數(shù),將EN_UserMemChkErr定義為1時,用戶可以自己定義這個函數(shù)。
** 輸 入: Addr: 應當回收的內(nèi)存塊
** 輸 出: 無
** 全局變量: 無
** 調(diào)用模塊: 無
**
** 作 者: 陳明計
** 日 期: 2003年8月3日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
#if EN_OS_MEM_CHK > 0 && EN_UserMemChkErr == 0
void UserMemChkErr(void xdata *Addr) reentrant
{
Addr = Addr;
while (1);
}
#endif
/*********************************************************************************************************
** 函數(shù)名稱: OSMemInit
** 功能描述: 初始化動態(tài)內(nèi)存分配模塊。
** 輸 入: Addr: 指向空閑空間起始位置的指針
** MemSize: 空閑空間的大小
** 輸 出: TRUE: 成功
** FALSE: 失敗
** 全局變量: 無
** 調(diào)用模塊: 無
**
** 作 者: 陳明計
** 日 期: 2003年8月3日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint8 OSMemInit(void xdata *Addr, unsigned int MemSize)
{
struct _FreeMem xdata *MemFree;
MemSize = MemSize & ~(sizeof(int) - 1); /* 內(nèi)存按照字(word)為單位分配 */
/* 調(diào)整MemSize為字(word)的整數(shù)倍 */
/* 判斷自由空間是否有效 */
if (Addr != NULL && MemSize > sizeof(struct _UsingMem))
{
/* 建立只有一個節(jié)點的雙向隊列 */
OS_ENTER_CRITICAL();
MemFree = (struct _FreeMem xdata *)Addr;
OSFreeMem = MemFree;
MemFree->Size = MemSize;
MemFree->Next = NULL;
MemFree->Last = NULL;
OS_EXIT_CRITICAL();
return TRUE;
}
else
{
return FALSE;
}
}
/*********************************************************************************************************
** 函數(shù)名稱: OSMemNew
** 功能描述: 分配內(nèi)存。
** 輸 入: Size: 所需內(nèi)存的大小
** 輸 出: 指向已分配的內(nèi)存開始的地址的指針,NULL為失敗。
** 全局變量: 無
** 調(diào)用模塊: 無
**
** 作 者: 陳明計
** 日 期: 2003年8月3日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void xdata *OSMemNew(unsigned int Size) reentrant
{
struct _FreeMem xdata *ThisFreeMem;
struct _UsingMem xdata *Rt;
OS_ENTER_CRITICAL();
ThisFreeMem = OSFreeMem;
/* 調(diào)整應當分配的大小(必須為字(word))的整數(shù)倍,且要加入分配給頭的空間 */
Size = ((Size + sizeof(int) - 1) & ~(sizeof(int) - 1)) +
sizeof(struct _UsingMem);
/* 查找足夠大的自由內(nèi)存塊 */
while(ThisFreeMem != NULL)
{
if ((ThisFreeMem->Size) >= Size)
{
break;
}
ThisFreeMem = ThisFreeMem->Next;
}
if (ThisFreeMem != NULL)
{
if ((ThisFreeMem->Size) < (Size + sizeof(struct _FreeMem)))
{
/* 分配后剩余內(nèi)存太小則整塊自由內(nèi)存分配出去 */
/* 即在雙向鏈表中刪除這個節(jié)點 */
if (ThisFreeMem->Next != NULL)
{
(ThisFreeMem->Next)->Last = ThisFreeMem->Last;
}
if (ThisFreeMem->Last)
{
(ThisFreeMem->Last)->Next = ThisFreeMem->Next;
}
Size = ThisFreeMem->Size;
Rt = (struct _UsingMem xdata *)(ThisFreeMem);
}
else
{
/* 否則從自由內(nèi)存塊的高地址端分配一塊內(nèi)存 */
/* 即僅僅調(diào)整這個節(jié)點的內(nèi)容 */
ThisFreeMem->Size -= Size;
Rt = (struct _UsingMem xdata *)((uint8 xdata *)ThisFreeMem +
ThisFreeMem->Size);
}
#if EN_OS_MEM_CHK > 0
Rt->HeadChk = 0xa55a;
Rt->EndChk = 0x5aa5;
#endif
Rt->Size = Size;
OS_EXIT_CRITICAL();
return ( void *)((uint8 xdata *)Rt + sizeof(struct _UsingMem));
}
else
{
OS_EXIT_CRITICAL();
return NULL;
}
}
/*********************************************************************************************************
** 函數(shù)名稱: OSMemFree
** 功能描述: 把由OSMemNew分配的空間歸還給系統(tǒng)
** 輸 入: Addr: 由指OSMemNew返回的指針
** 輸 出: 無
** 全局變量: 無
** 調(diào)用模塊: 無
**
** 作 者: 陳明計
** 日 期: 2003年8月3日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
#ifndef EN_OS_MEM_FREE
#define EN_OS_MEM_FREE 1
#endif
#if EN_OS_MEM_FREE > 0
void OSMemFree(void xdata *Addr) reentrant
{
struct _FreeMem xdata *ThisFreeMem;
struct _UsingMem xdata *UserMem;
unsigned int Size;
OS_ENTER_CRITICAL();
ThisFreeMem = OSFreeMem;
/* 找到內(nèi)存塊的開始位置 */
UserMem = (struct _UsingMem xdata *)((uint8 xdata *)Addr -
sizeof(struct _UsingMem));
#if EN_OS_MEM_CHK > 0
if (UserMem->HeadChk != 0xa55a || UserMem->EndChk != 0x5aa5)
{
UserMemChkErr(Addr);
OS_EXIT_CRITICAL();
return;
}
#endif
/* 查找這塊內(nèi)存應當在雙向鏈表中插入的位置 */
/* 雙向鏈表以內(nèi)存塊首地址的大小順序為節(jié)點的鏈接順序 */
while (1)
{
if (ThisFreeMem > (struct _FreeMem xdata *)UserMem)
{
ThisFreeMem = ThisFreeMem->Last;
break;
}
if (ThisFreeMem->Next == NULL)
{
break;
}
ThisFreeMem = ThisFreeMem->Next;
}
if (((uint8 xdata *)ThisFreeMem + (ThisFreeMem->Size)) == (uint8 xdata *)UserMem)
{
/* 回收的內(nèi)存塊與這一個自由內(nèi)存塊相鄰,則直接修改這個節(jié)點內(nèi)容 */
ThisFreeMem->Size += UserMem->Size;
}
else
{
/* 否則插入一個節(jié)點 */
Size = UserMem->Size;
((struct _FreeMem xdata *)UserMem)->Last = ThisFreeMem;
((struct _FreeMem xdata *)UserMem)->Next = ThisFreeMem->Next;
((struct _FreeMem xdata *)UserMem)->Size = Size;
ThisFreeMem->Next = (struct _FreeMem xdata *)UserMem;
ThisFreeMem = (struct _FreeMem xdata *)UserMem;
if (ThisFreeMem->Next != NULL)
{
(ThisFreeMem->Next)->Last = ThisFreeMem;
}
}
if (((uint8 xdata *)ThisFreeMem + (ThisFreeMem->Size)) ==
(uint8 xdata *)(ThisFreeMem->Next))
{
/* 如果這兩個內(nèi)存塊相鄰,則合并之 */
ThisFreeMem->Size += (ThisFreeMem->Next)->Size;
ThisFreeMem->Next = (ThisFreeMem->Next)->Next;
if(ThisFreeMem->Next != NULL)
{
(ThisFreeMem->Next)->Last = ThisFreeMem;
}
}
OS_EXIT_CRITICAL();
return;
}
#endif
#endif
/*********************************************************************************************************
** End Of File
********************************************************************************************************/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -