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

📄 mcoutmm.c

📁 rtCell 实时微内核-具有下列功能: 1. 完全抢占的实时微内核结构
💻 C
字号:
/*
 *******************************************************************************
 *                      The real-time kernel "rtCell"                          *
 *              Copyright 2007 taowentao, allrights reserved.                  *
 *----------------------------Modifying from minix-----------------------------*
 * File : mcOutMM.c                                                            *
 * By   : taowentao     2003-05-25                                             *
 *                      2004-12-31                                             *
 *                      2005-08-05                                             *
 *******************************************************************************
 */

#if !defined(MCOUTMM_H)
#include "giCell\mcOSLib\mcOutMM.h"
#endif

/*
 *******************************************************************************
 *                  The Global functions needed by microKernel                 *
 *******************************************************************************
 */

static FMM  hole[NR_HOLES];
static FMM *hole_head = NULL;      /* pointer to first hole             */
static FMM *free_slots = NULL;     /* ptr to list of unused table slots */
static DWORD freeBytes = 0L;

/*
 *******************************************************************************
 *                  The Global functions needed by microKernel                 *
 *******************************************************************************
 */

static void del_slot(FMM *prev_ptr, FMM *hp);
static void merge(FMM *hp);

/*===========================================================================*
 *                              alloc_mem                                    *
 *===========================================================================*/
/* amount of memory requested */
void * _cdecl_ mmAlloc_mem(size_t clicks)
{
    /* Allocate a block of memory from the free list using first fit. The block
     * consists of a sequence of contiguous bytes, whose length in clicks is
     * given by 'clicks'.  A pointer to the block is returned.  The block is
     * always on a click boundary.  This procedure is called when memory is
     * needed for FORK or EXEC.
     */
     
    FMM *hp, *prev_ptr;
    void *old_base;

    hp = hole_head;
    prev_ptr = NIL_HOLE;
    while (hp != NIL_HOLE) {

        if (hp->h_len >= clicks) {
            /* We found a hole that is big enough.  Use it. */
            old_base = hp->h_base;  /* remember where it started */
            hp->h_base += clicks;   /* bite a piece off */
            hp->h_len -= clicks;    /* ditto */
            freeBytes -= clicks;
            
            /* The entire hole has been used up.  Manipulate free list. */
            if (hp->h_len == 0) del_slot(prev_ptr, hp);
            return old_base;
        }

        prev_ptr = hp;
        hp = hp->h_next;
    }
    
    return NULL;
}

/*===========================================================================*
 *                              free_mem                                     *
 *===========================================================================*/
/* base address of block to free */
/* number of clicks to free */
void _cdecl_ mmFree_mem(BYTE *base, size_t clicks)
{
    /* Return a block of free memory to the hole list.  The parameters tell where
     * the block starts in physical memory and how big it is.  The block is added
     * to the hole list.  If it is contiguous with an existing hole on either end,
     * it is merged with the hole or holes.
     */ 
    FMM *hp, *new_ptr, *prev_ptr;

    if (clicks == 0) return;
    freeBytes += clicks;
    
    new_ptr = free_slots;
    prev_ptr = NULL;
    if (new_ptr == NIL_HOLE)
        puts("free_mem: Hole table full");
        
    new_ptr->h_base = base;
    new_ptr->h_len = clicks;
    free_slots = new_ptr->h_next;
    hp = hole_head;

    /* If this block's address is numerically less than the lowest hole currently
     * available, or if no holes are currently available, put this hole on the
     * front of the hole list.
     */
    if (hp == NIL_HOLE || base <= hp->h_base) {
        /* Block to be freed goes on front of the hole list. */
        new_ptr->h_next = hp;
        hole_head = new_ptr;
        merge(new_ptr);
        return;
    }

    /* Block to be returned does not go on front of hole list. */
    while (hp != NIL_HOLE && base > hp->h_base) {
        prev_ptr = hp;
        hp = hp->h_next;
    }

    /* We found where it goes.  Insert block after 'prev_ptr'. */
    new_ptr->h_next = prev_ptr->h_next;
    prev_ptr->h_next = new_ptr;
    merge(prev_ptr);              /* sequence is 'prev_ptr', 'new_ptr', 'hp' */
}

/*===========================================================================*
 *                              del_slot                                     *
 *===========================================================================*/
/* pointer to hole entry just ahead of 'hp' */
/* pointer to hole entry to be removed */
static void del_slot(FMM *prev_ptr, FMM *hp)
{
    /* Remove an entry from the hole list.  This procedure is called when a
     * request to allocate memory removes a hole in its entirety, thus reducing
     * the numbers of holes in memory, and requiring the elimination of one
     * entry in the hole list.
     */

    if(hp == hole_head)
        hole_head = hp->h_next;
    else
        prev_ptr->h_next = hp->h_next;

    hp->h_next = free_slots;
    free_slots = hp;
}

/*===========================================================================*
 *                              merge                                        *
 *===========================================================================*/
/* ptr to hole to merge with its successors */
static void merge(FMM *hp)
{
    /* Check for contiguous holes and merge any found.  Contiguous holes can occur
     * when a block of memory is freed, and it happens to abut another hole on
     * either or both ends.  The pointer 'hp' points to the first of a series of
     * three holes that can potentially all be merged together.
     */

    FMM *next_ptr = hp->h_next;

    /* If 'hp' points to the last hole, no merging is possible.  If it does not,
     * try to absorb its successor into it and free the successor's table entry.
     */
    if (next_ptr == NIL_HOLE) return;
    if (hp->h_base + hp->h_len == next_ptr->h_base) {
        hp->h_len += next_ptr->h_len;   /* first one gets second one's mem */
        del_slot(hp, next_ptr);
    } else {
        hp = next_ptr;
    }

    /* If 'hp' now points to the last hole, return; otherwise, try to absorb its
     * successor into it.
     */
    next_ptr = hp->h_next;
    if (next_ptr == NIL_HOLE) return;
    if (hp->h_base + hp->h_len == next_ptr->h_base) {
        hp->h_len += next_ptr->h_len;
        del_slot(hp, next_ptr);
    }
}

/*===========================================================================*
 *                              mem_init                                     *
 *===========================================================================*/

static void mmMem_init(void)
{
    /* Initialize hole lists.  There are two lists: 'hole_head' points to a linked
     * list of all the holes (unused memory) in the system; 'free_slots' points to
     * a linked list of table entries that are not in use.  Initially, the former
     * list has one entry for each chunk of physical memory, and the second
     * list links together the remaining table slots.  As memory becomes more
     * fragmented in the course of time (i.e., the initial big holes break up into
     * smaller holes), new table slots are needed to represent them.  These slots
     * are taken from the list headed by 'free_slots'.
     */
    
    FMM  *hp;    
    
    /* Put all holes on the free list. */
    for (hp = &hole[0]; hp < &hole[NR_HOLES]; hp++)
        hp->h_next = (hp + 1);
        
    hole[NR_HOLES-1].h_next = NIL_HOLE;
    hole_head = NIL_HOLE;
    free_slots = &hole[0];
    freeBytes = 0L;
}

/*
 *******************************************************************************
 *                  The Global functions needed by microKernel                 *
 *******************************************************************************
 */

void _cdecl_ mmAddToMemPool(BYTE *base, size_t size)
{
    /* Ask the kernel for chunks of physical memory and allocate a hole for
     * each of them.  The SYS_MEM call responds with the base and size of the
     * next chunk and the total amount of memory.
     */
    mmFree_mem(base, size);
}

/******************************************************************************/

void _cdecl_ mmMemoryInit(BYTE *base, size_t size)
{
    mmMem_init();
    mmAddToMemPool(base, size);
    /* base = mcFreeMemory; */
    /* size = VALID_FREE_MEM_SIZE; */
    /* free_mem(base, size); */
}

DWORD _cdecl_ mmGetFreeMemorySize(void)
{
    return (freeBytes);
}
/******************************************************************************/


⌨️ 快捷键说明

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