📄 mcoutmm.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 + -