An update.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@1597 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
88098ab5d3
commit
c877a06196
4 changed files with 229 additions and 8 deletions
120
plugins/memory.c
Normal file
120
plugins/memory.c
Normal file
|
@ -0,0 +1,120 @@
|
|||
//a qvm compatable malloc/free interface
|
||||
|
||||
//This is seperate from qvm_api.c because this has a chunk of memory that simply isn't needed in all plugins.
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
struct memhead_s
|
||||
{
|
||||
int size;
|
||||
int isfree;
|
||||
struct memhead_s *next;
|
||||
struct memhead_s *prev;
|
||||
};
|
||||
|
||||
#ifndef MEMSIZE
|
||||
#define MEMSIZE 1024*64 //64kb
|
||||
#endif
|
||||
|
||||
static struct memhead_s *head;
|
||||
static char memory[MEMSIZE];
|
||||
|
||||
//we create two dummies at the start and end
|
||||
//these will never be freed
|
||||
//we then have dynamic allocation in the middle.
|
||||
//sizes include the headers
|
||||
|
||||
void *malloc(int size)
|
||||
{
|
||||
struct memhead_s *lasthead;
|
||||
|
||||
if (size <= 0)
|
||||
return NULL;
|
||||
|
||||
size = ((size+4) & 3) + sizeof(struct memhead_s); //round up
|
||||
if (!head)
|
||||
{ //first call
|
||||
struct memhead_s *last;
|
||||
struct memhead_s *middle;
|
||||
struct memhead_s *first;
|
||||
|
||||
first = (struct memhead_s*)memory;
|
||||
last= (struct memhead_s*)((char*)memory - sizeof(struct memhead_s));
|
||||
first->size = last->size = sizeof(struct memhead_s);
|
||||
first->isfree = last->isfree = false;
|
||||
|
||||
middle = (struct memhead_s*)((char*)first+first->size);
|
||||
middle->size = sizeof(memory) - sizeof(struct memhead_s)*3;
|
||||
middle->isfree = true;
|
||||
|
||||
last->next = first;
|
||||
last->prev = middle;
|
||||
first->next = middle;
|
||||
first->prev = last;
|
||||
middle->next = last;
|
||||
middle->prev = first;
|
||||
|
||||
head = middle;
|
||||
}
|
||||
lasthead = head;
|
||||
|
||||
do
|
||||
{
|
||||
if (head->isfree)
|
||||
if (head->size >= size)
|
||||
{
|
||||
if (head->size > size + sizeof(struct memhead_s)+1)
|
||||
{ //split
|
||||
struct memhead_s *split;
|
||||
split = (struct memhead_s*)((char*)head + size);
|
||||
split->size = head->size - size;
|
||||
head->size = size;
|
||||
split->next = head->next;
|
||||
split->prev = head;
|
||||
head->next = split;
|
||||
split->next->prev = split;
|
||||
split->isfree = true;
|
||||
head->isfree = false;
|
||||
}
|
||||
else
|
||||
{ //no point in splitting
|
||||
head->isfree = false;
|
||||
}
|
||||
|
||||
return (char*)head + sizeof(struct memhead_s);
|
||||
}
|
||||
head = head->next;
|
||||
} while (lasthead != head);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct memhead_s *mergeblock(struct memhead_s *b1, struct memhead_s *b2)
|
||||
{
|
||||
//b1 and b2 must be in logical order
|
||||
|
||||
b1->next = b2->next;
|
||||
b2->next->prev = b1;
|
||||
b1->size += b2->size;
|
||||
|
||||
return b1;
|
||||
}
|
||||
|
||||
void free(void *mem)
|
||||
{ //the foot hopefully isn't going to be freed
|
||||
struct memhead_s *block;
|
||||
block = (struct memhead_s*)((char*)mem - sizeof(struct memhead_s));
|
||||
|
||||
if (block->isfree)
|
||||
Sys_Error("(plugin) Double free\n");
|
||||
block->isfree = true;
|
||||
|
||||
if (block->prev->isfree)
|
||||
{ //merge previous with this
|
||||
block = mergeblock(block->prev, block);
|
||||
}
|
||||
if (block->next)
|
||||
{ //merge next with this
|
||||
block = mergeblock(block, block->next);
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue