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 
 
 
/*===========================================================================*/