This commit is contained in:
j 2010-05-23 00:15:58 +02:00
commit 6b297cd037
9 changed files with 2790 additions and 0 deletions

14
src/halloc/Makefile Normal file
View file

@ -0,0 +1,14 @@
CFLAGS = -I. -ansi -Wall -pedantic
LIBNAME = libhalloc.a
OBJS = src/halloc.o
$(LIBNAME): $(OBJS)
ar rcs $(LIBNAME) $(OBJS)
install: $(LIBNAME)
cp halloc.h /usr/include
cp $(LIBNAME) /usr/lib
clean:
rm -f $(LIBNAME) $(OBJS)

45
src/halloc/README Normal file
View file

@ -0,0 +1,45 @@
halloc 1.2.1
============
Hierarchical memory heap interface - an extension to standard
malloc/free interface that simplifies tasks of memory disposal
when allocated structures exhibit hierarchical properties.
http://swapped.cc/halloc
=
To build libhalloc.a with GNU tools run
make
To install in /usr/include and /usr/lib
make install
To cleanup the build files
make clean
=
halloc-1.2.1
* fixed a double-free bug in _set_allocator() as per
Matthew Gregan comments
* switched to using NULL instead of 0 where applicable
halloc-1.2.0
* added missing <string.h> include to halloc.c
* improved standard compliance thanks to the feedback
received from Stan Tobias. Two things were fixed -
- hblock_t structure no longer uses zero-sized 'data'
array, which happened to be common, but non-standard
extension;
- secondly, added the code to test the behaviour of
realloc(ptr, 0). Standard allows it NOT to act as
free(), in which case halloc will use its own version
of allocator calling free() when neccessary.
halloc-1.1.0
* initial public release (rewrite of hhmalloc library)
=============================================================================
Copyright (c) 2004-2010, Alex Pankratov (ap@swapped.cc). All rights reserved.

43
src/halloc/halloc.h Normal file
View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
*
* Hierarchical memory allocator, 1.2.1
* http://swapped.cc/halloc
*/
/*
* The program is distributed under terms of BSD license.
* You can obtain the copy of the license by visiting:
*
* http://www.opensource.org/licenses/bsd-license.php
*/
#ifndef _LIBP_HALLOC_H_
#define _LIBP_HALLOC_H_
#include <stddef.h> /* size_t */
/*
* Core API
*/
void * halloc (void * block, size_t len);
void hattach(void * block, void * parent);
/*
* standard malloc/free api
*/
void * h_malloc (size_t len);
void * h_calloc (size_t n, size_t len);
void * h_realloc(void * p, size_t len);
void h_free (void * p);
char * h_strdup (const char * str);
/*
* the underlying allocator
*/
typedef void * (* realloc_t)(void * ptr, size_t len);
extern realloc_t halloc_allocator;
#endif

36
src/halloc/src/align.h Normal file
View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
*
* Hierarchical memory allocator, 1.2.1
* http://swapped.cc/halloc
*/
/*
* The program is distributed under terms of BSD license.
* You can obtain the copy of the license by visiting:
*
* http://www.opensource.org/licenses/bsd-license.php
*/
#ifndef _LIBP_ALIGN_H_
#define _LIBP_ALIGN_H_
/*
* a type with the most strict alignment requirements
*/
union max_align
{
char c;
short s;
long l;
int i;
float f;
double d;
void * v;
void (*q)(void);
};
typedef union max_align max_align_t;
#endif

254
src/halloc/src/halloc.c Normal file
View file

@ -0,0 +1,254 @@
/*
* Copyright (c) 2004i-2010 Alex Pankratov. All rights reserved.
*
* Hierarchical memory allocator, 1.2.1
* http://swapped.cc/halloc
*/
/*
* The program is distributed under terms of BSD license.
* You can obtain the copy of the license by visiting:
*
* http://www.opensource.org/licenses/bsd-license.php
*/
#include <stdlib.h> /* realloc */
#include <string.h> /* memset & co */
#include "halloc.h"
#include "align.h"
#include "hlist.h"
/*
* block control header
*/
typedef struct hblock
{
#ifndef NDEBUG
#define HH_MAGIC 0x20040518L
long magic;
#endif
hlist_item_t siblings; /* 2 pointers */
hlist_head_t children; /* 1 pointer */
max_align_t data[1]; /* not allocated, see below */
} hblock_t;
#define sizeof_hblock offsetof(hblock_t, data)
/*
*
*/
realloc_t halloc_allocator = NULL;
#define allocator halloc_allocator
/*
* static methods
*/
static void _set_allocator(void);
static void * _realloc(void * ptr, size_t n);
static int _relate(hblock_t * b, hblock_t * p);
static void _free_children(hblock_t * p);
/*
* Core API
*/
void * halloc(void * ptr, size_t len)
{
hblock_t * p;
/* set up default allocator */
if (! allocator)
{
_set_allocator();
assert(allocator);
}
/* calloc */
if (! ptr)
{
if (! len)
return NULL;
p = allocator(0, len + sizeof_hblock);
if (! p)
return NULL;
#ifndef NDEBUG
p->magic = HH_MAGIC;
#endif
hlist_init(&p->children);
hlist_init_item(&p->siblings);
return p->data;
}
p = structof(ptr, hblock_t, data);
assert(p->magic == HH_MAGIC);
/* realloc */
if (len)
{
p = allocator(p, len + sizeof_hblock);
if (! p)
return NULL;
hlist_relink(&p->siblings);
hlist_relink_head(&p->children);
return p->data;
}
/* free */
_free_children(p);
hlist_del(&p->siblings);
allocator(p, 0);
return NULL;
}
void hattach(void * block, void * parent)
{
hblock_t * b, * p;
if (! block)
{
assert(! parent);
return;
}
/* detach */
b = structof(block, hblock_t, data);
assert(b->magic == HH_MAGIC);
hlist_del(&b->siblings);
if (! parent)
return;
/* attach */
p = structof(parent, hblock_t, data);
assert(p->magic == HH_MAGIC);
/* sanity checks */
assert(b != p); /* trivial */
assert(! _relate(p, b)); /* heavy ! */
hlist_add(&p->children, &b->siblings);
}
/*
* malloc/free api
*/
void * h_malloc(size_t len)
{
return halloc(0, len);
}
void * h_calloc(size_t n, size_t len)
{
void * ptr = halloc(0, len*=n);
return ptr ? memset(ptr, 0, len) : NULL;
}
void * h_realloc(void * ptr, size_t len)
{
return halloc(ptr, len);
}
void h_free(void * ptr)
{
halloc(ptr, 0);
}
char * h_strdup(const char * str)
{
size_t len = strlen(str);
char * ptr = halloc(0, len + 1);
return ptr ? (ptr[len] = 0, memcpy(ptr, str, len)) : NULL;
}
/*
* static stuff
*/
static void _set_allocator(void)
{
void * p;
assert(! allocator);
/*
* the purpose of the test below is to check the behaviour
* of realloc(ptr, 0), which is defined in the standard
* as an implementation-specific. if it returns zero,
* then it's equivalent to free(). it can however return
* non-zero, in which case it cannot be used for freeing
* memory blocks and we'll need to supply our own version
*
* Thanks to Stan Tobias for pointing this tricky part out.
*/
allocator = realloc;
if (! (p = malloc(1)))
/* hmm */
return;
if ((p = realloc(p, 0)))
{
/* realloc cannot be used as free() */
allocator = _realloc;
free(p);
}
}
static void * _realloc(void * ptr, size_t n)
{
/*
* free'ing realloc()
*/
if (n)
return realloc(ptr, n);
free(ptr);
return NULL;
}
static int _relate(hblock_t * b, hblock_t * p)
{
hlist_item_t * i;
if (!b || !p)
return 0;
/*
* since there is no 'parent' pointer, which would've allowed
* O(log(n)) upward traversal, the check must use O(n) downward
* iteration of the entire hierarchy; and this can be VERY SLOW
*/
hlist_for_each(i, &p->children)
{
hblock_t * q = structof(i, hblock_t, siblings);
if (q == b || _relate(b, q))
return 1;
}
return 0;
}
static void _free_children(hblock_t * p)
{
hlist_item_t * i, * tmp;
#ifndef NDEBUG
/*
* this catches loops in hierarchy with almost zero
* overhead (compared to _relate() running time)
*/
assert(p && p->magic == HH_MAGIC);
p->magic = 0;
#endif
hlist_for_each_safe(i, tmp, &p->children)
{
hblock_t * q = structof(i, hblock_t, siblings);
_free_children(q);
allocator(q, 0);
}
}

136
src/halloc/src/hlist.h Normal file
View file

@ -0,0 +1,136 @@
/*
* Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
*
* Hierarchical memory allocator, 1.2.1
* http://swapped.cc/halloc
*/
/*
* The program is distributed under terms of BSD license.
* You can obtain the copy of the license by visiting:
*
* http://www.opensource.org/licenses/bsd-license.php
*/
#ifndef _LIBP_HLIST_H_
#define _LIBP_HLIST_H_
#include <assert.h>
#include "macros.h" /* static_inline */
/*
* weak double-linked list w/ tail sentinel
*/
typedef struct hlist_head hlist_head_t;
typedef struct hlist_item hlist_item_t;
/*
*
*/
struct hlist_head
{
hlist_item_t * next;
};
struct hlist_item
{
hlist_item_t * next;
hlist_item_t ** prev;
};
/*
* shared tail sentinel
*/
struct hlist_item hlist_null;
/*
*
*/
#define __hlist_init(h) { &hlist_null }
#define __hlist_init_item(i) { &hlist_null, &(i).next }
static_inline void hlist_init(hlist_head_t * h);
static_inline void hlist_init_item(hlist_item_t * i);
/* static_inline void hlist_purge(hlist_head_t * h); */
/* static_inline bool_t hlist_empty(const hlist_head_t * h); */
/* static_inline hlist_item_t * hlist_head(const hlist_head_t * h); */
/* static_inline hlist_item_t * hlist_next(const hlist_item_t * i); */
/* static_inline hlist_item_t * hlist_prev(const hlist_item_t * i,
const hlist_head_t * h); */
static_inline void hlist_add(hlist_head_t * h, hlist_item_t * i);
/* static_inline void hlist_add_prev(hlist_item_t * l, hlist_item_t * i); */
/* static_inline void hlist_add_next(hlist_item_t * l, hlist_item_t * i); */
static_inline void hlist_del(hlist_item_t * i);
static_inline void hlist_relink(hlist_item_t * i);
static_inline void hlist_relink_head(hlist_head_t * h);
#define hlist_for_each(i, h) \
for (i = (h)->next; i != &hlist_null; i = i->next)
#define hlist_for_each_safe(i, tmp, h) \
for (i = (h)->next, tmp = i->next; \
i!= &hlist_null; \
i = tmp, tmp = i->next)
/*
* static
*/
static_inline void hlist_init(hlist_head_t * h)
{
assert(h);
h->next = &hlist_null;
}
static_inline void hlist_init_item(hlist_item_t * i)
{
assert(i);
i->prev = &i->next;
i->next = &hlist_null;
}
static_inline void hlist_add(hlist_head_t * h, hlist_item_t * i)
{
hlist_item_t * next;
assert(h && i);
next = i->next = h->next;
next->prev = &i->next;
h->next = i;
i->prev = &h->next;
}
static_inline void hlist_del(hlist_item_t * i)
{
hlist_item_t * next;
assert(i);
next = i->next;
next->prev = i->prev;
*i->prev = next;
hlist_init_item(i);
}
static_inline void hlist_relink(hlist_item_t * i)
{
assert(i);
*i->prev = i;
i->next->prev = &i->next;
}
static_inline void hlist_relink_head(hlist_head_t * h)
{
assert(h);
h->next->prev = &h->next;
}
#endif

36
src/halloc/src/macros.h Normal file
View file

@ -0,0 +1,36 @@
/*
* Copyright (c) 2004-2010 Alex Pankratov. All rights reserved.
*
* Hierarchical memory allocator, 1.2.1
* http://swapped.cc/halloc
*/
/*
* The program is distributed under terms of BSD license.
* You can obtain the copy of the license by visiting:
*
* http://www.opensource.org/licenses/bsd-license.php
*/
#ifndef _LIBP_MACROS_H_
#define _LIBP_MACROS_H_
#include <stddef.h> /* offsetof */
/*
restore pointer to the structure by a pointer to its field
*/
#define structof(p,t,f) ((t*)(- offsetof(t,f) + (char*)(p)))
/*
* redefine for the target compiler
*/
#ifdef _WIN32
#define static_inline static __inline
#else
#define static_inline static __inline__
#endif
#endif