www.pudn.com > r&s1.10°æ±¾£«Îĵµ.rar > kmm.c
/*
===============================================================================
| Copyright (C) 2004 RuanHaiShen, All rights reserved.
| SUMMARY:
| Memory management implementation.
|
| DESCRIPTION:
| See http://www.01s.org for documentation, latest information, license
| and contact details.
| email:ruanhaishen@01s.org
=============================================================================*/
/*===========================================================================*/
#include "arch/arch.h"
#include "inc/queue.h"
#include "inc/kernel.h"
#include "inc/memory.h"
#include "inc/ipc.h"
#include "inc/kapi.h"
#if CFG_MM_EN > 0
#define PAGE_SIZE (sizeof(_mms)/sizeof(mm_t))
#define MM_USED ((u8)(((u32)MM_START) >> 24) - 1)
#ifdef CFG_MM_START_ADDR
# define MM_START ((byte*)(CFG_MM_START_ADDR)) /*memory start address*/
#else
# define MM_START _heap /*memory start address*/
static byte _heap[CFG_MM_SIZE];
#endif
static u8 _mm_used = 0xa5;
static mm_t _mms[] = {CFG_MM_BLOCKS};
#if CFG_DEBUG > 0
static void __mm_flag_check(void)
{
block_t bk;
#if PTR_SIZE == 4
bk.u.next = (block_t*)0x19831117L;
__ASSERT(bk.u.used.flags == 0x19);
#elif PTR_SIZE == 3
bk.u.next = (block_t*)0x198311L;
__ASSERT(bk.u.used.flags == 0x19);
#elif PTR_SIZE == 2
bk.u.next = (block_t*)0x1983;
__ASSERT(bk.u.used.flags == 0x19);
#endif
}
#endif
static void __mm_block_init(byte* block_start, mmsz_t size, mmsz_t blocks)
{
register u32 i;
register block_t* bk;
bk = (block_t*)block_start;
for (i = 0; i < blocks - 1; i++) {
bk->u.next = (block_t*)((byte*)bk + size);
bk = bk->u.next;
}
bk->u.next = NULL;
}
static uint __mm_get_page(mmsz_t size)
{
register uint page;
/*add the size of the header */
size += sizeof (block_t);
for (page = 0; page < PAGE_SIZE; page++) {
if (size <= _mms[page].size) {
return page;
}
}
return PAGE_SIZE;
}
void __mm_init(void)
{
register uint i;
register byte* block_start;
#if CFG_DEBUG > 0
__mm_flag_check();
#endif
/*initialize memory used flag*/
_mm_used = MM_USED;
block_start = MM_START;
for (i = 0; i < PAGE_SIZE; i++) {
__mm_block_init(block_start, _mms[i].size, _mms[i].blocks);
_mms[i].firstfree = (block_t*)block_start;
block_start += _mms[i].size * _mms[i].blocks;
_mms[i].nfrees = _mms[i].blocks;
}
}
void* kmalloc(mmsz_t size)
{
register uint page;
register block_t* bk;
__ASSERT(size != 0);
page = __mm_get_page(size);
if (page == PAGE_SIZE) {
return NULL;
}
CRITICAL_ENTER;
if ((bk = _mms[page].firstfree) != NULL) {
_mms[page].firstfree = bk->u.next;
CRITICAL_EXIT;
bk->u.used.page = (u8)(page);
bk->u.used.flags = _mm_used;
return bk + 1; /*increments past header*/
}
CRITICAL_EXIT;
return NULL;
}
void kfree(void* ptr)
{
register uint page;
register block_t* bk;
__ASSERT(ptr != NULL);
bk = (block_t*)ptr - 1;
CRITICAL_ENTER;
if (bk->u.used.flags == _mm_used) {
page = (uint)bk->u.used.page;
bk->u.next = _mms[page].firstfree;
_mms[page].firstfree = bk;
}
CRITICAL_EXIT;
}
err_t mm_status(void)
{
uint i, k;
block_t* bk;
for (i = 0; i < PAGE_SIZE; i++) {
task_lock();
bk = _mms[i].firstfree;
for (k = 0; bk != NULL; k++) {
bk = bk->u.next;
}
task_unlock();
_mms[i].nfrees = k;
}
return EOK;
}
#endif
/*===========================================================================*/