A task management system. At least this was the initial idea. Basically this it the base code for the taskrambler framework.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

173 lines
4.2 KiB

/**
* \file This holds all stufff related our memory managent.
* I try the best as far as I can to reduce memory fragmentation
* and unneccessary calls to alloc and free.
*
* To achive this I try an approach described here as "Quick Fit".
* http://www.flounder.com/memory_allocation.htm
*
* The basic idea is to keep allocated memory segments and don't free
* them again. Instead I will put them in a tree indexed by their size.
* To get new memory I first have a look in the tree if there is
* a fitting memory segment. Fitting mean, larger or exactly the size
* I need. If there is one, use it. If not create a new one using
* usual malloc approach.
* I won't split the reagions at all because most likely they will be
* free soon again. This way I might waste some memory, so I have to
* keep an eye on this.
*
* Right now I don't build an upper limit for allocation. The limit
* still is the system memory itself.
*
* This is not implemented as a class because it will be used in the
* process of object creation.
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2012 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <search.h>
#include "utils/memory.h"
struct memSegment {
size_t size;
void * ptr;
};
void * segments = NULL;
/**
* this will interpret any memory segment that is not smaller
* than the expected size as fitting.
*
* @param void * size_ptr a pointer to a size_t value searched for
* @param void * subject a pointer to the currently analysed tree element
*/
static
int
segmentFindCmp(const void * size_ptr, const void * subject)
{
if (*(size_t *)size_ptr > ((struct memSegment *)subject)->size)
return 1;
return 0;
}
/**
* this returns exact fits....uhh.....I can't relate solely on
* the size argument as then same sized segments will never
* be stored.
* Maybe a tree is not the best data structure to use to store
* these.
* Anyway, right now take the ptr into account if size if equal.
*/
static
int
segmentSearchCmp(const void * search, const void * subject)
{
size_t idx =
((struct memSegment *)search)->size -
((struct memSegment *)subject)->size;
if (0 == idx) {
return
((struct memSegment *)search)->ptr -
((struct memSegment *)subject)->ptr;
}
return idx;
}
static
void
segmentFree(void * segment)
{
free(segment);
}
void *
memMalloc(size_t size)
{
struct memSegment ** seg_ptr = tfind(&size, &segments, segmentFindCmp);
struct memSegment * seg;
if (NULL == seg_ptr) {
seg = (struct memSegment *)malloc(sizeof(struct memSegment) + size);
seg->size = size;
seg->ptr = (void *)seg + sizeof(struct memSegment);
} else {
seg = *seg_ptr;
// remove the found one from the tree as we use it now.
tdelete((void *)seg, &segments, segmentSearchCmp);
}
return seg->ptr;
}
/**
* this is a really memory wasting solution....just to be able to
* use calloc, which might be faster then malloc/memset solution.
*
* Maybe this is a bad idea, as we need to memset the buffer anyway
* if it comes from our tree, which hopefully should be the majority
* of cases.
*/
void *
memCalloc(size_t nmemb, size_t size)
{
size_t _size = nmemb * size;
void * mem = memMalloc(_size);
memset(mem, 0, _size);
return mem;
}
void
memFree(void ** mem)
{
if (NULL != *mem) {
tsearch(*mem - sizeof(struct memSegment), &segments, segmentSearchCmp);
*mem = NULL;
}
}
void
memCleanup()
{
tdestroy(segments, segmentFree);
}
void
ffree(void ** data)
{
if (NULL != *data) {
free(*data);
*data = NULL;
}
}
// vim: set ts=4 sw=4: