📄 malloc.c
字号:
#include "eDbInit.h"
#define _CHECK_MEM_
#define NR_HOLES 128 /* max entries in hole table */
#define SIZE_EXTRA 4
#define NIL_HOLE (hole *)0
#define TOHEAD(X) ((u8*)((u32*)(X)-1))
#define TOADDR(X) ((void*)((u32*)X+1))
#define SET_SIZE(P,X) (*((u32 *)P) = X)
#define GET_SIZE(P) (*((u32*)TOHEAD(P)))
#define ROUNDUP(X) ((X+3) & ~3)
#ifdef _CHECK_MEM_
u32 nByteUsedMem = 0;
u32 nByteUsedMemBak = 0;
#endif
#ifndef WIN32
//#define RAM_SIZE 0x1000000 // = 1024*1024*16
//extern u8 Image$$RW$$Limit[];
//extern u8 Image$$RW$$Base[];
//static u8 *raw_mem=&Image$$RW$$Limit[1024];
//#define MAX_DYNAMIC_MEM (Image$$RW$$Base + RAM_SIZE - Image$$RW$$Limit - 1024)
#define MAX_DYNAMIC_MEM 0x100000
static u8 raw_mem[MAX_DYNAMIC_MEM];
#else
#define MAX_DYNAMIC_MEM 0x100000
static u8 raw_mem[MAX_DYNAMIC_MEM];
#endif
typedef struct hole {
u8 *h_base;
u32 h_len;
struct hole *h_next;
} hole;
hole ahole[NR_HOLES];
hole *hole_head; /* pointer to first hole */
hole *free_slots; /* ptr to list of unused table slots */
void del_slot(hole *prev_ptr, hole *hp){
/* prev_ptr: pointer to hole entry just ahead of 'hp' */
/* hp: pointer to hole entry to be removed */
/* 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;
}
void merge(hole *hp)
/* hp: ptr to hole to merge with its successors */
{
hole *next_ptr;
/* 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 = hp->h_next) == 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.
*/
if ( (next_ptr = hp->h_next) == 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);
}
}
void free_mem(void *base){
/* 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.
*/
hole *hp, *new_ptr, *prev_ptr;
u32 nByte;
nByte = GET_SIZE(base);
if (nByte == 0) return;
#ifdef _CHECK_MEM_
if(nByteUsedMemBak < nByteUsedMem){
nByteUsedMemBak = nByteUsedMem;
}
nByteUsedMem -= nByte;
#endif
if ( (new_ptr = free_slots) == NIL_HOLE){
assert(0);
return ;
}
new_ptr->h_base = TOHEAD(base);
new_ptr->h_len = nByte;
free_slots = new_ptr->h_next;
hp = hole_head;
if (hp == NIL_HOLE || TOHEAD(base) <= hp->h_base) {
new_ptr->h_next = hp;
hole_head = new_ptr;
merge(new_ptr);
}else{
while (hp != NIL_HOLE && TOHEAD(base) > hp->h_base) {
prev_ptr = hp;
hp = hp->h_next;
}
new_ptr->h_next = prev_ptr->h_next;
prev_ptr->h_next = new_ptr;
merge(prev_ptr); /* sequence is 'prev_ptr', 'new_ptr', 'hp' */
}
}
void *alloc_mem(u32 nByte){
/* 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.
*/
hole *hp, *prev_ptr;
u8 *base;
hp = hole_head;
nByte += SIZE_EXTRA;
nByte = ROUNDUP(nByte);
while (hp != NIL_HOLE) {
if (hp->h_len >= nByte) {
/* We found a hole that is big enough. Use it. */
nByteUsedMem += nByte;
base = hp->h_base;
hp->h_base += nByte;
hp->h_len -= nByte;
if (hp->h_len != 0){
SET_SIZE(base,nByte);
return TOADDR(base);
}
/* add it to free list*/
del_slot(prev_ptr, hp);
SET_SIZE(base,nByte);
return TOADDR(base);
}
prev_ptr = hp;
hp = hp->h_next;
}
return 0;
}
void *realloc_mem(void *base, u32 nByte){
u8 *ptr;
u32 old_size;
if(base == 0){
return alloc_mem(nByte);
}
if(nByte == 0){
free_mem(base);
return 0;
}
old_size = GET_SIZE(base)-SIZE_EXTRA;
ptr = alloc_mem(nByte+old_size);
if(ptr == 0){
return 0;
}
memcpy(ptr,base,old_size);
free_mem(base);
return ptr;
}
u32 max_hole()
{
/* Scan the hole list and return the largest hole. */
hole *hp;
u32 max;
hp = hole_head;
max = 0;
while (hp != NIL_HOLE) {
if (hp->h_len > max) max = hp->h_len;
hp = hp->h_next;
}
return max;
}
void mem_init(void)
{
hole *hp;
u8 *base = raw_mem;
for (hp = &ahole[0]; hp < &ahole[NR_HOLES]; hp++){
hp->h_len = 0;
hp->h_base = 0;
hp->h_next = hp + 1;
}
ahole[NR_HOLES-1].h_next = NIL_HOLE;
ahole[NR_HOLES-1].h_base = 0;
ahole[NR_HOLES-1].h_len = 0;
hole_head = NIL_HOLE;
free_slots= &ahole[0];
SET_SIZE(base,MAX_DYNAMIC_MEM);
free_mem(TOADDR(base));
#ifdef _CHECK_MEM_
nByteUsedMem = 0;
nByteUsedMemBak = 0;
#endif
}
void check_memory(void){
#ifdef _CHECK_MEM_
hole *hp = hole_head;
hole *fr = free_slots;
fprintf(fdebug,"\nbase mem addr: %x\n",raw_mem);
fprintf(fdebug,"hole_head addr: %x\n",hp);
fprintf(fdebug,"free_slots addr: %x\n",fr);
fprintf(fdebug,"max alloc mem: %x bytes\n",nByteUsedMemBak);
fprintf(fdebug,"unrelease mem: %x bytes\n",nByteUsedMem);
while(hp != NIL_HOLE){
fprintf(fdebug,"hp->h_base: %x\t",hp->h_base);
fprintf(fdebug,"hp->h_len: %x\t",hp->h_len);
fprintf(fdebug,"hp->h_next: %x\n",hp->h_next);
hp = hp->h_next;
}
while(fr != NIL_HOLE && fr->h_len != 0){
fprintf(fdebug,"fr->h_base: %x\t",fr->h_base);
fprintf(fdebug,"fr->h_len: %x\t",fr->h_len);
fprintf(fdebug,"fr->h_next: %x\n",fr->h_next);
fr = fr->h_next;
}
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -