LCOV - code coverage report
Current view: directory - media/libnestegg/src - halloc.c (source / functions) Found Hit Coverage
Test: app.info Lines: 84 0 0.0 %
Date: 2012-06-02 Functions: 11 0 0.0 %

       1                 : /*
       2                 :  *      Copyright (c) 2004i-2010 Alex Pankratov. All rights reserved.
       3                 :  *
       4                 :  *      Hierarchical memory allocator, 1.2.1
       5                 :  *      http://swapped.cc/halloc
       6                 :  */
       7                 : 
       8                 : /*
       9                 :  *      The program is distributed under terms of BSD license. 
      10                 :  *      You can obtain the copy of the license by visiting:
      11                 :  *      
      12                 :  *      http://www.opensource.org/licenses/bsd-license.php
      13                 :  */
      14                 : 
      15                 : #include <stdlib.h>  /* realloc */
      16                 : #include <string.h>  /* memset & co */
      17                 : 
      18                 : #include "halloc.h"
      19                 : #include "align.h"
      20                 : #include "hlist.h"
      21                 : 
      22                 : /*
      23                 :  *      block control header
      24                 :  */
      25                 : typedef struct hblock
      26                 : {
      27                 : #ifndef NDEBUG
      28                 : #define HH_MAGIC    0x20040518L
      29                 :         long          magic;
      30                 : #endif
      31                 :         hlist_item_t  siblings; /* 2 pointers */
      32                 :         hlist_head_t  children; /* 1 pointer  */
      33                 :         max_align_t   data[1];  /* not allocated, see below */
      34                 :         
      35                 : } hblock_t;
      36                 : 
      37                 : #define sizeof_hblock offsetof(hblock_t, data)
      38                 : 
      39                 : /*
      40                 :  *
      41                 :  */
      42                 : realloc_t halloc_allocator = NULL;
      43                 : 
      44                 : #define allocator halloc_allocator
      45                 : 
      46                 : /*
      47                 :  *      static methods
      48                 :  */
      49                 : static void _set_allocator(void);
      50                 : static void * _realloc(void * ptr, size_t n);
      51                 : 
      52                 : static int  _relate(hblock_t * b, hblock_t * p);
      53                 : static void _free_children(hblock_t * p);
      54                 : 
      55                 : /*
      56                 :  *      Core API
      57                 :  */
      58               0 : void * halloc(void * ptr, size_t len)
      59                 : {
      60                 :         hblock_t * p;
      61                 : 
      62                 :         /* set up default allocator */
      63               0 :         if (! allocator)
      64                 :         {
      65               0 :                 _set_allocator();
      66               0 :                 assert(allocator);
      67                 :         }
      68                 : 
      69                 :         /* calloc */
      70               0 :         if (! ptr)
      71                 :         {
      72               0 :                 if (! len)
      73               0 :                         return NULL;
      74                 : 
      75               0 :                 p = allocator(0, len + sizeof_hblock);
      76               0 :                 if (! p)
      77               0 :                         return NULL;
      78                 : #ifndef NDEBUG
      79               0 :                 p->magic = HH_MAGIC;
      80                 : #endif
      81               0 :                 hlist_init(&p->children);
      82               0 :                 hlist_init_item(&p->siblings);
      83                 : 
      84               0 :                 return p->data;
      85                 :         }
      86                 : 
      87               0 :         p = structof(ptr, hblock_t, data);
      88               0 :         assert(p->magic == HH_MAGIC);
      89                 : 
      90                 :         /* realloc */
      91               0 :         if (len)
      92                 :         {
      93               0 :                 p = allocator(p, len + sizeof_hblock);
      94               0 :                 if (! p)
      95               0 :                         return NULL;
      96                 : 
      97               0 :                 hlist_relink(&p->siblings);
      98               0 :                 hlist_relink_head(&p->children);
      99                 :                 
     100               0 :                 return p->data;
     101                 :         }
     102                 : 
     103                 :         /* free */
     104               0 :         _free_children(p);
     105               0 :         hlist_del(&p->siblings);
     106               0 :         allocator(p, 0);
     107                 : 
     108               0 :         return NULL;
     109                 : }
     110                 : 
     111               0 : void hattach(void * block, void * parent)
     112                 : {
     113                 :         hblock_t * b, * p;
     114                 :         
     115               0 :         if (! block)
     116                 :         {
     117               0 :                 assert(! parent);
     118               0 :                 return;
     119                 :         }
     120                 : 
     121                 :         /* detach */
     122               0 :         b = structof(block, hblock_t, data);
     123               0 :         assert(b->magic == HH_MAGIC);
     124                 : 
     125               0 :         hlist_del(&b->siblings);
     126                 : 
     127               0 :         if (! parent)
     128               0 :                 return;
     129                 : 
     130                 :         /* attach */
     131               0 :         p = structof(parent, hblock_t, data);
     132               0 :         assert(p->magic == HH_MAGIC);
     133                 :         
     134                 :         /* sanity checks */
     135               0 :         assert(b != p);          /* trivial */
     136               0 :         assert(! _relate(p, b)); /* heavy ! */
     137                 : 
     138               0 :         hlist_add(&p->children, &b->siblings);
     139                 : }
     140                 : 
     141                 : /*
     142                 :  *      malloc/free api
     143                 :  */
     144               0 : void * h_malloc(size_t len)
     145                 : {
     146               0 :         return halloc(0, len);
     147                 : }
     148                 : 
     149               0 : void * h_calloc(size_t n, size_t len)
     150                 : {
     151               0 :         void * ptr = halloc(0, len*=n);
     152               0 :         return ptr ? memset(ptr, 0, len) : NULL;
     153                 : }
     154                 : 
     155               0 : void * h_realloc(void * ptr, size_t len)
     156                 : {
     157               0 :         return halloc(ptr, len);
     158                 : }
     159                 : 
     160               0 : void   h_free(void * ptr)
     161                 : {
     162               0 :         halloc(ptr, 0);
     163               0 : }
     164                 : 
     165               0 : char * h_strdup(const char * str)
     166                 : {
     167               0 :         size_t len = strlen(str);
     168               0 :         char * ptr = halloc(0, len + 1);
     169               0 :         return ptr ? (ptr[len] = 0, memcpy(ptr, str, len)) : NULL;
     170                 : }
     171                 : 
     172                 : /*
     173                 :  *      static stuff
     174                 :  */
     175               0 : static void _set_allocator(void)
     176                 : {
     177                 :         void * p;
     178               0 :         assert(! allocator);
     179                 :         
     180                 :         /*
     181                 :          *      the purpose of the test below is to check the behaviour
     182                 :          *      of realloc(ptr, 0), which is defined in the standard
     183                 :          *      as an implementation-specific. if it returns zero,
     184                 :          *      then it's equivalent to free(). it can however return
     185                 :          *      non-zero, in which case it cannot be used for freeing
     186                 :          *      memory blocks and we'll need to supply our own version
     187                 :          *
     188                 :          *      Thanks to Stan Tobias for pointing this tricky part out.
     189                 :          */
     190               0 :         allocator = realloc;
     191               0 :         if (! (p = malloc(1)))
     192                 :                 /* hmm */
     193               0 :                 return;
     194                 :                 
     195               0 :         if ((p = realloc(p, 0)))
     196                 :         {
     197                 :                 /* realloc cannot be used as free() */
     198               0 :                 allocator = _realloc;
     199               0 :                 free(p);
     200                 :         }
     201                 : }
     202                 : 
     203               0 : static void * _realloc(void * ptr, size_t n)
     204                 : {
     205                 :         /*
     206                 :          *      free'ing realloc()
     207                 :          */
     208               0 :         if (n)
     209               0 :                 return realloc(ptr, n);
     210               0 :         free(ptr);
     211               0 :         return NULL;
     212                 : }
     213                 : 
     214               0 : static int _relate(hblock_t * b, hblock_t * p)
     215                 : {
     216                 :         hlist_item_t * i;
     217                 : 
     218               0 :         if (!b || !p)
     219               0 :                 return 0;
     220                 : 
     221                 :         /* 
     222                 :          *  since there is no 'parent' pointer, which would've allowed
     223                 :          *  O(log(n)) upward traversal, the check must use O(n) downward 
     224                 :          *  iteration of the entire hierarchy; and this can be VERY SLOW
     225                 :          */
     226               0 :         hlist_for_each(i, &p->children)
     227                 :         {
     228               0 :                 hblock_t * q = structof(i, hblock_t, siblings);
     229               0 :                 if (q == b || _relate(b, q))
     230               0 :                         return 1;
     231                 :         }
     232               0 :         return 0;
     233                 : }
     234                 : 
     235               0 : static void _free_children(hblock_t * p)
     236                 : {
     237                 :         hlist_item_t * i, * tmp;
     238                 :         
     239                 : #ifndef NDEBUG
     240                 :         /*
     241                 :          *      this catches loops in hierarchy with almost zero 
     242                 :          *      overhead (compared to _relate() running time)
     243                 :          */
     244               0 :         assert(p && p->magic == HH_MAGIC);
     245               0 :         p->magic = 0; 
     246                 : #endif
     247               0 :         hlist_for_each_safe(i, tmp, &p->children)
     248                 :         {
     249               0 :                 hblock_t * q = structof(i, hblock_t, siblings);
     250               0 :                 _free_children(q);
     251               0 :                 allocator(q, 0);
     252                 :         }
     253               0 : }
     254                 : 

Generated by: LCOV version 1.7